diff options
author | Lin Jen-Shin <godfat@godfat.org> | 2018-07-16 18:07:36 +0300 |
---|---|---|
committer | Lin Jen-Shin <godfat@godfat.org> | 2018-07-16 18:07:36 +0300 |
commit | afe44451f46e2c470f429b0b6f73e04d49e66f7c (patch) | |
tree | 2388a3f85355ca180d2256f9c9299b5bf2dda059 /doc/development | |
parent | 5c4934ee9486fb5ce7f14581680369010009835b (diff) | |
parent | a73f480715f086e86d781e22d8a76b71c3b0680a (diff) |
[ci skip]ce-6038-rebase-preserve-merge
Merge remote-tracking branch 'upstream/master' into ce-6038-rebase-preserve-merge
* upstream/master: (173 commits)
Fix invalid link to GitLab.com architecture.md
i18n: externalize strings from 'app/views/import'
Remove Repository#lookup and unreachable rugged code
refactor code based on feedback
Trigger rails5 tests either by variable or ref name
Fix link in help doc which was linking to old mono-repo, now in its own repo
Allow Danger step to fail
update webpack to v4.16
Backport logger changes from EE
Add the CI Job trigger as the build trigger
Remove flaky and redundant expectations
use fileuploader dynamic path method in uploads manager and add spec
fix typo in uploads manager
add small comment to download method in uploads manager
refactor uploads manager
Update 10.6-to-10.7.md
Lazy-load performance bar UI
Update .gitlab-ci.yml
fixed test to correctly text relative URLs doesnt add query param if source & target projects match
Add changelog entry
...
Diffstat (limited to 'doc/development')
-rw-r--r-- | doc/development/architecture.md | 2 | ||||
-rw-r--r-- | doc/development/fe_guide/img/vue_arch.png | bin | 9848 -> 0 bytes | |||
-rw-r--r-- | doc/development/fe_guide/vue.md | 239 | ||||
-rw-r--r-- | doc/development/what_requires_downtime.md | 4 |
4 files changed, 14 insertions, 231 deletions
diff --git a/doc/development/architecture.md b/doc/development/architecture.md index e6cf5e01f46..3e417a44ec1 100644 --- a/doc/development/architecture.md +++ b/doc/development/architecture.md @@ -197,4 +197,4 @@ Note: It is recommended to log into the `git` user using `sudo -i -u git` or `su ## GitLab.com -CONFLICT! +We've also detailed [our architecture of GitLab.com](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/) but this is probably over the top unless you have millions of users. diff --git a/doc/development/fe_guide/img/vue_arch.png b/doc/development/fe_guide/img/vue_arch.png Binary files differdeleted file mode 100644 index a67706c7c1e..00000000000 --- a/doc/development/fe_guide/img/vue_arch.png +++ /dev/null diff --git a/doc/development/fe_guide/vue.md b/doc/development/fe_guide/vue.md index 219b98ac696..f6cbd11042c 100644 --- a/doc/development/fe_guide/vue.md +++ b/doc/development/fe_guide/vue.md @@ -2,27 +2,24 @@ To get started with Vue, read through [their documentation][vue-docs]. -## Vue architecture +## Examples -All new features built with Vue.js must follow a [Flux architecture][flux]. -The main goal we are trying to achieve is to have only one data flow and only one data entry. -In order to achieve this goal, you can either use [vuex](#vuex) or use the [store pattern][state-management], explained below: +What is described in the following sections can be found in these examples: -Each Vue bundle needs a Store - where we keep all the data -, a Service - that we use to communicate with the server - and a main Vue component. +- web ide: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/app/assets/javascripts/ide/stores +- security products: https://gitlab.com/gitlab-org/gitlab-ee/tree/master/ee/app/assets/javascripts/vue_shared/security_reports +- registry: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/app/assets/javascripts/registry/stores -Think of the Main Vue Component as the entry point of your application. This is the only smart -component that should exist in each Vue feature. -This component is responsible for: -1. Calling the Service to get data from the server -1. Calling the Store to store the data received -1. Mounting all the other components +## Vue architecture -![Vue Architecture](img/vue_arch.png) +All new features built with Vue.js must follow a [Flux architecture][flux]. +The main goal we are trying to achieve is to have only one data flow and only one data entry. +In order to achieve this goal we use [vuex](#vuex). You can also read about this architecture in vue docs about [state management][state-management] and about [one way data flow][one-way-data-flow]. -### Components, Stores and Services +### Components and Store In some features implemented with Vue.js, like the [issue board][issue-boards] or [environments table][environments-table] @@ -33,10 +30,8 @@ new_feature ├── components │ └── component.vue │ └── ... -├── stores +├── store │ └── new_feature_store.js -├── services # only when not using vuex -│ └── new_feature_service.js ├── index.js ``` _For consistency purposes, we recommend you to follow the same structure._ @@ -125,217 +120,6 @@ You can read more about components in Vue.js site, [Component System][component- #### Vuex Check this [page](vuex.md) for more details. -#### Flux like state management -The Store is a class that allows us to manage the state in a single -source of truth. It is not aware of the service or the components. - -The concept we are trying to follow is better explained by Vue documentation -itself, please read this guide: [State Management][state-management] - -### A folder for the Service - -**If you are using Vuex you won't need this step** - -The Service is a class used only to communicate with the server. -It does not store or manipulate any data. It is not aware of the store or the components. -We use [axios][axios] to communicate with the server. -Refer to [axios](axios.md) for more details. - -Axios instance should only be imported in the service file. - -```javascript -import axios from '~/lib/utils/axios_utils'; -``` - -### End Result - -The following example shows an application: - -```javascript -// store.js -export default class Store { - - /** - * This is where we will iniatialize the state of our data. - * Usually in a small SPA you don't need any options when starting the store. - * In that case you do need guarantee it's an Object and it's documented. - * - * @param {Object} options - */ - constructor(options) { - this.options = options; - - // Create a state object to handle all our data in the same place - this.todos = []; - } - - setTodos(todos = []) { - this.todos = todos; - } - - addTodo(todo) { - this.todos.push(todo); - } - - removeTodo(todoID) { - const state = this.todos; - - const newState = state.filter((element) => {element.id !== todoID}); - - this.todos = newState; - } -} - -// service.js -import axios from '~/lib/utils/axios_utils' - -export default class Service { - constructor(options) { - this.todos = axios.create({ - baseURL: endpoint.todosEndpoint - }); - - } - - getTodos() { - return this.todos.get(); - } - - addTodo(todo) { - return this.todos.put(todo); - } -} -// todo_component.vue -<script> -export default { - props: { - data: { - type: Object, - required: true, - }, - }, -}; -</script> -<template> - <div> - <h1> - Title: {{data.title}} - </h1> - <p> - {{data.text}} - </p> - </div> -</template> - -// todos_main_component.vue -<script> -import Store from 'store'; -import Service from 'service'; -import TodoComponent from 'todoComponent'; -export default { - components: { - todo: TodoComponent, - }, - /** - * Although most data belongs in the store, each component it's own state. - * We want to show a loading spinner while we are fetching the todos, this state belong - * in the component. - * - * We need to access the store methods through all methods of our component. - * We need to access the state of our store. - */ - data() { - const store = new Store(); - - return { - isLoading: false, - store: store, - todos: store.todos, - }; - }, - - created() { - this.service = new Service('/todos'); - - this.getTodos(); - }, - - methods: { - getTodos() { - this.isLoading = true; - - this.service - .getTodos() - .then(response => { - this.store.setTodos(response); - this.isLoading = false; - }) - .catch(() => { - this.isLoading = false; - // Show an error - }); - }, - - addTodo(event) { - this.service - .addTodo({ - title: 'New entry', - text: `You clicked on ${event.target.tagName}`, - }) - .then(response => { - this.store.addTodo(response); - }) - .catch(() => { - // Show an error - }); - }, - }, -}; -</script> -<template> - <div class="container"> - <div v-if="isLoading"> - <i - class="fa fa-spin fa-spinner" - aria-hidden="true" /> - </div> - - <div - v-if="!isLoading" - class="js-todo-list"> - <template v-for='todo in todos'> - <todo :data="todo" /> - </template> - - <button - @click="addTodo" - class="js-add-todo"> - Add Todo - </button> - </div> - <div> -</template> - -// index.js -import todoComponent from 'todos_main_component.vue'; - -new Vue({ - el: '.js-todo-app', - components: { - todoComponent, - }, - render: createElement => createElement('todo-component' { - props: { - someProp: [], - } - }), -}); - -``` - -The [issue boards service][issue-boards-service] -is a good example of this pattern. - ## Style guide Please refer to the Vue section of our [style guide](style_guide_js.md#vue-js) @@ -446,6 +230,5 @@ need to test the rendered output. [Vue][vue-test] guide's to unit test show us e [state-management]: https://vuejs.org/v2/guide/state-management.html#Simple-State-Management-from-Scratch [one-way-data-flow]: https://vuejs.org/v2/guide/components.html#One-Way-Data-Flow [vue-test]: https://vuejs.org/v2/guide/unit-testing.html -[issue-boards-service]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/app/assets/javascripts/boards/services/board_service.js.es6 [flux]: https://facebook.github.io/flux [axios]: https://github.com/axios/axios diff --git a/doc/development/what_requires_downtime.md b/doc/development/what_requires_downtime.md index 47396666879..b668c9de6a0 100644 --- a/doc/development/what_requires_downtime.md +++ b/doc/development/what_requires_downtime.md @@ -198,14 +198,14 @@ And that's it, we're done! ## Changing The Schema For Large Tables While `change_column_type_concurrently` and `rename_column_concurrently` can be -used for changing the schema of a table without downtime it doesn't work very +used for changing the schema of a table without downtime, it doesn't work very well for large tables. Because all of the work happens in sequence the migration can take a very long time to complete, preventing a deployment from proceeding. They can also produce a lot of pressure on the database due to it rapidly updating many rows in sequence. To reduce database pressure you should instead use -`change_column_type_using_background_migration` or `rename_column_concurrently` +`change_column_type_using_background_migration` or `rename_column_using_background_migration` when migrating a column in a large table (e.g. `issues`). These methods work similarly to the concurrent counterparts but uses background migration to spread the work / load over a longer time period, without slowing down deployments. |