Recently in follow starting from 0 handy with you to build a set of specifications Vue3. Article x project engineering environment to establish some detail problems in the process of learning, through various query solution finally, and ultimately achieve a set of with code specification + + + automated unit test specification submitted the front end of the deployment environment, write this article records the process. Related requirements are as follows:
- Architectural structures,
- Code specification
- Submit specifications
- Unit testing
- Automated deployment
Architectural structures,
-
Initializing the architecture
- Initialize the vite
npm init @vitejs/app
Copy the code
- The terminal is initialized
-
Modify the vite. Config. Js
Import {defineConfig} from 'vite' import vue from '@vitejs/plugin-vue' // If the editor says path module cannot be found, You can install it @ types/node - > NPM I @ types/node - D import path from export 'path' / / https://vitejs.dev/config/ default defineConfig({ plugins: [vue()], resolve:{ alias:{ '@':path.resolve(__dirname,'src') } }, base:'./', server:{ port:4000, open:true, cors:true } })Copy the code
-
Initialize the project directory
Vue3 - vite ├ ─. Gitignore ├ ─. Vscode │ └ ─ extensions. The json ├ ─ index. The HTML ├ ─ package - lock. Json ├ ─ package. The json ├ ─ public │ └ ─ the favicon. Ico ├ ─ README. Md ├ ─ SRC │ ├ ─ App. Vue │ ├ ─ assets │ │ └ ─ logo. The PNG │ ├ ─ common │ ├ ─ components │ │ └ ─ The HelloWorld. Vue │ ├ ─ env. Which s │ ├ ─ main. Ts │ ├ ─ the router │ ├ ─ store │ ├ ─ style │ ├ ─ utils │ └ ─ views ├ ─ tests ├ ─ Tsconfig. Json └ ─ vite. Config. TsCopy the code
-
Initializing a Route
- Install the routing
npm install vue-router@4
Copy the code
- Configuring routing Files
import {createRouter,createWebHistory,RouteRecordRaw} from 'vue-router'
import Home from '@/src/views/home.vue'
import Vuex from '@/src/views/vuex.vue'
const routes: Array<RouteRecordRaw>=[
{
path:'/',
name:'home',
components:Home
},{
path:'vuex',
name:'vuex',
components:Vuex
},
{
path:'/axios',
name:'axios',
component:()=>import('@/views/axios')
}
]
const router = createRouter({
history:createWebHistory(),
routes
})
export default router;
Copy the code
- Mount the routing
import { createApp } from 'vue'
import App from './App.vue'
import router from './router/index'
const app= createApp(App);
app.use(router).mount('#app')
Copy the code
-
Initialize vuex
- Install vuex
npm install vuex@next
Copy the code
- Configure the store
import { InjectionKey } from 'vue'
import { createStore, Store, useStore as baseUseStore } from 'vuex'
import RootStateTypes, { AllStateTypes } from './types'
import numFactoryModule from './modules/NumFactory'
export const store = createStore<RootStateTypes>({
state: {
text: 'This is Vuex Root.state.text'
},
getters: {},
mutations: {},
actions: {},
modules: {
numFactoryModule
}
})
export const key: InjectionKey<Store<RootStateTypes>> = Symbol('vue-store')
export function useStore<T = AllStateTypes>() {
return baseUseStore<T>(key)
}
Copy the code
- Mount vuex
import { createApp } from 'vue'
import App from './App.vue'
import router from './router/index'
import { key, store } from './store/index'
const app= createApp(App);
app.use(router).use(store,key).mount('#app')
Copy the code
-
Integrated UI framework ### Element Plus
- The installation Element Plus
npm install element-plus
Copy the code
- To select load on Demand, install is required first
unplugin-vue-components
npm install unplugin-vue-components
Copy the code
- Configuration vite. Config. Js
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
export default {
plugins: [
// ...
Components({
resolvers: [ElementPlusResolver()],
}),
],
}
Copy the code
- Add style – import. Ts
Add style-import.ts to the utis directory to install required components
import { App } from 'vue' import { ElIcon, ElLoading, ElCard, ElButton} from 'element-plus' /** * Import element Plus components on demand * Vite plugin https://github.com/element-plus/vite-plugin-element-plus * @param app {App} */ export default function styleImport(app: App) { ; [ElButton, ElCard, ElLoading, ElIcon].forEach((v) => { app.use(v) }) return app }Copy the code
- The main element js mount – plus
import { createApp } from 'vue'
import App from './App.vue'
import router from './router/index'
import { key, store } from './store/index'
import styleImport from './utils/style-import'
const app= createApp(App);
styleImport(app).use(router).use(store,key).mount('#app')
Copy the code
-
Integrated axios
- Install axios
npm i axios
Copy the code
- Configuration axios
Create axios.ts in the utils directory
import Axios from 'axios' import { ElMessage } from 'element-plus' const baseURL = 'https://api.github.com' const axios = Axios.create({ baseURL, timeout: 20000 / / request timeout 20 s}) / / front interceptor (before a request to intercept) axios. Interceptors. Request. Use ((response) = > {/ * * * according to the actual circumstance of your project to do processing * config Nothing is done to config here, Return */ return response}, (error) = > {return Promise. Reject (error)}) / / rear interceptor (access to the response when the intercept) axios. Interceptors. Response. Use ((response) = > {/ * * * Do response and error based on what your project is doing * I'm not doing anything with response and error, Return */ return response}, (error) => { if (error.response && error.response.data) { const code = error.response.status const msg = error.response.data.message ElMessage.error(`Code: ${code}, Message: ${msg}`) console.error(`[Axios Error]`, error.response) } else { ElMessage.error(`${error}`) } return Promise.reject(error) } ) export default axiosCopy the code
-
Integrated CSS precompiler Stylus/Sass/Less
The loader is installed in Vite, so you do not need to deal with it separately. You only need to download the relevant development dependencies
npm i stylus -D
# or
npm i sass -D
npm i less -D
Copy the code
At this point, One based on TypeScript + Vite + Vue3 + Vue Router + Vuex + Element Plus + Axios + Stylus/Sass/Less After setting up the front-end project development environment, the next step is to configure code detection + submission detection + unit testing + automated deployment.
Code specification
Integrate the EditorConfig configuration
EditorConfig helps maintain a consistent coding style for multiple developers working on the same project on different IDE editors.
Website: editorconfig.org
Add the.editorConfig file to the project root directory:
# Editor configuration, See http://editorconfig.org # root = true [*] # all files applicable charset = UTF-8 # utF-8 Indent_style = space # indented style (TAB | space) indent_size = 2 # # end_of_line indentation size = lf control line type (lf | cr | CRLF) Trim_trailing_whitespace = true # Insert_final_newline = true # Always insert a newline at the end of the file [*.md] # indicates that the following rules apply only to MD files max_line_length = off trim_trailing_whitespace = falseCopy the code
Note: VSCode uses EditorConfig to download EditorConfig for VSCode from the plugin market
Integrating the Prettier configuration
Prettier Prettier is a powerful code formatting tool that supports JavaScript, TypeScript, CSS, SCSS, Less, JSX, Angular, Vue, GraphQL, JSON, Markdown, etc. Basically the front end can use the file format it can be done, is the most popular code formatting tool.
Liverpoolfc.tv: prettier. IO /
- Install the Prettier
npm i prettier -D
Copy the code
- configuration
.prettierrc
The. Prettierrc file is created in the root directory of the project, where the configuration is as follows:
{
"useTabs": false,
"tabWidth": 2,
"printWidth": 100,
"singleQuote": true,
"trailingComma": "none",
"bracketSpacing": true,
"semi": false
}
Copy the code
Note:
- The VSCode editor Prettier requires downloading the plug-in Prettier-code Formatter to use Prettier for configuration
Prettier after Prettier is configured, when VSCode formatting is used, the editor formats the Prettier configuration file according to the rules of the Prettier configuration file, avoiding the coding style differences caused by different editors where Prettier is configured.
Integrate ESLint configuration
ESLint is a tool for finding and reporting problems in code, and for auto-fixing some problems. Its core is the ability to analyze code to check code quality and style problems through pattern matching of AST (Abstract Syntax Tree) obtained from code parsing.
As we mentioned before as team members programming ability and coding habits between different quality problems caused by the code, we use ESLint to solve, while writing code to find problems, if found wrong, prompt is given rules, and automatically repair, go down for a long time, can make team members gravitate to the same kind of coding style.
- Install ESLint
npm i eslint -D
Copy the code
- Configuration ESLint
After ESLint is installed successfully, execute NPX ESLint –init and follow terminal instructions to complete a series of Settings to create the configuration file.
Based on the above selection, ESLint will automatically look for missing dependencies, which we select hereYesDownload and install these dependencies using NPM.
Note: If the automatic installation dependency fails, manual installation is required
npm i @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint-config-airbnb-base eslint-plugin-import eslint-plugin-vue -D
Copy the code
- ESLint configuration files
.eslintrc.js
After the previous step, the.eslintrc.js configuration file is automatically generated in the project root directory:
module.exports = { env: { browser: true, es2021: true, node: true }, extends: [ 'plugin:vue/vue3-essential', 'airbnb-base', 'plugin:jest/recommended', 'plugin: prettier/it / / add a prettier plug-in], parserOptions: {ecmaVersion: 13, the parser: '@typescript-eslint/parser', sourceType: 'module' }, plugins: ['vue', '@typescript-eslint'], rules: { 'generator-star-spacing': 'off', 'no-debugger': 'off', 'no-tabs': 'off', 'no-unused-vars': 'off', 'no-console': 'off', 'no-irregular-whitespace': 'off', 'import/no-unresolved': 'off', 'import/extensions': 'off', 'import/no-absolute-path': 'off', 'import/no-extraneous-dependencies': 'off', 'vue/no-multiple-template-root': 'off', 'no-param-reassign': [ 'error', { props: true, ignorePropertyModificationsFor: [ 'e', // for e.returnvalue 'ctx', // for Koa routing 'req', // for Express requests 'request', // for Express requests 'res', // for Express responses 'response', // for Express responses 'state' // for vuex state ] } ] }, settings: { 'import/resolver': { typescript: { project: `${__dirname}/tsconfig.json` } } } }Copy the code
Note:
- To use the ESLint configuration file for VSCode, you need to download the plugin ESLint from the plugin market
After the configuration is complete, we enable ESLin in VSCode. When writing code, ESLint will check the code in real time according to our configured rules, and will give error messages and fix solutions if any problems are found. Although, now the editor has given error prompts and fixes, but we need to click one by one to fix, or quite troublesome. Very simple, we just set the editor to automatically execute when saving the fileeslint --fix
Command for code style fixes.
- VSCode in
settings.json
Add the following code to the Settings file:
"editor.codeActionsOnSave": { "source.fixAll.eslint": true }
Copy the code
- EsLint reports an error when typescript uses import
You need to install eslint-plugin-import and eslint-import-resolver-typescript plug-ins to configure esLint to use tsconfig.js path
"paths": { "@/*": ["./*"]}
Copy the code
8. Resolve conflict between Prettier and ESLint
When you add extra configuration rules for ESLint and Prettier to your project, there are often rules that conflict.
The ESLint configuration in this project uses the Airbnb JavaScript style guide validation. One of the rules is to put a semicolon after the end of code, while we added an unsemicolon after the end of code in the Prettier configuration file, so there’s a conflict, Prettier formatting code occurs after Prettier is used, ESLint detects formatting errors and throws an error.
Eslint-plugin-prettier and eslint-config-prettier are used to solve conflicts between the two.
eslint-plugin-prettier
Prettier’s rule into ESLint’s ruleeslint-config-prettier
Disable the rule in ESLint that conflicts with Prettier.
Prettier Configuration Rule > ESLint Configates rules.
- in
.eslintrc.js
Add the prettier plug-in
Extends: [' plugin: vue/vue3 - essential ', 'reality - base', 'the plugin: prettier/it / / add a prettier plug-in].Copy the code
Integrate Husky and Lint-staged
We already integrate ESLint and Prettier into the project, where they verify code in real time and, to a certain extent, regulate it, but some people on the team may find the restrictions cumbersome and choose to ignore “hints”. Write your code in your own style, or disable the tools altogether, and commit your code directly to the repository. Over time, ESLint becomes useless.
So, we also need to make certain that the repository code is spec compliant by making it impossible to commit code that has not passed ESLint detection and fixes.
To solve this problem, you need to use a Git Hook. When a local Git commit is performed, ESLint checks and fixes the committed code (i.e., ESLint –fix). If the code fails to pass the ESLint rule, the commit is disabled.
To achieve this feature, we resorted to Husky + Lint-staged. Husky — Git Hook, which can be set to trigger Git commands at various stages (pre-commit, commit-msg, pre-push, etc.). Lint-staged — Run linters on files temporarily stored in Git.
-
Configuration husky
Use the husky-init command to quickly initialize a husky configuration in your project
npx husky-init ; npm install
Copy the code
This command does four things:
- Install Husky to development dependencies
- Create in the project root directory
.husky
directory
- in
.husky
The directory to createpre-commit
Hook, and initializepre-commit
Command tonpm test
- Modify the
package.json
的scripts
, an increase of"prepare": "husky install"
Here, husky is configured and now we can use it:
Husky contains many hooks, such as pre-commit, commit-msg, and pre-push. Here, we use pre-commit to trigger the ESLint command.
Alter.husky/pre-commit hook trigger command:
eslint --fix ./src --ext .vue,.js,.ts
Copy the code
The above pre-commit hook file does the following: Git commit -m “XXX” : $git commit -m “XXX” : $git commit -m “XXX” : $git commit -m
However, there is a problem: sometimes we need to implement ESLint –fix for all files when we have changed only one or two files. If this were a history project and we configured ESLint rules halfway through, then other unmodified “history” files would also be checked when submitting code, which could result in a large number of ESLint errors, obviously not the desired result.
We want to use ESLint only to fix the code we wrote this time and not affect the rest of the code. So there’s a magical tool called Lint-Staged.
Configuration lint – staged
Lint-staged this tool, commonly used in conjunction with Husky, allows Husky hook triggered commands to only act on Git add files (files in git staging) without affecting other files.
- Install the lint – staged
npm i lint-staged -D
Copy the code
- in
package.json
To add lint-staged configuration items
"lint-staged": { "*.{vue,js,ts}": "eslint --fix" }
Copy the code
- Modify the
.husky/pre-commit
The trigger command of hook is:npx lint-staged
Husky and Lint-staged configurations are now complete. Add./ SRC/git commit -m “test…” Eslint –fix will be executed for only the two files test-1.js and test-2.ts. If ESLint passes, the commit succeeds, otherwise the commit terminates. This ensures that the code we submit to the Git repository is canonical.
Submit specifications
Commit Message format specification
Commit Message consists of Header, Body, and Footer.
<Header> <Body> <Footer> Copy the codeCopy the code
Header
The Header section contains three fields type (required), Scope (optional), and subject (required).
<type>(<scope>): <subject> Copies codeCopy the code
type
Type specifies the commit type of the commit (it must be one of the following).
value | describe |
---|---|
feat | Add a new feature |
fix | Fix a Bug |
docs | Document change |
style | Code formatting (does not affect functionality, such as space, semicolon, and other formatting fixes) |
refactor | Code refactoring |
perf | To improve the performance |
test | test |
build | Changing project builds or external dependencies (e.g. scopes: webpack, gulp, NPM, etc.) |
ci | Change the scripts commands in the continuous integration software configuration files and packages, such as scopes: Travis, Circle, etc |
chore | Change the build process or assistive tools |
revert | Code back |
scope
Scope Specifies the scope of the impact of the commit. Scope is determined by project. For example, it can be divided by menu or function module in business project, or component library development. (scope can be omitted)
subject
Subject is a brief description of the commit. The length of the subject is no more than 50 characters. Subject generally complies with the following specifications:
- Use the first person present tense starting with a verb, e.g. change instead of changed or changes
- The first letter is lowercase
- Ending without a period (.)
Integrate the CommitLint validation commit specification
In the “Code Specification” section, we talked about how, despite the specification, in a multi-person project, some people will always do what they want, so we added a restriction to the submission of code: Only commitLint/config-Conventional and @commitLint/CLI commit messages are allowed to pass.
-
Install commitlint
npm i @commitlint/config-conventional @commitlint/cli -D
Copy the code
-
Configuration commitlint
Create a file named commitlint.config.js in the root directory of your project and fill it with the following:
module.exports = { extends: ['@commitlint/config-conventional'] }
Copy the code
-
.husky
Directory creationcommit-msg
file
Create a commit- MSG file in the. Husky directory and run the commit message authentication command there
#! /bin/sh . "$(dirname "$0")/_/husky.sh" npx --no-install commitlint --editCopy the code
-
Commitlint validation
- Submission information that does not conform to the specification
As shown in the following figure, the submission information 111 does not meet the specifications and the submission fails.
- Submit information that conforms to the specification
Commitlint test: Commitlint test complies with the specification and is successfully committed to the repository.
Unit testing
Unit testing is a very important part of project development, complete testing can provide quality assurance for code and business, reduce the occurrence of bugs
-
Installation development dependency
npm i @vue/test-utils@next jest vue-jest@next ts-jest -D
Copy the code
-
Create the JEST configuration file
Create a new jest.config.js file in the project root directory:
module.exports = { moduleFileExtensions: ['vue', 'js', 'ts'], preset: 'ts-jest', testEnvironment: 'jsdom', transform: {' ^. + \ \. Vue $' : 'vue - jest, / / the vue file using the vue - jest conversion' $' ^. + \ \. Ts: 'ts-jest' // ts files with ts-jest conversions}, // match __tests__.js/.ts files or xx.test.js/ts xx.spec.js/ts testRegex in other directories: '(/__tests__/.*|(\\.|/)(test|spec))\\.(ts)$' }Copy the code
-
Create a unit test file
In the jest. Config. js file above, we configure unit tests to match only any.ts file in the __tests__ directory or xx.test.ts/xx.spec.ts file in other directories.
Here, we create the Tests directory under the project root to store the unit test file
├ ─ ─ SRC / └ ─ ─ tests / / / unit Test ├ ─ ─ Test. The spec. Ts / / the Test component testsCopy the code
Test.spec.ts
import { mount } from '@vue/test-utils' import Test from '.. /src/views/Test.vue' test('Test.vue', async () => { const wrapper = mount(Test) expect(wrapper.html()).toContain('Unit Test Page') expect(wrapper.html()).toContain('count is: 0') await wrapper.find('button').trigger('click') expect(wrapper.html()).toContain('count is: 1') })Copy the code
Test.vue
<template>
<div class="test-container page-container">
<div class="page-title">Unit Test Page</div>
<p>count is: {{ count }}</p>
<button @click="increment">increment</button>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue'
export default defineComponent({
name: 'VuexDemo',
setup() {
const count = ref<number>(0)
const increment = () => {
count.value += 1
}
return { count, increment }
}
})
</script>
Copy the code
-
Integrated @ types/jest
As shown above, when we use VSCode/WebStrom/IDEA, in the unit test file, the IDE will indicate that certain methods (test, describe, IT, expect, etc.) do not exist, which can be fixed by installing @types/jest.
npm i @types/jest -D
Copy the code
The TypeScript compiler will also tell you that jest methods and types are missing. We need to add @types/jest to ts.config.json (TypeScript configuration file) in the root directory:
{ "compilerOptions": { ... "types": ["vite/client", "jest"] }, }
Copy the code
-
Add eslint – plugin – jest
Because we integrated ESLint into the project, as shown above, it clearly failed ESLint rule verification. Therefore, we also need to add the eslint-plugin-jest plugin to ESLint to unvalidate jEST.
- Install eslint – plugin – jest
npm i eslint-plugin-jest -D
Copy the code
- Add eslint-plugin-jest to the esLint configuration file
.eslintrc.js
中
extends: [ 'plugin:vue/vue3-essential', 'airbnb-base', 'plugin:jest/recommended', 'the plugin: prettier/it / / add prettier plugins],Copy the code
-
Executing unit tests
In the scripts of the package.json file in the root directory, add a unit test command: “test”: “jest”
Jest uses the jest config file to find.ts files in __tests__ or.spec.ts and.test.ts files in any other directory. The unit test method is then executed.
Note:
- If the following error is reported as a problem with the jEST version, you can install [email protected], [email protected]
-
Unit test constraints
Previously, we used Husky to constrain the code style specification and commit information specification in the pre-commit and commit-msg phases of Git, respectively. In this step, we do unit tests in the pre-push phase, and let the code push to the remote repository only if all the unit tests pass, otherwise we abort the push.
Use the husky command to automatically create a pre-push hook file in the.husky directory and execute the unit test command NPM run test there.
#! /bin/sh . "$(dirname "$0")/_/husky.sh" npm run testCopy the code
Now, we can conduct unit tests in Git push first. Only when all unit tests pass, can push succeed
Automatic deployment
This project is to build a standard front-end engineering environment, for which we use CI (Continuous Integration) to complete the final deployment of the project.
Common CI tools include GitHub Actions, GitLab CI, Travis CI, Circle CI, etc.
Here, we use GitHub Actions.
-
What are GitHub Actions
GitHub Actions is GitHub’s continuous integration service. Continuous integration consists of Actions such as grabbing code, running tests, logging into remote servers, publishing to third-party services, and more. GitHub calls these Actions Actions.
-
Configuration making Actions
Since GitHub Actions are only valid for the GitHub repository, we create the GitHub repository to host the project code
Where, we use:
master
Branches store project source codegh-pages
Branches store packaged static files
The GH-Pages branch is a fixed branch of the GitHub Pages service. You can access the static file resources of this branch through HTTP.
-
Create a lot Token
Create a GitHub Token with repo and Workflow permissions
Note: Newly generated tokens are displayed only once and saved for later use. If it is lost, it can be regenerated
-
Add Secret to the repository
Add the new Token to GitHub repository Secrets and name the new secret VUE3_DEPLOY (whatever you like).
Steps: Repository -> Settings -> Secrets -> New Repository Secret.
Newly created SecretVUE3_DEPLOY
This is used in the Actions configuration file, keep the two places the same!
-
Create the Actions configuration file
- Create in the project root directory
.github
Directory. - in
.github
Directory creationworkflows
Directory. - in
workflows
Directory creationdeploy.yml
File.
Jobs: deploy: runs-on: Ubuntu -latest steps: - uses: actions/checkout@v2 - name: Setup Node.js v14.x uses: actions/setup-node@v1 with: node-version: '14.x' - name: Install run: NPM Install # Install dependencies - name: Build run: NPM run Build # package - name: Deploy uses: Peaceiris /actions-gh-pages@v3 # Deploy to GitHub Pages action with: publish_dir:./dist # deploy to dist folder github_token: ${{secrets. Vue3_deploy}} # secret user_name: ${{secrets.MY_USER_NAME}} user_email: ${{secrets.my_user_email}} commit_message: Update Vite2.x + vue3. x + TypeScript Starter # Git commit information for deploymentCopy the code
-
Automatic deployment trigger mechanism
When a new submission is pushed to the GitHub repository, GitHub Actions are triggered to execute commands in the GitHub Action configuration file on the GitHub server, such as: Install dependencies, project packaging, etc., then deploy the packaged static files to GitHub Pages, and finally, we have domain access.
Through the domain nameJingyuanhe. Making. IO/vue3 – typesc…Visit the project
The last
This article is a reference to others, thanks again from 0 to take you to build a standard Vue3. X project engineering environment, mainly to record some pits encountered in the learning process, to prevent the same problems in the future.