“This article has participated in the good article call order activity, click to see: back end, big front end double track submission, 20,000 yuan prize pool for you to challenge!”

This article is a tutorial on how to build a Vue3+Typescript development environment. It may involve some basics, but also some practical experience and lightning rod. If you’re an older driver, you can skip through it, but if you’re new to the front end or you haven’t built a full development environment yet, I hope you follow this article and build one yourself. Many people get bored when they see words like vue-router,Vuex, Eslint, etc. Do you really know how they are integrated into a project?

True knowledge comes from practice

The infrastructure

Initialize the project

Create the basic project architecture with Vite. If you haven’t already installed Vite, a quick install is as follows:

  • npm
npm install @vitejs/app
Copy the code
  • yarn
yarn create @vitejs/app
Copy the code

Initialize the project with Vite:

npm init @vitejs/app v3-ts-project
Copy the code

Follow the prompts to select the template we need. Here we choose the template of VUE + TS.

Do a preliminary cleanup of the project and remove the HelloWorld component and its associated references.

Integrated routing

npm install vue-router@4
Copy the code

After the installation, do some configuration for Vite before configuring the route:

Configure an alias

  • resolve.alias

When using an alias for a file system path, always use an absolute path. The alias values of relative paths are used intact and therefore cannot be resolved properly.

We first need to install the @types/node package

npm install @types/node --save-dev
Copy the code

Edit the vite. Config. Js

// vite.config.js

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  base:'/'.// Develop a common base path
  resolve: {alias: {The '@':resolve(__dirname,'src'), // Set @ to the/SRC directory
      // '@components':resolve(__dirname,'src/components'),
      // '@pages':resolve(__dirname,'src/pages')}}})Copy the code

Setting aliases reduces relative paths in the code, does not have to worry about hierarchy issues, the path is clear, easy to maintain the code, and has gradually become a code specification.

Set up the<router-view>

// App.vue

<template>
  <router-view></router-view>
</template>

<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
  name: 'App',})</script>.Copy the code

Configuring routing Entry

Create the router/index.ts file in the SRC directory.

// /src/router/index.ts

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

import Home from '@/views/home/index.vue';
import Detatil from '@/views/detail/index.vue';
const NotFound = () = > import('@/views/notFound/notFound.vue') // Dynamic import

const routes:Array<RouteRecordRaw> = [
  {
    path: '/'.name: 'Home'.component: Home,
  },
  {
    path: '/detail'.name: 'detail'.component: Detatil,
  },
  {
    path: '/:pathMatch(.*)*'./ / 404
    name: 'notFound'.component: NotFound,
  },
];

const router = createRouter({
  history: createWebHashHistory(),
  routes,
});

export default router;
Copy the code

If you change the introduction of NotFound to

import NotFound from '@/views/notFound/notFound.vue';
Copy the code

When the system loads routes, it will load all statically imported components at once, as shown in the figure:

Dynamic import means that components are loaded only when they are accessed to the corresponding path. In order to reduce resource consumption and improve the display speed of the home page, we try to use dynamic import for non-main pages.

mount

// main.ts

import { createApp } from 'vue'
import App from './App.vue'
import router from './router';

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

Our routing configuration basics are complete.

For details, see the vue-Router official website.

integrationvuex

First installationvuex:

  • npm
npm install vuex@next --save
Copy the code
  • yarn
yarn add vuex@next --save
Copy the code

Creating a directory structure

Create the following files in the SRC directory:

  • /src/store/index.ts
  • /src/store/modules/user.ts

To edit the user first. Ts

// src/store/index.ts

// Declare the type for store state
export interface State {
  name: string,
}

// Default state
const defaultState = {
  name: ' '
}

const user = {
  namespaced: true.state: () = > defaultState,
  mutations: {
    setName(state:typeof defaultState, payload: string){
      state.name = payload
    }
  },
  actions: {
    patchName (context: any) {
      context.commit('setName'.'Ming')}},getters: {
    getDemoName(state:typeof defaultState){
      return state.name + 'demo'; }}}export default user;
Copy the code

Editing the ts

// /src/sotre/index.ts

import { InjectionKey } from 'vue'
import { createStore, Store } from 'vuex'

import user from './modules/user';


// Define the injection key
export const key: InjectionKey<Store<any>> = Symbol('Unique identification of store');

export const store = createStore({
  modules:{
    user
  }
})
Copy the code

mount

// main.ts

import { createApp } from 'vue'
import App from './App.vue'
import router from './router';
import { store, key } from './store';

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

The VUEX configuration is complete.

Note: In Typescript, when we use useStore in a component, we need to pass the key in, otherwise we won’t get the store.

Environment variables and patterns

Vite provides a special global object import.meta. Env that exposes the current environment variables. Vite uses Dotenv to load environment variable files from your environment directory.

Env.[mode] # Loads only in the specified mode, but is ignored by gitCopy the code

To prevent accidental leakage of environment variables, vite specifies that only variables prefixed with vite_are exposed to import.meta. Env objects.

OK, let’s do it:

First create three files in the root directory:

.env.local // Development environment.env.staging // pre-release environment.env.production // Production environmentCopy the code

They read roughly as follows:

.env.local:

# .env.local

NODE_ENV=development

VITE_API_BASE_URL="https://development.com"
Copy the code

.env.staging:

# .env.staging

NODE_ENV=staging

VITE_API_BASE_URL="https://staging.com"
Copy the code

.env.production:

# .env.production

NODE_ENV=production

VITE_API_BASE_URL="https://production.com"
Copy the code

By default, Vite only has development and production environments, but we can add more environments with more –mode.

Let’s edit package.json and change the launch command:

// package.json
...
"scripts": {
  "dev": "vite --mode development",
  "build": "vue-tsc --noEmit && vite build",
  "prebuild": "vue-tsc --noEmit && vite build --mode staging",
  "serve": "vite preview",
  "prepare": "husky install"
},
Copy the code

So that when we

  • runnpm run devIs read by default.env.localConfiguration file of
  • runnpm run prebuildIs read by default.env.stagingConfiguration file of
  • runnpm run buildIs read by default.env.productionConfiguration file of

Variables from the file are added to the import.meta. Env object.

This will allow us to release versions for different environments by executing different compilation commands through CI for different branches (more on CI in the future).

integrationaxios

Under normal circumstances, we need to encapsulate the request and do unified access management for the request, such as setting some custom request header parameters, such as token, and so on. At the same time, we also need to do format conversion for the data of the request result and deal with global error.

The installationaxios

npm install axios -D
Copy the code

Let’s create a new untils/axios.ts file in the SRC directory:

// src/untils/axios.ts

import axios from 'axios';

// Environment variables
const API_BASE_URL: any = import.meta.env.VITE_API_BASE_URL;

const instance = axios.create({
  baseURL: API_BASE_URL,
  timeout: 20000});// Add a request interceptor
instance.interceptors.request.use(
  (response) = > {
    // Set the token...
    response.headers = {};
    return response;
  },

  /** * do the same thing for your project ** * do the same thing for your project */
  (error) = > Promise.reject(error)
);

// Add response interception
axios.interceptors.response.use(
  (response) = >
    /** * do some customizable data processing operations */
    response,
  (error) = > {
    const { code } = error.response.status;
    /** * do some global error handling */
    switch (code) {
      case 401:
        /** Permission processing */
        break;
      case 500:
        break;
      default:
        break;
    }
    return Promise.reject(error); });export default axios;
Copy the code

use

The introduction of axios:

import axios from '@/untils/axios.ts';

const test = () = > {
  axios.get('https://www.fastmock.site/mock/2f82fcaef2f445bf7e05e7ff91eb86b0/api/getProducts')
  .then((res) = > {
    console.log(res);
  }).catch((err) = > {
    console.log(err);
  });
}
Copy the code

For more information about the use of the Axios request method, see the website: Dispatchers

Note: I’m going to share an online generate request url: FastMock. It works!

Integrated UI Framework

Currently, there are several UI frameworks that support VUE3:

  • Element Plus
  • Vant
  • Vuetify

Choose Element Plus here, and refer to the documentation for other frameworks.

Installation:

npm install element-plus --save
Copy the code

Mount in main.ts

// main.ts

import { createApp } from 'vue'

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

import App from './App.vue'
import router from './router';
import { store, key } from './store';

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

Integrated CSS preprocessor

less

npm install less -D
Copy the code

sass

npm install sass -D
Copy the code

Code specification

integrationeslint

Eslint is a checking mechanism that effectively helps us unify specifications. This is essential for multi-person development teams and projects. With more and more users, a basic and perfect rule system has been formed, which does not require us to do too much configuration operation. There are mature rule schemes for us to choose. Standing on the shoulders of giants, we will avoid many detours. Take a look at:

The installationeslint

npm install eslint --save-dev
Copy the code

Next, set a configuration file:

Note: Run the following command at the terminal in the project’s root directory

./node_modules/.bin/eslint --init
Copy the code

Then a series of problems will appear in the terminal, we choose the following options in turn:

  • To check syntax, find problems, and enforce code style
  • JavaScript modules (import/export)
  • Vue.js
  • Yes
  • Node
  • Use a popular style guide
  • Reality: github.com/airbnb/java… (The most popular rule scheme in the community)
  • JavaScript

When you are done, you will be prompted to install some dependencies. Select install.

When the installation is complete, the.eslintrc.js file will appear in the root directory:

// .eslintrc.js

module.exports = {
  env: {
    browser: true.es2021: true.node: true,},extends: [
    'plugin:vue/essential'.'airbnb-base',].parserOptions: {
    ecmaVersion: 12.parser: '@typescript-eslint/parser'.sourceType: 'module',},plugins: [
    'vue'.'@typescript-eslint',].rules: {}};Copy the code

You can configure some custom team rules in rules, see ESLint.

use

Next you can run the command to check your file:

./node_modules/.bin/eslint Your filesCopy the code

Such as:

./node_modules/.bin/eslint ./src/store/index.ts
Copy the code

I have checked the previous store/index.ts file and found many problems:

If you want auto-fix, you can add the –fix option at the end:

./node_modules/.bin/eslint ./src/store/index.ts --fix
Copy the code

There are some issues that esLint itself can’t handle with auto-fixes, such as:

We need to do some configuration for ESLint:

// .eslintrc.js
module.exports = {
  env: {
    browser: true.es2021: true.node: true,},extends: ['plugin:vue/essential'.'airbnb-base'.'prettier'].parserOptions: {
    ecmaVersion: 12.parser: '@typescript-eslint/parser'.sourceType: 'module',},plugins: ['vue'.'@typescript-eslint'.'prettier'].rules: {
    'vue/no-multiple-template-root': 'off'.// Resolve the error that the top level of the template can only return one element
    'import/extensions': [ 
      // Other files do not need extension, import vue files need extension
      'error'.'never',
      {
        vue: 'always'.// If you introduce a vue module into ts without adding the. Vue suffix, ts will not find the module},].// Resolve the import file suffix problem
    'import/no-unresolved': [ // Resolve the unrecognized problem
      2,
      {
        ignore: ['/'],},],"import/no-extraneous-dependencies": ["error", { "devDependencies": true}].// Resolve the dependency problem
    "no-param-reassign": [ // Fix the problem that parameters cannot be modified directly
      "error",
      {
        "props": true."ignorePropertyModificationsFor": [
          "request"."res"."response"."state"]}]},};Copy the code

Note: introducing a vue module in TS without the. Vue suffix will cause ts to not find the module, so set esLint’s verification file suffix configuration.

Installing a plug-in

Plugins are actually installed to improve our development experience by not having to run commands to lint code every time. Different ides also need to install the corresponding plug-in, you can check the official website query.

The author uses vsCode as an example to install the ESLint plugin in vsCode’s plugin market:

Then open vscode settings. json (Command +shift+p) and add the following Settings:

// setting.json."editor.codeActionsOnSave": {
  "source.fixAll.eslint": true
}
Copy the code

This way we will execute ESLint when we save the code

Basic configurations are complete.

integrationprettier

The installationprettier

Liverpoolfc.tv: prettier. IO /

npm install --save-dev --save-exact prettier
Copy the code

Create a configuration file called.prettierrc.json in the root of your project to tell the IDE you’re using prettier.

You can also create a.prettierIgnore configuration file to ignore the directory where you don’t want prettier, just like.gitignore.

We can now use the command line to format files,. For all files:

npx prettier --write .
Copy the code

We can also configure setting.json to automatically format after saving:

// setting.json

"editor.formatOnSave": true.Copy the code

After formatting we found some changes:

Prettier before

<button @click="setName" @drag="setName" @mousedown="setName" @mouseover="setName"</button>Copy the code

After the prettier

<button
  @click="setName"
  @drag="setName"
  @mousedown="setName"
  @mouseover="setName"</button>Copy the code

In addition, there are other changes, such as single quotes becoming double quotes, which conflict with our previous Eslint. But what if I want to keep both formats?

Resolve the conflict

Eslint-config-prettier esLint-config-prettier esLint-config-prettier esLint-config-prettier esLint-config-prettier

npm install eslint-config-prettier -D
Copy the code

Then add the configuration in.eslintrc.js:

.extends:[
  ...
  "prettier" // Always put it last to ensure that ESLint is overridden
]
Copy the code

This means that the formatting priority Prettier is higher than Eslint.

13, “Prettier” (Prettier, Prettier, Prettier, Prettier, Prettier)

{
  "singleQuote": true
}
Copy the code

So we have to satisfy the above two situations, but also there is a problem, if we do not wish to meet the rules also prompted by Eslint Prettier.

We install eslint – plugin – prettier will prettier rules in the form of a plug-in to join eslint, finally through eslint to error.

npm install eslint-plugin-prettier -D
Copy the code

Edit the.eslintrc.js file:

plugins: ["vue"."@typescript-eslint"."prettier"].rules: {..."prettier/prettier": "error",},Copy the code

The code specification for our development environment is then configured.

integrationstylelint

Stylelint is used to check whether the style conforms to the specification.

Install stylelint

npm install --save-dev stylelint stylelint-config-standard
Copy the code

Stylelint-config-standard are some of the default style rules recommended by Stylelint.

Then create a.stylelintrc.json configuration file in the project root directory and edit it.

// .stylelintrc.json

{
  "extends": "stylelint-config-standard"
}
Copy the code

Now we can format the style code by command

npx stylelint "**/*.vue"
Copy the code

In order to be more efficient, we still need to use the plugin in the IDE to help us with lint. Again, using vscode as an example, search for stylelint in the plugin market and install the following plugin.

For convenience, let’s edit the setting.json file:

// setting.json."editor.codeActionsOnSave": {
  "source.fixAll.eslint": true."source.fixAll.stylelint": true
},
Copy the code

integrationhusky

If the project uses Git to commit the code.

The purpose of Husky is to ensure that submitted code is also validated by Lint. Although we have configured the code specification in the project, we can not ensure that every developer’s IDE has installed the corresponding plug-in or Settings to ensure that our code specification is implemented. If you don’t verify at the time you submit the code, the code that doesn’t conform to the rules will be submitted anyway, and our code specification will remain void. So we need to verify at the time of submission.

The installationhusky:

npx husky-init && npm install 
Copy the code

After the installation,

  • A.husky folder is generated in our root directory, which contains the hook execution file. The pre-commit hook is executed before committing the information, that is, when we commit git.

  • Json scripts will generate a new command: “prepare”: “husky install”.

Let’s change the pre-commit command again:

// pre-commit #! /bin/sh . "$(dirname "$0")/_/husky.sh" .. /node_modules/.bin/eslint --fixCopy the code

After husky is configured, esLint will format the code when we submit it.

However, this formatting is for all the files in the project, and every commit requires all the code to be formatted, which can waste a lot of time and resources if the project is large. We wanted to format only the changed code that had been submitted this time, so we needed to use the Lint-Staged tool to optimize it.

The installationlint-staged

npm install lint-staged -D
Copy the code

You can also use

npx mrm@2 lint-staged
Copy the code

This command will help you install and configure both Husky and Lint-Staged.

Next we modify the package.json file:

// package.json."lint-staged": {
    "*.{ts,vue,js}": "./node_modules/.bin/eslint --fix"
}
Copy the code

Modify the pre – commit:

#! /bin/sh . "$(dirname "$0")/_/husky.sh" npx lint-stagedCopy the code

At this point we have all the code specifications configured.

To verify, I’ll remove the.eslintrc.js configuration that solves errors that ESLint cannot automatically fix, and then submit the code:

Note: If you are not doing Eslint locally, if Eslint passes when it is submitted, it will still be submitted, but your local code will not have Eslint results, meaning that your local code will still have no Eslint code, but the remote code is Eslint code.

When the result is as expected, we revert to the configuration of.eslintrc.js:

The configuration is successful.

If you don’t have an IDE plug-in installed, you’ll need to lint it when you submit. If you don’t have an IDE plug-in installed, you’ll need to add a configuration:

// package.json."lint-staged": {
    "*.{js,vue,ts}": "./node_modules/.bin/eslint --fix"."*.{html,vue,css,sass,scss}": "./node_modules/.bin/stylelint --fix"
  }
Copy the code

Submit specifications

Introduction of specification

When we submit the code through Git, we need to fill in message, otherwise we cannot submit it. In general, we have to make sure that our submissions are focused, but messages have no rules, and each developer may have his or her own style. For example:

  • “Added shopping cart functionality.”
  • “Fixed bug where new items were not added to the shopping cart”
  • “Refactoring the shopping cart.”

Time is long, and then submit record panel would be disastrous, more like reading novels, if one day the product to you say I’m going to take up a shopping cart version of the function, then you may go to submit record inside to find one to submit code changes, the find, one silly, should be heard to say to want to take up a shopping cart version of the product function to silly. This is just a scenario. In many cases, we will check the submission record panel. At this time, we need a specification to constrain our submission format, so that we can clearly know what the contents of my submission are. One of the most popular in the community is Conventional Commits, which is inspired by Angular’s commit guidelines and provides a set of simple rules that create clear commit rules. Let’s take a look at these:

The submission record is divided into three parts: type, body and footer

<type>[optional scope]: <description>

[optional body]

[optional footer(s)]
Copy the code

Type: Mandatory, the type of submission. There are the following types:

type describe
feat New features
fix Fix the bug
docs Modify the document
refactor Code refactoring, no new features and bug fixes
build Changes to the build process, new dependencies, tools, etc. (e.g. webPack changes)
style Only whitespace, indentation, and so on are modified, without changing the code logic
perf Improved performance and presentation modifications
chore Modify the build process or tools
test Modification of test cases
ci Automatic process configuration modification
revert Roll back to the previous version

Body: Mandatory, the main description of this submission. Multiple lines are available.

Footer: Mandatory for major and destructive changes or incompatible changes that describe the scope of impact. Otherwise, leave it empty.

So what should we do?

We can use Commitizen to help us quickly build the commit template, but still consider the differences between people, some people use the Git command line, some people are used to git visual tools, and the tools are derived from more situations, unified cannot be unified, they can not be unified by you. So there wouldn’t have Commitizen, solve the problem or the solution, we control the admission rules, to submit format study, at the time of submission by commitlint we go to check your submission information is in accordance with the specification. In many cases, there is no way to regulate everyone’s behavior 100 percent. Many norms are maintained, recognized and implemented by everyone together.

integrationcommitlint

First install commitLint:

npm install --save-dev @commitlint/{config-conventional,cli}
Copy the code

Windows environment:

npm install --save-dev @commitlint/config-conventional @commitlint/cli
Copy the code

Create a configuration file (commitlint.config.js) in the root directory

// commitlint.config.js

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

Then we need to use husky’s commit-msg hook to execute the command:

npx husky add .husky/commit-msg 'npx --no-install commitlint --edit
Copy the code

Now that we’ve configured it, let’s test it.

Non-standard submission:

Specification submission:

portal

The configuration is successful.

automation

When it comes to front-end automation, continuous integration, continuous delivery, and continuous deployment is a very important part of the Internet agile development process, often used for daily compilation, unit testing, building, packaging, and automated deployment. From we submit the code to release behavior of the process is usually repeated, we through software, programs make this process automation, and continuous integration, continuous delivery, continuous deployment is the process of different stage, we commit the code to test automation often called continuous integration (CI), build, release test version, Delivery to a quality team is called continuous delivery (CD), and automatic release to an online environment is called continuous deployment (CD).

gitlab-ci

We mainly introduce Gitlab-CI here.

First, the general mechanism by which it works: Whenever we push/merge code, Gitlab recognizes a configuration file in our project called.gitlab-ci.yml. Gitlab-ci provides gitlab-Runner software to create a program that runs these tasks.

Now that we know the mechanics, let’s look at some abstractions:

Let’s start with a picture:

The execution process of.gitlab-ci.yml, which usually has multiple task phases, can be literally understood as Pipeline.

【stage】 : A stage in which there is at least one or more tasks, and the next stage is executed only after the completion of one stage.

[job] : tasks, which we write in the.gitlab-ci.yml configuration file, are the smallest units in the CI system that can be controlled and run, such as NPM install.

Since gitlab-runner of many companies is configured by students at the back end, I will not say much about what is involved behind it. It is only necessary to understand some related concepts and operation mechanism. Students interested in the front end can practice it in depth by themselves.

In this section, we will mainly talk about how to configure the configuration file of. Gitlab-ci.yml.

In the.gitlab-ci.yml file you can define the following things:

  • The script you want to run.
  • Other configuration files and templates you want to include.
  • Dependencies and caching.
  • Commands to run sequentially and commands to run in parallel.
  • Where you want to deploy the application.
  • Whether you want to run the scripts automatically or manually trigger any of them.

It is described according to a specific syntax, let’s look at an official example:

stages:  # Define phase
  - build  # the build phase
  - test   # test phase

build-code-job: # Define task name (custom)
  stage: build  # Execute in the build phase
  script: # Scripts that are executed sequentially
    - echo "Check the ruby version, then build some Ruby project files:" 
    - ruby -v 
    - rake
    
test-code-job1: # Define task name (custom)
  stage: test Execute in the test phase
  script: # Scripts that are executed sequentially
    - echo "If the files are built successfully, test some files with one command:" 
    - rake test1 
    
test-code-job2: # Define task name (custom)
  stage: test Execute in the test phase
  script:  # Scripts that are executed sequentially
    - echo "If the files are built successfully, test other files with a different command:" 
    - rake test2
Copy the code

First we defined two phases, build and Test. The build phase is executed first, then all build tasks are executed, and then test tasks are executed. Note: Different tasks in the same phase can be parallel. For example, in the test phase above, two tasks of test-code-job1 and test-code-job2 are run simultaneously, and unit testing is carried out at the same time, which greatly improves efficiency.

Let’s look at an actual project. Gitlab-ci.yml configuration file:

# cache node_modules
cache: 
  key: cache
  paths:
    - node_modules/

# Define stages
stages:
  - install
  - build
  - deploy

# Install phase task
job_install:
  stage: install
  only: # Limit the branch of code submission
    - /^master$|^pre$|^dev$|^release-\d{0,}.\d{0,}.\d{0,}$/ # Use regular matches
  script: # Execute command
    - yarn install
    - .

# Master Build phase task
job_build:
  stage: build
  only:
    - master
  script:
    - yarn build
  artifacts: # output
    paths:
      - dist
    expire_in: 120 mins # Valid time
    
# dev Build phase task
job_devbuild:
  stage: build
  only:
    - dev
  script:
    - yarn devbuild
  artifacts:
    paths:
      - dist
    expire_in: 120 mins
    
# Release build phase tasks
job_opsbuild:
  stage: build
  only:
    - /^release-\d{0,}.\d{0,}.\d{0,}$/
  script:
    - yarn opsbuild
  artifacts:
    paths:
      - dist
    expire_in: 120 mins

# Deploy phase task
job_deploy:
  stage: deploy
  only:
    - /^master$|^pre$|^dev$|^release-\d{0,}.\d{0,}.\d{0,}$/
  script:
    - .
Copy the code

First, the packages under node_modules are cached, and three phases are defined: install, build, and deploy. Branches are judged by only, and different build commands are executed to achieve continuous delivery in different environments.

For more detailed configuration details, please refer to the portal website.

conclusion

Our VUE3 development project is basically set up, which integrates routing management, management, UI framework, code specification, submission specification and automated construction. This project can basically meet our daily development requirements.

In the process of writing this article, in order to express it as succinct and easy to understand as possible, the author also consulted a lot of materials and the official website, and had a feeling of reviewing the old and learning the new. While sharing knowledge, the author also learned knowledge. I hope everyone can make progress together.

I’ll put this project up on Github.

Address: v3 – ts – project

If you have any questions, welcome to comment and correct, thank you.