Project construction Specification

I. Code specification

1.1. Integrate the EditorConfig configuration

EditorConfig helps maintain a consistent coding style for multiple developers working on the same project on different IDE editors.

# http://editorconfig.org

root = true

[*] # indicates that all files apply
charset = utf-8 Set character set to UTF-8
indent_style = space # indented style (TAB | space)
indent_size = 2 # Indent size
end_of_line = lf # control line type (lf | cr | CRLF)
trim_trailing_whitespace = true # Remove any whitespace at the beginning of the line
insert_final_newline = true Always insert a new line at the end of the file

[*.md] # indicates that the following rules apply only to md files
max_line_length = off
trim_trailing_whitespace = false
Copy the code

VSCode requires a plug-in: EditorConfig for VSCode

1.2. Use the Prettier tool

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.

1. Install the prettier

npm install prettier -D
Copy the code

2. Configure the. Prettierrc file:

  • UseTabs: Use TAB or space indent, select false;
  • TabWidth: if TAB is a space, select 2 Spaces;
  • PrintWidth: When the line length is 80 characters, some people prefer 100 or 120 characters;
  • SingleQuote: Use single or double quotes, select true, use single quotes;
  • TrailingComma: whether to add the trailingComma entered on multiple lines, set tonone;
  • Semi: Indicates whether to add a semicolon to the end of the statement. The default value is true.
{
  "useTabs": false."tabWidth": 2."printWidth": 80."singleQuote": true."trailingComma": "none"."semi": false
}
Copy the code

3. Create the. Prettierignore file

/dist/*
.local
.output.js
/node_modules/**

**/*.svg
**/*.sh

/public/*
Copy the code

4.VSCode needs to install the plug-in for Prettier

5. Test whether Prettier takes effect

  • Test 1: Save code in code;
  • Test 2: Configure the command for one-time modification.

Configure a script in package.json:

    "prettier": "prettier --write ."
Copy the code

1.3. Use ESLint to detect

1. We chose ESLint when we created the project earlier, so Vue will help us configure the ESLint environment we need by default.

2.VSCode needs to install the ESLint plugin:

3. Resolving the conflict between ESLint and Prettier:

Install plugins :(if prettier is selected by vue when creating a project, these two plugins are installed automatically)

npm i eslint-plugin-prettier eslint-config-prettier -D
Copy the code

Add the prettier plugin:

  extends: [
    "plugin:vue/vue3-essential"."eslint:recommended"."@vue/typescript/recommended"."@vue/prettier"."@vue/prettier/@typescript-eslint",
    'plugin:prettier/recommended'
  ],
Copy the code

1.4. git Husky and ESLint

Although we have already required the project to use ESLint, there is no guarantee that the problems in ESLint will be resolved before team members submit code:

  • That is, we want to ensure that the code in the repository is esLint compliant;

  • Git commit: If the git commit does not conform to the ESLint specification, it will be automatically fixed by the specification.

So how do you do this? Husky tools are available:

  • Husky is a Git hook that triggers the various stages of git commit: pre-commit, commit-msg, and pre-push

How do you use Husky?

Here we can use the autoconfiguration command:

npx husky-init && npm install
Copy the code

Three things will be done here:

1. Install Husky-related dependencies:

2. Create the.husky folder in the project directory:

npx huksy install
Copy the code

3. Add a script to package.json:

Next, we need to do one operation: on commit, execute the Lint script:

Git commit will automatically validate your code.

1.5. Git Commit specification

1.5.1. Code submission style

Git commits are usually committed in a consistent style so that you can quickly locate each commit for later version control.

But if writing these manually every time is a hassle, we can use a tool: Commitizen

  • Commitizen is a tool that helps us write normative Commit messages;

1. Install Commitizen

npm install commitizen -D
Copy the code

2. Install AND initialize THE Z-Xconventional – Changelog:

npx commitizen init cz-conventional-changelog --save-dev --save-exact
Copy the code

This command will help us install CZ-Conventional – Changelog:

And configure it in package.json:

This time we need to submit code using NPX cz:

  • The first step is to select Type, the type of this update
Type role
feat New features
fix Fix the Bug (Bug fix)
docs Modify documentation
style Change code formats (white-space, formatting, missing semi Colons, etc.)
refactor Code Refactor
perf A code change that improves Performance
test When adding Missing tests
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 Changing the build process or ancillary tools (such as changing the test environment)
revert Code back
  • Step 2 Select the scope of this modification (scope)

  • The third step is to select the information to submit

  • Step 4 Submit detailed description

  • Step 5 is a major change

  • Step 6 Whether to affect an Open issue

We can also build a command in scripts to execute cz:

1.5.2. Code submission verification

What if we standardize the commit style according to CZ, but some colleagues still commit according to non-standard format through Git commit?

  • We can restrict commits via commitlint;

1. Install @commitlint/ config-Conventional and @commitlint/ CLI

npm i @commitlint/config-conventional @commitlint/cli -D
Copy the code

2. Create the commitlint.config.js file in the root directory and configure commitLint

module.exports = {
  extends: ['@commitlint/config-conventional']}Copy the code

3. Use husky to generate the commit-msg file and verify the commit information:

npx husky add .husky/commit-msg "npx --no-install commitlint --edit $1"
Copy the code

Second, third-party library integration

2.1. The vue. Config. Js configuration

Vue.config.js can be configured in three ways:

  • Method 1: Directly use the options provided by the CLI to configure:
    • For example, publicPath: configures the subdirectory for application deployment (the default is/, which is equivalent to deploying inhttps://www.my-app.com/);
    • For example, outputDir: modify the output folder;
  • Method 2: Use configureWebpack to modify the WebPack configuration.
    • It could be an object, it could be merged directly;
    • It can be a function that receives a config that can be used to modify the configuration.
  • Method 3: Modify the WebPack configuration using chainWebpack:
    • Is a function that receives a Webpack-chain-based config object that can be modified.
const path = require('path')

module.exports = {
  outputDir: './build'.// configureWebpack: {
  // resolve: {
  // alias: {
  // views: '@/views'
  / /}
  / /}
  // }
  // configureWebpack: (config) => {
  // config.resolve.alias = {
  // '@': path.resolve(__dirname, 'src'),
  // views: '@/views'
  / /}
  // },
  chainWebpack: (config) = > {
    config.resolve.alias.set(The '@', path.resolve(__dirname, 'src')).set('views'.'@/views')}}Copy the code

2.2. The vue – integration of the router

Install the latest version of vue-Router:

npm install vue-router@next
Copy the code

Create a Router object:

import { createRouter, createWebHashHistory } from 'vue-router'
import { RouteRecordRaw } from 'vue-router'

const routes: RouteRecordRaw[] = [
  {
    path: '/'.redirect: '/main'
  },
  {
    path: '/main'.component: () = > import('.. /views/main/main.vue')}, {path: '/login'.component: () = > import('.. /views/login/login.vue')}]const router = createRouter({
  routes,
  history: createWebHashHistory()
})

export default router
Copy the code

Install the router:

import router from './router'

createApp(App).use(router).mount('#app')
Copy the code

Configure jumps in app.vue:

<template>
  <div id="app">
    <router-link to="/login">The login</router-link>
    <router-link to="/main">Home page</router-link>
    <router-view></router-view>
  </div>
</template>
Copy the code

2.3. Vuex integration

Install vuex:

npm install vuex@next
Copy the code

Create a store object:

import { createStore } from 'vuex'

const store = createStore({
  state() {
    return {
      name: 'coderwhy'}}})export default store
Copy the code

Install the store:

createApp(App).use(router).use(store).mount('#app')
Copy the code

For use in app.vue:

<h2>{{ $store.state.name }}</h2>
Copy the code

2.4. Element – plus integration

Element Plus, a Vue 3.0-based desktop component library for developers, designers, and product managers:

  • I believe many of you have used element-UI in Vue2, and element-Plus is a UI component library developed by Element-UI for VUE3.
  • It works the same way as many other component libraries, so learn element-Plus and others like Ant-Design-Vue, NaiveUI, and VantUI;

The installation element – plus

npm install element-plus
Copy the code

2.4.1. Global import

One way to introduce element-Plus is global import, which means that all components and plug-ins are automatically registered:

import ElementPlus from 'element-plus'
import 'element-plus/lib/theme-chalk/index.css'

import router from './router'
import store from './store'

createApp(App).use(router).use(store).use(ElementPlus).mount('#app')
Copy the code

2.4.2. Local introduction

When a component is used in development, it is introduced into a component:

<template> <div id="app"> <router-link to="/login"> </router-link> <router-view></router-view> <h2>{{$store.state.name}}</h2> <el-button> Default button </el-button> <el-button Type ="primary"> </el-button> <el-button type="success"> </el-button> <el-button type="warning"> </el-button> <el-button type="danger"> </el-button> </div> </template> <script lang="ts"> import { defineComponent } from 'vue' import { ElButton } from 'element-plus' export default defineComponent({ name: 'App', components: { ElButton } }) </script> <style lang="less"> </style>Copy the code

However, we will find that there is no corresponding style. There are two ways to introduce styles:

  • Global reference style (as you did before);
  • Local reference styles (via Babel’s plug-in);

1. Install the Babel plugin:

npm install babel-plugin-import -D
Copy the code

2. Configure the Babel. Config. Js

module.exports = {
  plugins: [['import',
      {
        libraryName: 'element-plus'.customStyleName: (name) = > {
          return `element-plus/lib/theme-chalk/${name}.css`}}]],presets: ['@vue/cli-plugin-babel/preset']}Copy the code

But there’s still a downside:

  • These components need to be imported and registered with components when they are used in multiple pages or components.
  • So we can register them globally once;
import {
  ElButton,
  ElTable,
  ElAlert,
  ElAside,
  ElAutocomplete,
  ElAvatar,
  ElBacktop,
  ElBadge,
} from 'element-plus'

const app = createApp(App)

const components = [
  ElButton,
  ElTable,
  ElAlert,
  ElAside,
  ElAutocomplete,
  ElAvatar,
  ElBacktop,
  ElBadge
]

for (const cpn of components) {
  app.component(cpn.name, cpn)
}
Copy the code

2.5. Axios integration

Install axios:

npm install axios
Copy the code

Encapsulation axios:

import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
import { Result } from './types'
import { useUserStore } from '/@/store/modules/user'

class HYRequest {
  private instance: AxiosInstance

  private readonly options: AxiosRequestConfig

  constructor(options: AxiosRequestConfig) {
    this.options = options
    this.instance = axios.create(options)

    this.instance.interceptors.request.use(
      (config) = > {
        const token = useUserStore().getToken
        if (token) {
          config.headers.Authorization = `Bearer ${token}`
        }
        return config
      },
      (err) = > {
        return err
      }
    )

    this.instance.interceptors.response.use(
      (res) = > {
        // Intercepts the data of the response
        if (res.data.code === 0) {
          return res.data.data
        }
        return res.data
      },
      (err) = > {
        return err
      }
    )
  }

  request<T = any>(config: AxiosRequestConfig): Promise<T> {
    return new Promise((resolve, reject) = > {
      this.instance
        .request<any, AxiosResponse<Result<T>>>(config)
        .then((res) = > {
          resolve((res as unknown) as Promise<T>)
        })
        .catch((err) = > {
          reject(err)
        })
    })
  }

  get<T = any>(config: AxiosRequestConfig): Promise<T> {
    return this.request({ ... config,method: 'GET' })
  }

  post<T = any>(config: AxiosRequestConfig): Promise<T> {
    return this.request({ ... config,method: 'POST' })
  }

  patch<T = any>(config: AxiosRequestConfig): Promise<T> {
    return this.request({ ... config,method: 'PATCH'})}delete<T = any>(config: AxiosRequestConfig): Promise<T> {
    return this.request({ ... config,method: 'DELETE'}}})export default HYRequest
Copy the code

2.6. VSCode configuration

{
  "workbench.iconTheme": "vscode-great-icons"."editor.fontSize": 17."eslint.migration.2_x": "off"."[javascript]": {
    "editor.defaultFormatter": "dbaeumer.vscode-eslint"
  },
  "files.autoSave": "afterDelay"."editor.tabSize": 2."terminal.integrated.fontSize": 16."editor.renderWhitespace": "all"."editor.quickSuggestions": {
    "strings": true
  },
  "debug.console.fontSize": 15."window.zoomLevel": 1."emmet.includeLanguages": {
    "javascript": "javascriptreact"
  },
  "explorer.confirmDragAndDrop": false."workbench.tree.indent": 16."javascript.updateImportsOnFileMove.enabled": "always"."editor.wordWrap": "on"."path-intellisense.mappings": {
    "@": "${workspaceRoot}/src"
  },
  "hediet.vscode-drawio.local-storage": "eyIuZHJhd2lvLWNvbmZpZyI6IntcImxhbmd1YWdlXCI6XCJcIixcImN1c3RvbUZvbnRzXCI6W10sXCJsaWJyYXJpZXNcIjpcImdlbmVyYWw7YmFzaWM7YXJ yb3dzMjtmbG93Y2hhcnQ7ZXI7c2l0ZW1hcDt1bWw7YnBtbjt3ZWJpY29uc1wiLFwiY3VzdG9tTGlicmFyaWVzXCI6W1wiTC5zY3JhdGNocGFkXCJdLFwicGx 1Z2luc1wiOltdLFwicmVjZW50Q29sb3JzXCI6W1wiRkYwMDAwXCIsXCIwMENDNjZcIixcIm5vbmVcIixcIkNDRTVGRlwiLFwiNTI1MjUyXCIsXCJGRjMzMzN cIixcIjMzMzMzM1wiLFwiMzMwMDAwXCIsXCIwMENDQ0NcIixcIkZGNjZCM1wiLFwiRkZGRkZGMDBcIl0sXCJmb3JtYXRXaWR0aFwiOjI0MCxcImNyZWF0ZVR hcmdldFwiOmZhbHNlLFwicGFnZUZvcm1hdFwiOntcInhcIjowLFwieVwiOjAsXCJ3aWR0aFwiOjExNjksXCJoZWlnaHRcIjoxNjU0fSxcInNlYXJjaFwiOnR ydWUsXCJzaG93U3RhcnRTY3JlZW5cIjp0cnVlLFwiZ3JpZENvbG9yXCI6XCIjZDBkMGQwXCIsXCJkYXJrR3JpZENvbG9yXCI6XCIjNmU2ZTZlXCIsXCJhdXR vc2F2ZVwiOnRydWUsXCJyZXNpemVJbWFnZXNcIjpudWxsLFwib3BlbkNvdW50ZXJcIjowLFwidmVyc2lvblwiOjE4LFwidW5pdFwiOjEsXCJpc1J1bGVyT25 cIjpmYWxzZSxcInVpXCI6XCJcIn0ifQ=="."hediet.vscode-drawio.theme": "Kennedy"."editor.fontFamily": "Source Code Pro, 'Courier New', monospace"."editor.smoothScrolling": true."editor.formatOnSave": true."editor.defaultFormatter": "esbenp.prettier-vscode"."workbench.colorTheme": "Atom One Dark"."vetur.completion.autoImport": false."security.workspace.trust.untrustedFiles": "open"."eslint.lintTask.enable": true."eslint.alwaysShowStatus": true."editor.codeActionsOnSave": {
    "source.fixAll.eslint": true}}Copy the code