# Vuex
> 原文:[https://docs.gitlab.com/ee/development/fe_guide/vuex.html](https://docs.gitlab.com/ee/development/fe_guide/vuex.html)
* [Separation of concerns](#separation-of-concerns)
* [File structure](#file-structure)
* [`index.js`](#indexjs)
* [`state.js`](#statejs)
* [Access `state` properties](#access-state-properties)
* [`actions.js`](#actionsjs)
* [Dispatching actions](#dispatching-actions)
* [`mutations.js`](#mutationsjs)
* [Naming Pattern: `REQUEST` and `RECEIVE` namespaces](#naming-pattern-request-and-receive-namespaces)
* [Updating complex state](#updating-complex-state)
* [`getters.js`](#gettersjs)
* [`mutation_types.js`](#mutation_typesjs)
* [Initializing a store’s state](#initializing-a-stores-state)
* [Why not just …spread the initial state?](#why-not-just-spread-the-initial-state)
* [Communicating with the Store](#communicating-with-the-store)
* [Vuex Gotchas](#vuex-gotchas)
* [Testing Vuex](#testing-vuex)
* [Testing Vuex concerns](#testing-vuex-concerns)
* [Testing components that need a store](#testing-components-that-need-a-store)
* [Two way data binding](#two-way-data-binding)
# Vuex[](#vuex "Permalink")
如果將狀態管理與組件分離有明顯的好處(例如,由于狀態復雜性),我們建議使用[Vuex 而](https://vuex.vuejs.org)不是其他任何 Flux 模式. 否則,請隨時管理組件中的狀態.
在以下情況下,應強烈考慮 Vuex:
* 您期望應用程序的多個部分對狀態變化做出反應
* 需要在多個組件之間共享數據
* 與后端的交互非常復雜,例如多個 API 調用
* 該應用程序涉及通過傳統 REST API 和 GraphQL 與后端進行交互(尤其是將 REST API 移至 GraphQL 時,這是一項待處理的后端任務)
*注意:以下*所有內容在[Vuex](https://vuex.vuejs.org)官方[文檔](https://vuex.vuejs.org)中有更詳細的[說明](https://vuex.vuejs.org) .
## Separation of concerns[](#separation-of-concerns "Permalink")
Vuex 由狀態,獲取器,變異,動作和模塊組成.
當用戶點擊一個動作時,我們需要`dispatch`它. 此操作將`commit`將更改狀態的突變. *注意:*動作本身不會更新狀態,只有突變可以更新狀態.
## File structure[](#file-structure "Permalink")
在 GitLab 上使用 Vuex 時,請將這些問題分為不同的文件以提高可讀性:
```
└── store
├── index.js # where we assemble modules and export the store
├── actions.js # actions
├── mutations.js # mutations
├── getters.js # getters
├── state.js # state
└── mutation_types.js # mutation types
```
下例顯示了一個列出用戶并將其添加到狀態的應用程序. (有關更復雜的示例實現,請查看[此處](https://gitlab.com/gitlab-org/gitlab/tree/master/ee/app/assets/javascripts/vue_shared/security_reports/store)的安全應用程序商店)
### `index.js`[](#indexjs "Permalink")
這是我們商店的入口點. 您可以使用以下內容作為指導:
```
import Vuex from 'vuex';
import * as actions from './actions';
import * as getters from './getters';
import mutations from './mutations';
import state from './state';
export const createStore = () =>
new Vuex.Store({
actions,
getters,
mutations,
state,
});
```
*注意:*在實施此[RFC](https://gitlab.com/gitlab-org/frontend/rfcs/-/issues/20)之前,以上內容將需要禁用`import/prefer-default-export` ESLint 規則.
### `state.js`[](#statejs "Permalink")
在編寫任何代碼之前,您應該做的第一件事就是設計狀態.
通常,我們需要將數據從 haml 提供給 Vue 應用程序. 讓我們將其存儲在狀態中以便更好地訪問.
```
export default () => ({
endpoint: null,
isLoading: false,
error: null,
isAddingUser: false,
errorAddingUser: false,
users: [],
});
```
#### Access `state` properties[](#access-state-properties "Permalink")
您可以使用`mapState`訪問組件中的狀態屬性.
### `actions.js`[](#actionsjs "Permalink")
An action is a payload of information to send data from our application to our store.
動作通常由`type`和`payload` ,它們描述發生了什么. 與[變種](#mutationsjs)不同,動作可以包含異步操作-這就是為什么我們始終需要在動作中處理異步邏輯.
在此文件中,我們將編寫將調用突變的操作以處理用戶列表:
```
import * as types from './mutation_types';
import axios from '~/lib/utils/axios_utils';
import createFlash from '~/flash';
export const fetchUsers = ({ state, dispatch }) => {
commit(types.REQUEST_USERS);
axios.get(state.endpoint)
.then(({ data }) => commit(types.RECEIVE_USERS_SUCCESS, data))
.catch((error) => {
commit(types.RECEIVE_USERS_ERROR, error)
createFlash('There was an error')
});
}
export const addUser = ({ state, dispatch }, user) => {
commit(types.REQUEST_ADD_USER);
axios.post(state.endpoint, user)
.then(({ data }) => commit(types.RECEIVE_ADD_USER_SUCCESS, data))
.catch((error) => commit(types.REQUEST_ADD_USER_ERROR, error));
}
```
#### Dispatching actions[](#dispatching-actions "Permalink")
要從組件調度動作,請使用`mapActions`幫助器:
```
import { mapActions } from 'vuex';
{
methods: {
...mapActions([
'addUser',
]),
onClickUser(user) {
this.addUser(user);
},
},
};
```
### `mutations.js`[](#mutationsjs "Permalink")
變異指定應用程序狀態如何響應發送到商店的操作而改變. 更改 Vuex 存儲中狀態的唯一方法應該是通過提交突變.
**在編寫任何代碼之前先考慮狀態是一個好主意.**
請記住,動作僅描述發生了某些事情,而沒有描述應用程序狀態如何變化.
**切勿直接從組件提交突變**
相反,您應該創建一個將導致突變的動作.
```
import * as types from './mutation_types';
export default {
[types.REQUEST_USERS](state) {
state.isLoading = true;
},
[types.RECEIVE_USERS_SUCCESS](state, data) {
// Do any needed data transformation to the received payload here
state.users = data;
state.isLoading = false;
},
[types.RECEIVE_USERS_ERROR](state, error) {
state.isLoading = false;
},
[types.REQUEST_ADD_USER](state, user) {
state.isAddingUser = true;
},
[types.RECEIVE_ADD_USER_SUCCESS](state, user) {
state.isAddingUser = false;
state.users.push(user);
},
[types.REQUEST_ADD_USER_ERROR](state, error) {
state.isAddingUser = false;
state.errorAddingUser = error;
},
};
```
#### Naming Pattern: `REQUEST` and `RECEIVE` namespaces[](#naming-pattern-request-and-receive-namespaces "Permalink")
發出請求時,我們通常希望向用戶顯示加載狀態.
與其創建一個突變來切換加載狀態,不如:
1. 類型為`REQUEST_SOMETHING`的突變,以切換加載狀態
2. 類型為`RECEIVE_SOMETHING_SUCCESS`的突變,用于處理成功回調
3. 類型為`RECEIVE_SOMETHING_ERROR`的突變,用于處理錯誤回調
4. 動作`fetchSomething`發出請求并在提到的情況下提交突變
1. 如果您的應用程序執行的不是`GET`請求,則可以使用以下示例:
* `POST` : `createSomething`
* `PUT` : `updateSomething`
* `DELETE` : `deleteSomething`
結果,我們可以從該組件調度`fetchNamespace`操作,它將負責提交`REQUEST_NAMESPACE` , `RECEIVE_NAMESPACE_SUCCESS`和`RECEIVE_NAMESPACE_ERROR`突變.
> 以前,我們是從`fetchNamespace`操作中調度操作,而不是提交突變,所以如果您在代碼庫的較早部分中找到了不同的模式,請不要感到困惑. 但是,無論何時您編寫新的 Vuex 商店,我們都鼓勵利用新模式
通過遵循這種模式,我們保證:
1. 所有應用程序都遵循相同的模式,從而使任何人都更容易維護代碼
2. 應用程序中的所有數據都遵循相同的生命周期模式
3. 單元測試更容易
#### Updating complex state[](#updating-complex-state "Permalink")
有時,尤其是當狀態復雜時,實際上很難遍歷該狀態以精確更新突變需要更新的內容. 理想情況下, `vuex`狀態應盡可能標準化/解耦,但這并非總是如此.
重要的是要記住,當在突變本身中選擇`portion of the mutated state`并對其進行突變時,代碼更易于閱讀和維護.
給定此狀態:
```
export default () => ({
items: [
{
id: 1,
name: 'my_issue',
closed: false,
},
{
id: 2,
name: 'another_issue',
closed: false,
}
]
});
```
像這樣寫一個突變可能很誘人:
```
// Bad
export default {
[types.MARK_AS_CLOSED](state, item) {
Object.assign(item, {closed: true})
}
}
```
盡管此方法有效,但它具有以下依賴性:
* 正確的選擇`item`中的組件/動作.
* `item`屬性已經在`closed`狀態下聲明.
* 新的`confidential`財產將不會產生反應.
* 他指出, `item`是通過引用`items`
這樣寫的突變更難維護,更容易出錯. 我們寧可這樣寫一個變異:
```
// Good
export default {
[types.MARK_AS_CLOSED](state, itemId) {
const item = state.items.find(i => i.id == itemId);
Vue.set(item, 'closed', true)
state.items.splice(index, 1, item)
}
}
```
這種方法更好,因為:
* 它選擇并更新突變中的狀態,這種狀態更易于維護.
* 它沒有外部依賴性,如果傳遞了正確的`itemId`則狀態將正確更新.
* 它沒有反應性警告,因為我們生成了一個新`item`以避免耦合到初始狀態.
這樣寫的變異更容易維護. 另外,我們避免了由于反應系統的限制而導致的錯誤.
### `getters.js`[](#gettersjs "Permalink")
有時我們可能需要根據存儲狀態獲取派生狀態,例如針對特定道具進行過濾. 使用 getter 還將由于依賴關系而緩存結果,這取決于[計算的 props 的工作方式.](https://vuejs.org/v2/guide/computed.html#Computed-Caching-vs-Methods)這可以通過`getters`來完成:
```
// get all the users with pets
export const getUsersWithPets = (state, getters) => {
return state.users.filter(user => user.pet !== undefined);
};
```
要從組件訪問吸氣劑,請使用`mapGetters`幫助器:
```
import { mapGetters } from 'vuex';
{
computed: {
...mapGetters([
'getUsersWithPets',
]),
},
};
```
### `mutation_types.js`[](#mutation_typesjs "Permalink")
來自[vuex 突變文檔](https://vuex.vuejs.org/guide/mutations.html) :>在各種 Flux 實現中,將常數用于突變類型是一種常見的模式. 這使代碼可以利用像 linters 這樣的工具,并將所有常量放在一個文件中,使您的協作者可以快速了解整個應用程序中可能發生的變異.
```
export const ADD_USER = 'ADD_USER';
```
### Initializing a store’s state[](#initializing-a-stores-state "Permalink")
Vuex 存儲通常需要一些初始狀態才能使用其`action` . 通常,這些數據包括 API 端點,文檔 URL 或 ID 之類的數據.
要設置此初始狀態,請在安裝 Vue 組件時將其作為參數傳遞給商店的創建函數:
```
// in the Vue app's initialization script (e.g. mount_show.js)
import Vue from 'vue';
import Vuex from 'vuex';
import { createStore } from './stores';
import AwesomeVueApp from './components/awesome_vue_app.vue'
Vue.use(Vuex);
export default () => {
const el = document.getElementById('js-awesome-vue-app');
return new Vue({
el,
store: createStore(el.dataset),
render: h => h(AwesomeVueApp)
});
};
```
然后,存儲功能可以將此數據傳遞給州的創建功能:
```
// in store/index.js
import * as actions from './actions';
import mutations from './mutations';
import createState from './state';
export default initialState => ({
actions,
mutations,
state: createState(initialState),
});
```
狀態函數可以接受此初始數據作為參數并將其烘焙到返回的`state`對象中:
```
// in store/state.js
export default ({
projectId,
documentationPath,
anOptionalProperty = true
}) => ({
projectId,
documentationPath,
anOptionalProperty,
// other state properties here
});
```
#### Why not just …spread the initial state?[](#why-not-just-spread-the-initial-state "Permalink")
精明的讀者將從上面的示例中看到切出幾行代碼的機會:
```
// Don't do this!
export default initialState => ({
...initialState,
// other state properties here
});
```
我們已經做出有意識的決定,避免使用這種模式,以幫助我們的前端代碼庫實現可發現性和可搜索性. 在[此討論中](https://gitlab.com/gitlab-org/frontend/rfcs/-/issues/56#note_302514865)描述了[這樣做的原因](https://gitlab.com/gitlab-org/frontend/rfcs/-/issues/56#note_302514865) :
> 考慮在存儲狀態中使用了`someStateKey` . 如果僅由`el.dataset`提供,則*可能*無法直接對其進行 grep. 相反,您必須 grep 以獲得`some_state_key` ,因為它可能來自 rails 模板. 反之亦然:如果您正在查看 Rails 模板,您可能想知道是什么使用了`some_state_key` ,但是您*必須* grep 為`someStateKey`
### Communicating with the Store[](#communicating-with-the-store "Permalink")
```
<script>
import { mapActions, mapState, mapGetters } from 'vuex';
export default {
computed: {
...mapGetters([
'getUsersWithPets'
]),
...mapState([
'isLoading',
'users',
'error',
]),
},
methods: {
...mapActions([
'fetchUsers',
'addUser',
]),
onClickAddUser(data) {
this.addUser(data);
}
},
created() {
this.fetchUsers()
}
}
</script> <template>
<ul>
<li v-if="isLoading">
Loading...
</li>
<li v-else-if="error">
{{ error }}
</li>
<template v-else>
<li
v-for="user in users"
:key="user.id"
>
{{ user }}
</li>
</template>
</ul> </template>
```
### Vuex Gotchas[](#vuex-gotchas "Permalink")
1. 不要直接調用突變. 始終使用動作進行突變. 這樣做將在整個應用程序中保持一致性. 從 Vuex 文檔:
> Why don’t we just call store.commit(‘action’) directly? Well, remember that mutations must be synchronous? Actions aren’t. We can perform asynchronous operations inside an action.
```
// component.vue
// bad
created() {
this.$store.commit('mutation');
}
// good
created() {
this.$store.dispatch('action');
}
```
2. 使用變異類型而不是對字符串進行硬編碼. 這將減少出錯的可能性.
3. 在實例化商店的用途之后的所有組件中,都可以訪問 State.
### Testing Vuex[](#testing-vuex "Permalink")
#### Testing Vuex concerns[](#testing-vuex-concerns "Permalink")
有關測試操作,獲取器和突變的信息,請參考[vuex 文檔](https://vuex.vuejs.org/guide/testing.html) .
#### Testing components that need a store[](#testing-components-that-need-a-store "Permalink")
較小的組件可能會使用`store`屬性來訪問數據. 為了編寫這些組件的單元測試,我們需要包括商店并提供正確的狀態:
```
//component_spec.js
import Vue from 'vue';
import Vuex from 'vuex';
import { mount, createLocalVue } from '@vue/test-utils';
import { createStore } from './store';
import Component from './component.vue'
const localVue = createLocalVue();
localVue.use(Vuex);
describe('component', () => {
let store;
let wrapper;
const createComponent = () => {
store = createStore();
wrapper = mount(Component, {
localVue,
store,
});
};
beforeEach(() => {
createComponent();
});
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
it('should show a user', async () => {
const user = {
name: 'Foo',
age: '30',
};
// populate the store
await store.dispatch('addUser', user);
expect(wrapper.text()).toContain(user.name);
});
});
```
### Two way data binding[](#two-way-data-binding "Permalink")
在 Vuex 中存儲表單數據時,有時需要更新存儲的值. 絕對不應直接更改存儲,而應使用操作. 為了在我們的代碼中仍然使用`v-model` ,我們需要以這種形式創建計算屬性:
```
export default {
computed: {
someValue: {
get() {
return this.$store.state.someValue;
},
set(value) {
this.$store.dispatch("setSomeValue", value);
}
}
}
};
```
另一種方法是使用`mapState`和`mapActions` :
```
export default {
computed: {
...mapState(['someValue']),
localSomeValue: {
get() {
return this.someValue;
},
set(value) {
this.setSomeValue(value)
}
}
},
methods: {
...mapActions(['setSomeValue'])
}
};
```
添加其中一些屬性變得很麻煩,并使代碼重復性更高,并需要編寫更多的測試. 為了簡化此操作, `~/vuex_shared/bindings.js`有一個幫助器.
可以像這樣使用助手:
```
// this store is non-functional and only used to give context to the example
export default {
state: {
baz: '',
bar: '',
foo: ''
},
actions: {
updateBar() {...}
updateAll() {...}
},
getters: {
getFoo() {...}
}
}
```
```
import { mapComputed } from '~/vuex_shared/bindings'
export default {
computed: {
/**
* @param {(string[]|Object[])} list - list of string matching state keys or list objects
* @param {string} list[].key - the key matching the key present in the vuex state
* @param {string} list[].getter - the name of the getter, leave it empty to not use a getter
* @param {string} list[].updateFn - the name of the action, leave it empty to use the default action
* @param {string} defaultUpdateFn - the default function to dispatch
* @param {string} root - optional key of the state where to search fo they keys described in list
* @returns {Object} a dictionary with all the computed properties generated
*/
...mapComputed(
[
'baz',
{ key: 'bar', updateFn: 'updateBar' }
{ key: 'foo', getter: 'getFoo' },
],
'updateAll',
),
}
}
```
然后, `mapComputed`將生成適當的計算屬性,這些屬性從存儲中獲取數據并在更新時調度正確的操作.
- GitLab Docs
- Installation
- Requirements
- GitLab cloud native Helm Chart
- Install GitLab with Docker
- Installation from source
- Install GitLab on Microsoft Azure
- Installing GitLab on Google Cloud Platform
- Installing GitLab on Amazon Web Services (AWS)
- Analytics
- Code Review Analytics
- Productivity Analytics
- Value Stream Analytics
- Kubernetes clusters
- Adding and removing Kubernetes clusters
- Adding EKS clusters
- Adding GKE clusters
- Group-level Kubernetes clusters
- Instance-level Kubernetes clusters
- Canary Deployments
- Cluster Environments
- Deploy Boards
- GitLab Managed Apps
- Crossplane configuration
- Cluster management project (alpha)
- Kubernetes Logs
- Runbooks
- Serverless
- Deploying AWS Lambda function using GitLab CI/CD
- Securing your deployed applications
- Groups
- Contribution Analytics
- Custom group-level project templates
- Epics
- Manage epics
- Group Import/Export
- Insights
- Issues Analytics
- Iterations
- Public access
- SAML SSO for GitLab.com groups
- SCIM provisioning using SAML SSO for GitLab.com groups
- Subgroups
- Roadmap
- Projects
- GitLab Secure
- Security Configuration
- Container Scanning
- Dependency Scanning
- Dependency List
- Static Application Security Testing (SAST)
- Secret Detection
- Dynamic Application Security Testing (DAST)
- GitLab Security Dashboard
- Offline environments
- Standalone Vulnerability pages
- Security scanner integration
- Badges
- Bulk editing issues and merge requests at the project level
- Code Owners
- Compliance
- License Compliance
- Compliance Dashboard
- Create a project
- Description templates
- Deploy Keys
- Deploy Tokens
- File finder
- Project integrations
- Integrations
- Atlassian Bamboo CI Service
- Bugzilla Service
- Custom Issue Tracker service
- Discord Notifications service
- Enabling emails on push
- GitHub project integration
- Hangouts Chat service
- Atlassian HipChat
- Irker IRC Gateway
- GitLab Jira integration
- Mattermost Notifications Service
- Mattermost slash commands
- Microsoft Teams service
- Mock CI Service
- Prometheus integration
- Redmine Service
- Slack Notifications Service
- Slack slash commands
- GitLab Slack application
- Webhooks
- YouTrack Service
- Insights
- Issues
- Crosslinking Issues
- Design Management
- Confidential issues
- Due dates
- Issue Boards
- Issue Data and Actions
- Labels
- Managing issues
- Milestones
- Multiple Assignees for Issues
- Related issues
- Service Desk
- Sorting and ordering issue lists
- Issue weight
- Associate a Zoom meeting with an issue
- Merge requests
- Allow collaboration on merge requests across forks
- Merge Request Approvals
- Browser Performance Testing
- How to create a merge request
- Cherry-pick changes
- Code Quality
- Load Performance Testing
- Merge Request dependencies
- Fast-forward merge requests
- Merge when pipeline succeeds
- Merge request conflict resolution
- Reverting changes
- Reviewing and managing merge requests
- Squash and merge
- Merge requests versions
- Draft merge requests
- Members of a project
- Migrating projects to a GitLab instance
- Import your project from Bitbucket Cloud to GitLab
- Import your project from Bitbucket Server to GitLab
- Migrating from ClearCase
- Migrating from CVS
- Import your project from FogBugz to GitLab
- Gemnasium
- Import your project from GitHub to GitLab
- Project importing from GitLab.com to your private GitLab instance
- Import your project from Gitea to GitLab
- Import your Jira project issues to GitLab
- Migrating from Perforce Helix
- Import Phabricator tasks into a GitLab project
- Import multiple repositories by uploading a manifest file
- Import project from repo by URL
- Migrating from SVN to GitLab
- Migrating from TFVC to Git
- Push Options
- Releases
- Repository
- Branches
- Git Attributes
- File Locking
- Git file blame
- Git file history
- Repository mirroring
- Protected branches
- Protected tags
- Push Rules
- Reduce repository size
- Signing commits with GPG
- Syntax Highlighting
- GitLab Web Editor
- Web IDE
- Requirements Management
- Project settings
- Project import/export
- Project access tokens (Alpha)
- Share Projects with other Groups
- Snippets
- Static Site Editor
- Wiki
- Project operations
- Monitor metrics for your CI/CD environment
- Set up alerts for Prometheus metrics
- Embedding metric charts within GitLab-flavored Markdown
- Embedding Grafana charts
- Using the Metrics Dashboard
- Dashboard YAML properties
- Metrics dashboard settings
- Panel types for dashboards
- Using Variables
- Templating variables for metrics dashboards
- Prometheus Metrics library
- Monitoring AWS Resources
- Monitoring HAProxy
- Monitoring Kubernetes
- Monitoring NGINX
- Monitoring NGINX Ingress Controller
- Monitoring NGINX Ingress Controller with VTS metrics
- Alert Management
- Error Tracking
- Tracing
- Incident Management
- GitLab Status Page
- Feature Flags
- GitLab CI/CD
- GitLab CI/CD pipeline configuration reference
- GitLab CI/CD include examples
- Introduction to CI/CD with GitLab
- Getting started with GitLab CI/CD
- How to enable or disable GitLab CI/CD
- Using SSH keys with GitLab CI/CD
- Migrating from CircleCI
- Migrating from Jenkins
- Auto DevOps
- Getting started with Auto DevOps
- Requirements for Auto DevOps
- Customizing Auto DevOps
- Stages of Auto DevOps
- Upgrading PostgreSQL for Auto DevOps
- Cache dependencies in GitLab CI/CD
- GitLab ChatOps
- Cloud deployment
- Docker integration
- Building Docker images with GitLab CI/CD
- Using Docker images
- Building images with kaniko and GitLab CI/CD
- GitLab CI/CD environment variables
- Predefined environment variables reference
- Where variables can be used
- Deprecated GitLab CI/CD variables
- Environments and deployments
- Protected Environments
- GitLab CI/CD Examples
- Test a Clojure application with GitLab CI/CD
- Using Dpl as deployment tool
- Testing a Phoenix application with GitLab CI/CD
- End-to-end testing with GitLab CI/CD and WebdriverIO
- DevOps and Game Dev with GitLab CI/CD
- Deploy a Spring Boot application to Cloud Foundry with GitLab CI/CD
- How to deploy Maven projects to Artifactory with GitLab CI/CD
- Testing PHP projects
- Running Composer and NPM scripts with deployment via SCP in GitLab CI/CD
- Test and deploy Laravel applications with GitLab CI/CD and Envoy
- Test and deploy a Python application with GitLab CI/CD
- Test and deploy a Ruby application with GitLab CI/CD
- Test and deploy a Scala application to Heroku
- GitLab CI/CD for external repositories
- Using GitLab CI/CD with a Bitbucket Cloud repository
- Using GitLab CI/CD with a GitHub repository
- GitLab Pages
- GitLab Pages
- GitLab Pages domain names, URLs, and baseurls
- Create a GitLab Pages website from scratch
- Custom domains and SSL/TLS Certificates
- GitLab Pages integration with Let's Encrypt
- GitLab Pages Access Control
- Exploring GitLab Pages
- Incremental Rollouts with GitLab CI/CD
- Interactive Web Terminals
- Optimizing GitLab for large repositories
- Metrics Reports
- CI/CD pipelines
- Pipeline Architecture
- Directed Acyclic Graph
- Multi-project pipelines
- Parent-child pipelines
- Pipelines for Merge Requests
- Pipelines for Merged Results
- Merge Trains
- Job artifacts
- Pipeline schedules
- Pipeline settings
- Triggering pipelines through the API
- Review Apps
- Configuring GitLab Runners
- GitLab CI services examples
- Using MySQL
- Using PostgreSQL
- Using Redis
- Troubleshooting CI/CD
- GitLab Package Registry
- GitLab Container Registry
- Dependency Proxy
- GitLab Composer Repository
- GitLab Conan Repository
- GitLab Maven Repository
- GitLab NPM Registry
- GitLab NuGet Repository
- GitLab PyPi Repository
- API Docs
- API resources
- .gitignore API
- GitLab CI YMLs API
- Group and project access requests API
- Appearance API
- Applications API
- Audit Events API
- Avatar API
- Award Emoji API
- Project badges API
- Group badges API
- Branches API
- Broadcast Messages API
- Project clusters API
- Group clusters API
- Instance clusters API
- Commits API
- Container Registry API
- Custom Attributes API
- Dashboard annotations API
- Dependencies API
- Deploy Keys API
- Deployments API
- Discussions API
- Dockerfiles API
- Environments API
- Epics API
- Events
- Feature Flags API
- Feature flag user lists API
- Freeze Periods API
- Geo Nodes API
- Group Activity Analytics API
- Groups API
- Import API
- Issue Boards API
- Group Issue Boards API
- Issues API
- Epic Issues API
- Issues Statistics API
- Jobs API
- Keys API
- Labels API
- Group Labels API
- License
- Licenses API
- Issue links API
- Epic Links API
- Managed Licenses API
- Markdown API
- Group and project members API
- Merge request approvals API
- Merge requests API
- Project milestones API
- Group milestones API
- Namespaces API
- Notes API
- Notification settings API
- Packages API
- Pages domains API
- Pipeline schedules API
- Pipeline triggers API
- Pipelines API
- Project Aliases API
- Project import/export API
- Project repository storage moves API
- Project statistics API
- Project templates API
- Projects API
- Protected branches API
- Protected tags API
- Releases API
- Release links API
- Repositories API
- Repository files API
- Repository submodules API
- Resource label events API
- Resource milestone events API
- Resource weight events API
- Runners API
- SCIM API
- Search API
- Services API
- Application settings API
- Sidekiq Metrics API
- Snippets API
- Project snippets
- Application statistics API
- Suggest Changes API
- System hooks API
- Tags API
- Todos API
- Users API
- Project-level Variables API
- Group-level Variables API
- Version API
- Vulnerabilities API
- Vulnerability Findings API
- Wikis API
- GraphQL API
- Getting started with GitLab GraphQL API
- GraphQL API Resources
- API V3 to API V4
- Validate the .gitlab-ci.yml (API)
- User Docs
- Abuse reports
- User account
- Active sessions
- Deleting a User account
- Permissions
- Personal access tokens
- Profile preferences
- Threads
- GitLab and SSH keys
- GitLab integrations
- Git
- GitLab.com settings
- Infrastructure as code with Terraform and GitLab
- GitLab keyboard shortcuts
- GitLab Markdown
- AsciiDoc
- GitLab Notification Emails
- GitLab Quick Actions
- Autocomplete characters
- Reserved project and group names
- Search through GitLab
- Advanced Global Search
- Advanced Syntax Search
- Time Tracking
- GitLab To-Do List
- Administrator Docs
- Reference architectures
- Reference architecture: up to 1,000 users
- Reference architecture: up to 2,000 users
- Reference architecture: up to 3,000 users
- Reference architecture: up to 5,000 users
- Reference architecture: up to 10,000 users
- Reference architecture: up to 25,000 users
- Reference architecture: up to 50,000 users
- Troubleshooting a reference architecture set up
- Working with the bundled Consul service
- Configuring PostgreSQL for scaling
- Configuring GitLab application (Rails)
- Load Balancer for multi-node GitLab
- Configuring a Monitoring node for Scaling and High Availability
- NFS
- Working with the bundled PgBouncer service
- Configuring Redis for scaling
- Configuring Sidekiq
- Admin Area settings
- Continuous Integration and Deployment Admin settings
- Custom instance-level project templates
- Diff limits administration
- Enable and disable GitLab features deployed behind feature flags
- Geo nodes Admin Area
- GitLab Pages administration
- Health Check
- Job logs
- Labels administration
- Log system
- PlantUML & GitLab
- Repository checks
- Repository storage paths
- Repository storage types
- Account and limit settings
- Service templates
- System hooks
- Changing your time zone
- Uploads administration
- Abuse reports
- Activating and deactivating users
- Audit Events
- Blocking and unblocking users
- Broadcast Messages
- Elasticsearch integration
- Gitaly
- Gitaly Cluster
- Gitaly reference
- Monitoring GitLab
- Monitoring GitLab with Prometheus
- Performance Bar
- Usage statistics
- Object Storage
- Performing Operations in GitLab
- Cleaning up stale Redis sessions
- Fast lookup of authorized SSH keys in the database
- Filesystem Performance Benchmarking
- Moving repositories managed by GitLab
- Run multiple Sidekiq processes
- Sidekiq MemoryKiller
- Switching to Puma
- Understanding Unicorn and unicorn-worker-killer
- User lookup via OpenSSH's AuthorizedPrincipalsCommand
- GitLab Package Registry administration
- GitLab Container Registry administration
- Replication (Geo)
- Geo database replication
- Geo with external PostgreSQL instances
- Geo configuration
- Using a Geo Server
- Updating the Geo nodes
- Geo with Object storage
- Docker Registry for a secondary node
- Geo for multiple nodes
- Geo security review (Q&A)
- Location-aware Git remote URL with AWS Route53
- Tuning Geo
- Removing secondary Geo nodes
- Geo data types support
- Geo Frequently Asked Questions
- Geo Troubleshooting
- Geo validation tests
- Disaster Recovery (Geo)
- Disaster recovery for planned failover
- Bring a demoted primary node back online
- Automatic background verification
- Rake tasks
- Back up and restore GitLab
- Clean up
- Namespaces
- Maintenance Rake tasks
- Geo Rake Tasks
- GitHub import
- Import bare repositories
- Integrity check Rake task
- LDAP Rake tasks
- Listing repository directories
- Praefect Rake tasks
- Project import/export administration
- Repository storage Rake tasks
- Generate sample Prometheus data
- Uploads migrate Rake tasks
- Uploads sanitize Rake tasks
- User management
- Webhooks administration
- X.509 signatures
- Server hooks
- Static objects external storage
- Updating GitLab
- GitLab release and maintenance policy
- Security
- Password Storage
- Custom password length limits
- Restrict allowed SSH key technologies and minimum length
- Rate limits
- Webhooks and insecure internal web services
- Information exclusivity
- How to reset your root password
- How to unlock a locked user from the command line
- User File Uploads
- How we manage the TLS protocol CRIME vulnerability
- User email confirmation at sign-up
- Security of running jobs
- Proxying assets
- CI/CD Environment Variables
- Contributor and Development Docs
- Contribute to GitLab
- Community members & roles
- Implement design & UI elements
- Issues workflow
- Merge requests workflow
- Code Review Guidelines
- Style guides
- GitLab Architecture Overview
- CI/CD development documentation
- Database guides
- Database Review Guidelines
- Database Review Guidelines
- Migration Style Guide
- What requires downtime?
- Understanding EXPLAIN plans
- Rake tasks for developers
- Mass inserting Rails models
- GitLab Documentation guidelines
- Documentation Style Guide
- Documentation structure and template
- Documentation process
- Documentation site architecture
- Global navigation
- GitLab Docs monthly release process
- Telemetry Guide
- Usage Ping Guide
- Snowplow Guide
- Experiment Guide
- Feature flags in development of GitLab
- Feature flags process
- Developing with feature flags
- Feature flag controls
- Document features deployed behind feature flags
- Frontend Development Guidelines
- Accessibility & Readability
- Ajax
- Architecture
- Axios
- Design Patterns
- Frontend Development Process
- DropLab
- Emojis
- Filter
- Frontend FAQ
- GraphQL
- Icons and SVG Illustrations
- InputSetter
- Performance
- Principles
- Security
- Tooling
- Vuex
- Vue
- Geo (development)
- Geo self-service framework (alpha)
- Gitaly developers guide
- GitLab development style guides
- API style guide
- Go standards and style guidelines
- GraphQL API style guide
- Guidelines for shell commands in the GitLab codebase
- HTML style guide
- JavaScript style guide
- Migration Style Guide
- Newlines style guide
- Python Development Guidelines
- SCSS style guide
- Shell scripting standards and style guidelines
- Sidekiq debugging
- Sidekiq Style Guide
- SQL Query Guidelines
- Vue.js style guide
- Instrumenting Ruby code
- Testing standards and style guidelines
- Flaky tests
- Frontend testing standards and style guidelines
- GitLab tests in the Continuous Integration (CI) context
- Review Apps
- Smoke Tests
- Testing best practices
- Testing levels
- Testing Rails migrations at GitLab
- Testing Rake tasks
- End-to-end Testing
- Beginner's guide to writing end-to-end tests
- End-to-end testing Best Practices
- Dynamic Element Validation
- Flows in GitLab QA
- Page objects in GitLab QA
- Resource class in GitLab QA
- Style guide for writing end-to-end tests
- Testing with feature flags
- Translate GitLab to your language
- Internationalization for GitLab
- Translating GitLab
- Proofread Translations
- Merging translations from CrowdIn
- Value Stream Analytics development guide
- GitLab subscription
- Activate GitLab EE with a license