I’m participating in nuggets Creators Camp # 4, click here to learn more and learn together!

This article is not just about building scaffolding, but also taking you through every step, and even every configuration item, and the knowledge of each configuration

Vue3, Vite, TypeScript, ESlint, Stylelint, VuE-Router, Axios, Pinia

The initialization time of this article is 2022/2/19. The latest vite version is 2.8.0

Because I want to write each point in detail, there will be a lot of content. The paper is mainly divided into two parts:

The first part is the construction of the development environment and the basic capabilities of scaffolding:

  • Basic Environment Preparation
  • Initialize the Vite project
  • Extend the Vite configuration
  • Configuration TypeScript
  • Access code specification

The second part is the construction of application-layer capacity:

  • Access to the vue – the router
  • Access Axios
  • Access to the UI library
  • Access Piniainia)
  • Access Echarts5

Source code address: github.com/JasonLuox/f…

The content is too much, the author’s ability is also limited, it is inevitable that there will be omissions and mistakes, welcome to point out in the comment section, all reasonable criticism and suggestions I will accept and express thanks ~

Writing in the front

Back in the beginning of last year, there was a comment on the changes in the front end from Utah (it’s good for us vUE developers to keep an eye on what Utah is saying and doing) :

It seemed like vite2.0 was just around the time, and I was so excited to try it out. I have to say, with the speed of Webpack, Vite was a miracle!

At that time, I was just in charge of the whole UI reconstruction of the project, and I had certain cognition and proficiency in the whole front-end framework system used by the project, so I also tried to build the vuE3 + Vite framework system. At that time stepped on a lot of pits, as we all know, when a new technology comes out, it is difficult to search through the search engine to find the relevant tutorial/error solutions, the only valuable reference is official documents and issues. At that time, after the end of the pit, I actually had the intention to write such an article, but the procrastination let me successfully put off until now.

Over the past year, I have also seen many similar articles in various public accounts and blogs. Although writing this article now has the suspicion of refried rice, but just with the help of gold digging activities, or plan to finish this pigeon long article through their own ability, and to present more details as far as possible. I have prepared a brand new environment, while building while writing this article, hands-on practice is the fastest way to master ability/find problems!

Old project upgrade suggestion

Vue3 has been released for a long time (when it was first released, most people were in the wait-and-see mode, but now they are actively embracing it. I have to say: Say yes after using it!) With faster speeds and more efficient syntax, the ecosystem has gradually improved, making it easier to develop small and medium-sized applications. Looking at the VUe2 project in the code repository, it is inevitable to have some bad thoughts. So should we upgrade the VUe2 project?

  • If your company has a mature UI specification, the UI specification is usually based on a specific UI library, so upgrading from VUe2 to VUe3 requires you to consider whether the UI library used in your previous project provides a compatible version of VUe3.

    This is a pit, I have been trying to upgrade the company’s project to VUe3, but the VUe3 adaptation version of UI library is still under development and has not been officially released, so now I can only wait, but the framework is backward, the technology must first, the technology reserves of developers must always keep in the forefront of the industry to not be eliminated!

  • Although VUe3 is almost a comprehensive dimension reduction blow to VUe2, if it is a large volume product, I suggest maintaining the development of the old version and using VUe3 + Vite again in the new project. There is a certain gap between VUe2 and VUe3 in terms of grammar and difficulty in getting started. Blind upgrade will not only increase investment in manpower and resources (although for technologists are positive correlation, learn new skills, to develop more efficient code), but also can increase the risk of delay to product normal iteration, always maintain cognitive: is not the only technology developers in a team, more products, design, interaction, testing and other aspects of cooperation.

  • Of course, the above is only a superficial personal view. The specific situation also depends on the recognition and investment of each technical team to the new technology, and each technical leader needs to consider the whole.

Since you are starting from scratch, you must install node:

The first part

0. Install Nodejs

Why nodeJS?

(Haha, I remember it was a background developer who asked me this question, but I didn’t answer it at that time)

Node.js is an open source, cross-platform execution environment that can run JavaScript on the server.

Just as a browser can provide an environment in which JS runs, Nodejs functions as a browser.

If you just run simple HTML, or if you just run packaged static files in production, you really don’t need Node.js. The purpose of Node.js is to provide the foundation of front-end engineering to facilitate your development and improve the efficiency of development.

For example, vuE-CLI scaffolding, such as the common package management tool NPM, such as the common packaging tool webpack/vite/rollup, etc., Node.js can provide the corresponding tool/wheel running environment, so that saves a lot of configuration process, improve efficiency.

compatibility

Vite requires node.js version >= 12.0.0

The installation

Open the NodeJS website and select the latest long term maintenance version to download (stability is what a standard development team needs, early versions are more suitable for solo workers/tech enthusiasts, I use Windows so I can only show Windows installation).

Installation is very simple, direct brainless next step on the line

There are some NPM modules that depend on the C/C ++ editing environment

Open the CLI (shortcut key) after the installationwin + rAfter the input cmd) inputnode -v

You can see the successfully installed version of Node.js, and that’s it!

If you can’t see it, you need to configure the environment variable (right-click this computer => Properties => Advanced system Settings => Advanced => Environment variable =>Path) and add a corresponding installation directory \nodejs. For example, if I install it by default, add a C:\Program Files\nodejs\.

Normal installation should help you to add environment variables by default, of course, there will be some unexpected need to manually add.

Install CNPM

Because NPM source is in foreign countries after all, it will be slow to use. We can install Taobao mirror CNPM to improve the installation speed

npm install -g cnpm -registry=https://registry.npm.taobao.org
Copy the code

The operation commands and usage of CNPM are the same as those of NPM

Check whether the installation is complete. CNPM -v

Of course, there are other package management tools yarn, PNPM, etc. Just choose one that you like to use

Initialize the Vite project

Home | Vite official Chinese documents

NPM 7+ Directly run NPM create vite@latest my-vue-app — –template vue-ts

  1. If the NPM is lower than 7+, upgrade the NPMnpm install npm -g
  2. You can also omit the following-- --template vue-tsParameters are manually selected
  3. Running this command using CNPM to specify project name and template does not take effect, very strange Bug

As you can see, a vite project named my-vue-app is generated in the current directory. The directory structure is as follows

├─ Public ├─ SRC │ ├─ Assets │ ├─ Components │ ├─ app.vue │ ├─ Env.d.ts Global Statement │ ├─ SRC │ ├─ Assets │ ├─ App.vue │ ├─ Env.d.ts Global Statement │ └ ─ ─ main. Ts main entrance ├ ─ ─ the gitignore git ignore configuration ├ ─ ─ index. The HTML template file ├ ─ ─ package. The json rely on package/run the script configuration file ├ ─ ─ the README. Md ├ ─ ─ tsconfig. Json ├─ └─ ├─ ├.configCopy the code

Run the command displayed on the command line after the initialization is successful

cd my-vue-app
npm install
npm run dev
Copy the code

As you can see, the project runs on port 3000 by default and took 398ms to build:

The browser opens at http://localhost:3000, with the iconic Vue home page and a simple accumulator component:

The initial project is complete, of course, as an enterprise application is certainly not adequate, the next extension is important.

Two, expand vite configuration

Instead of the familiar webpack, open the vite configuration file, vite.config.js, and you’ll find nothing:

True out of the box! Of course, for better expansion features and better development experience, can be indefineConfigAdd the following configuration to the function

Common base path base

If you need to deploy the project under a nested common path, just specify the Base configuration item and the paths of all resources will be overridden accordingly.

Resource urls introduced by JS, URL () references in CSS, and resources referenced in.html files are automatically adjusted during build to match this option. The default public path is /, which we specify as the current project root directory./

base: './'
Copy the code

Development server option Server

Vite will automatically run on local port 3000 when we run the service without any configuration, so we can extend the configuration

Server: {port: 4000, // Set the service startup port number, if the port is already in use, Vite will automatically try the next available port open: True, / / a Boolean | string set whether the service is started automatically open the browser, when this value as a string, can be used as a URL path name cors: {'/ API ': {target: 'http://127.0.0.1:8000', // whether to allow different sources secure: false, // support HTTPS rewrite: path => path.replace(/^/api/, '') } } }Copy the code

Proxy Proxy uses HTTP-proxy, and the usage is simple. The preceding configuration is to replace 127.0.0.1:4000/ API request URL with 127.0.0.1:8000, which is a common method for local development and debugging to solve cross-domain problems.

The alias resolve. Alias

During the development of our project, there will be many nested directories, so to find a directory often use relative path.. /.. /.. The alIas alIas allows us to quickly specify the directory of the first level, and reduces the consumption of the path index compared to the relative path, which is also a better solution in terms of performance

For better file management and a clearer directory hierarchy, we will now add the following directories under SRC, the purpose of each directory will be discussed later

├ ─ ─ the SRC │ ├ ─ ─ the router routing configuration │ ├ ─ ─ stores state management │ ├ ─ ─ typings ts public type │ ├ ─ ─ utils tools function encapsulation │ └ ─ ─ views the page viewCopy the code

Add alias configuration:

Import {resolve} from 'path' const pathResolve = (dir: string) => resolve(__dirname, dir) resolve: {alias: import {resolve} from 'path' const pathResolve = (dir: string) => resolve(__dirname, dir) resolve: {alias: {' @ ': pathResolve ('. / SRC), / / set point ` @ ` ` SRC ` catalog views. PathResolve ('./ SRC /views'), // set 'views' to './ SRC /views', same as components: pathResolve('./ SRC /components'), assets: pathResolve('./src/assets'), }, },Copy the code

@type/node = @type/node = @type/node

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

Build option Build

When deploying your application to production, simply run the NPM run build command to execute vuE-tsc –noEmit && vite build for package.json to validate the typescript type used in your project. After the verification succeeds, the package function is performed

Build: {outDir: 'dist', // Specify the packing path. The default is dist directory terserOptions: {compress: {keep_infinity: Drop_console: true, // Prevents Infinity from being compressed to 1/0, which may cause performance issues on Chrome. True // Production environment removes debugger},}, chunkSizeWarningLimit: 1500 // Limit for chunk size warnings (in KBS)}Copy the code

OutDir can be used to specify where to store the package files. The default is the dist folder in the root of the project

Terser is a JavaScript parser and Mangler/Compressor toolkit for ES6+. The terserOptions.compress property can be used to compress JS to reduce the size of the packaged file.

The default chunkSizeWarningLimit is 500. There is a warning when the size of a chunk exceeds 500 after packaging, which is too small in the actual project, so we set it to 1500 here

That’s it for the basic configuration of Vite, but there will be some tweaks later when other third-party libraries are introduced.

Complete configuration

The complete configuration of vite.config.js is as follows

import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import { resolve } from 'path' const pathResolve = (dir: string) => resolve(__dirname, dir) // https://vitejs.dev/config/ export default defineConfig({ plugins: [vue()], build: TerserOptions: {compress: {keep_infinity: {outDir: 'dist', // specify the packing path, which is the dist directory in the root of the project. Drop_console: true, // Prevents Infinity from being compressed to 1/0, which may cause performance issues on Chrome. True // Production environment remove debugger},}, chunkSizeWarningLimit: 1500 // Limit of chunk size warnings (in KBS)}, resolve: {alias: {'@': PathResolve ('./ SRC '), // set '@' to 'SRC' : pathResolve('./ SRC /views'), components: PathResolve ('./ SRC /components'), assets: pathResolve('./ SRC /assets'),},}, base: './', // Set the public base path server: {port: 4000, // Set the service startup port number open: true, // set whether the browser is automatically opened when the service starts cors: true, // allow cross-domain // set the proxy, according to the actual situation of our project configure proxy: {'/ API ': {target: 'http://127.0.0.1:8000', changeOrigin: true, secure: false, rewrite: path => path.replace(/^/ API /, '')}}}})Copy the code

Configure TypeScript

TypsScript profile

TypeScript is a strongly typed programming language that builds on JavaScript, giving you better tooling at any scale

TypeScript is a strongly typed javascript-based programming language that provides a better toolified experience for projects of any size.

Note: The above description is the official TypeScript definition.

It’s not uncommon to see people talking about how typescript is necessary for small projects or business scenarios that are so simple that they can be fully developed with just one or two front-end developments. Don’t you add development costs for nothing?

In fact, as a mature business developer, will find the use of front-end technology to come back and forth, Lu Xun said: to be good at learning new knowledge in the repetitive work. Therefore, when you find it difficult to learn something in the project in the team, besides job-changing, you can also consider adding some new technology to the project, such as Typecsript, which can not only reduce the output of bugs, but also improve your knowledge reserve, paving the way for future large-scale projects with multi-person cooperation. Why not?

And on the Vite project:

  • Vite natural support introduced.tsFile.
  • Vite useesbuildConvert TypeScript to JavaScript, approximatelytsc20~30 times faster, while HMR updates reflect less than 50ms to the browser.

Ts as long as there is a certain js basic entry is also very simple, the following website is I think also good entry tutorial for everyone to learn

  • TypeScript tutorial
  • Introduction · TypeScript Handbook (Chinese Version)

Tsconfig file details

When initializing the vite project in step 2, you can see that tsconfig.json and tsconfig.node.json files are added to the project root directory

As the name implies, this file specifies the root file and compilation options used to compile the project. Why tsconfig.node.json? As explained below)

When we use

  • Called without any input filestsc, the compiler will start from the current directory to findtsconfig.jsonFile, step by step to search the parent directory.
  • Called without any input filestscAnd use command line arguments--project(or-p) specifies a containtsconfig.jsonThe directory of the file.

The tsconfig.json file is ignored when an input file is specified on the command line.

Remember the script command we executed when we ran the NPM run build package? (in package.json)

"build": "vue-tsc --noEmit && vite build",
Copy the code

Vue-tsc is a vue3 command line type checking tool based on Volar. You can also configure what vuE-tsc –noEmit needs to check and how it needs to check via tsconfig.json.

Let’s go to tsconfig.json and have a look at some basic configurations:

{
  "compilerOptions": {
    "target": "esnext",
    "useDefineForClassFields": true,
    "module": "esnext",
    "moduleResolution": "node",
    "strict": true,
    "jsx": "preserve",
    "sourceMap": true,
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "lib": ["esnext", "dom"]
  },
  "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
  "references": [{ "path": "./tsconfig.node.json" }]
}
Copy the code

tsconfig.node.json

{
  "compilerOptions": {
    "composite": true,
    "module": "esnext",
    "moduleResolution": "node"
  },
  "include": ["vite.config.ts"]
}
Copy the code

Json: tsconfig.node.json: tsconfig.node.json: tsconfig.node.json: tsconfig.node.json: tsconfig.node.json

The References property is a new feature in TypeScript 3.0 that allows TypeScript applications to be split and structured. This is similar to the idea of writing vUE components. Instead of processing too much content in a single file, we can split it into multiple files and configure different parts for clearer and more maintainable purposes.

This article covers only a few configuration options that need to be understood. For complete configuration options, see the compiler option TypeScript — the JavaScript superset include

This property is well understood and specifies the range of files to compile.

SRC.ts,.d.ts,.tsx,.vue files are compiled by default.

You can see the “include” in tsconfig.node.json: [“vite.config.ts”] indicates that the separate configuration file is only the configuration file that compiles vite, vite.config.ts

In contrast, we can add exclude to configure a range of files that do not need to be compiled:

exclude

"exclude": ["node_modules","dist"]
Copy the code

Exclude third-party dependencies and packaged static files.

compilerOptions.skipLibCheck

Action: Ignores type checking for all declaration files (*.d.ts).

"compilerOptions": {
    "skipLibCheck": true
}
Copy the code

In short, this property not only ignores errors caused by NPM irregularities, but also maximizes support for the type system. Set this to true so that the third-party libraries used are not standardized.

You may wonder, why skip these third-party library checks?

The purpose of type checking (and the code specification below, etc.) is to maintain consistency and discipline in the business code development within the team to ensure quick start and maintenance among development members. So what we need to do is to integrate the various rules into the business code module, and not some framework or third-party library content.

compilerOptions.baseUrl

Function: Sets baseUrl to tell the compiler where to look for modules. All non-relative module imports are treated as relative to baseUrl.

Note that the import of relative modules is not affected by the baseUrl setting, because they are always relative to the file from which they were imported.

This setting is similar to the base set in the previous build option, which is the current root directory

"baseUrl": "./"
Copy the code

compilerOptions.paths

Function: list of module names to baseUrl based path maps.

Note that “paths” is parsed relative to “baseUrl”.

Remember that we configured the path alias resolve.alias in section 3. To enable ts to resolve the corresponding path, we also need to configure the Paths option:

"paths": {
    "@/*": ["src/*"],
    "views/*": ["src/views/*"],
    "components/*": ["src/components/*"],
    "assets/*": ["src/assets/*"]
}
Copy the code

compilerOptions.isolatedModules

Purpose: Treats each file as a separate module

Typescript treats files that are not imported/exported as old script files. Because such a file is not any definition of modules and their merging in the global namespace. This configuration item disallows such files. Treat any imported or exported files added as modules

This setting is required to be set to true in the official vite documentation. It was not added by default when the project was initialized, so we need to do it ourselves:

"isolatedModules": true
Copy the code

compilerOptions.types

Effect: Adds a list of type declaration filenames to include. only the module declaration files listed here will be loaded

"types": ["vite/client"]
Copy the code

You can add vite/client to types, which provides the following type definition additions:

  • Resource import (for example, import one.svgFile)
  • import.meta.envType definitions for Vite injected environment variables on
  • import.meta.hotOn theHMR APIThe type definition

This is about all the configuration we need to add. The complete configuration is as follows: Complete configuration

{
  "compilerOptions": {
    "baseUrl": "./",
    "skipLibCheck": true,
    "target": "esnext",
    "module": "esnext",
    "moduleResolution": "node",
    "noImplicitAny": false,
    "strict": true,
    "jsx": "preserve",
    "sourceMap": true,
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "lib": ["esnext", "dom"],
    "types": ["vite/client"],
    "isolatedModules": true,
    "paths": {
      "@/*": ["src/*"],
      "views/*": ["src/views/*"],
      "components/*": ["src/components/*"],
      "assets/*": ["src/assets/*"]
    }
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.d.ts",
    "src/**/*.tsx",
    "src/**/*.vue"
  ],
  "exclude": ["node_modules", "dist"]
}
​
Copy the code

Env.d. ts file details

Open the env.d.ts file in the SRC folder and you can see that it looks like this

/// <reference types="vite/client" />
​
declare module '*.vue' {
  import type { DefineComponent } from 'vue'
  // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
  const component: DefineComponent<{}, {}, any>
  export default component
}
Copy the code

Let’s look at the triple slash instruction on the first line, as explained in the official documentation client type:

Vite’s default type definition is written to its Node.js API. To supplement this to the client code environment of a Vite application, add a D.ts declaration file: ///
.

Please note that the Triple Slash Directives are single-line comments containing a single XML tag, the contents of which are used as compiler Directives and only take effect at the top of the file. See TypeScript: Documentation – Triple-Slash Directives for this.

So the purpose of this file is obvious: to help the compiler recognize types.

TypeScript has more type declarations than JavaScript. In principle, TypeScript needs to be heard first and used later. This causes the compiler to fail type checking when calling many native interfaces (browsers, Node.js) or third-party modules because some global variables or object methods are not declared.

When we encounter Property XXX does not exist on type… When an error is reported, it can be determined that the method/attribute was not declared. We can make a global declaration in this file.

As you can see, this file already declares a DefineComponent component type for all vue files by default, which means as long as our single-file component uses it

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

$router, this.$route command. This.$route command

Iv. Access code specifications

Code specification

As an enterprise-level framework, code specifications are essential. Although we use typescript with the type specification, we can’t prevent team members from using different development styles, such as statement endings; , two Spaces or four Spaces for indentation, small hump or hyphen for variable names, and so on.

Unified code specification can not only enhance the maintainability of code, but also improve the mutual cooperation of team members. More importantly, it can cultivate the perfect code style and development consciousness of front-end developers.

ESlint

Introduction to the

ESlint has been described as the next generation of JS Linter tools that parse JS code into an AST abstract syntax tree and then check whether the AST conforms to established rules. And these “rules” have very flexible configurations.

In January 2019, TypeScirpt officially decided to fully adopt ESLint as a code checking tool and created a new project, typescript-ESLint, TypeScript file parser @typescript-eslint/parser and related configuration options @typescript-eslint/eslint-plugin are provided. Without further ado, let’s look at how to plug into the framework:

The installation

Directly run the command to install:

npm install --save-dev eslint
Copy the code

ESLint uses Espree for syntax parsing by default, so some typescript syntax cannot be parsed, so we also need to install @typescript-esLint /parser instead of the default parser

npm install @typescript-eslint/parser --save-dev
Copy the code

Next you need to install the corresponding @typescript-eslint/eslint-plugin, which supplements the esLint default rules and provides some additional rules for TS syntax:

npm install --save-dev @typescript-eslint/eslint-plugin
Copy the code

Of course, don’t forget to install eslint-plugin-vue, the plugin’s ability to make ESLint recognize vue files

npm install --save-dev eslint-plugin-vue
Copy the code

With the dependency plug-in installed, we can put it in the project root directory

  1. Create.eslintrc.js to configure rules for ESlint

  2. Create a new.eslintignore file to specify directories/files that will not be ESlint verified. We will ignore ESlint for the following files/folders

    /build/
    /dist/
    /node_modules/
    *.js
    Copy the code

configuration

As always, let’s take a look at some of the more important configuration items in ESlint:

env

Role: Provides predefined environment variables.

Because there are so many global variables in Node or the browser that it would be tedious to declare them individually, we need to use env, which is the default set of global variables defined by the environment.

Env: {browser: true, ES2021: true, // Add all ECMAScript 2021 global variables and automatically set the ecmaVersion parser option to 12 node: true,},Copy the code

parser

Action: Specifies the parser to use. We’ll just specify vue-eslint-parser

parser: 'vue-eslint-parser',
Copy the code

parserOptions

Function: Pass some additional configuration parameters to the parser

For example, the @typescript-esLint /parser we installed earlier can be configured here

ParserOptions: {parser: '@typescript-eslint/parser', ecmaVersion: "latest", // Supported ES version sourceType: 'module', // generation module type, default is script, we set to module},Copy the code

extends

Action: Uses the default Lint package

It would be tedious to set the rules ourselves, so we can just use industry best practices

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

We just choose Plugin :vue/vue3-recommended and Plugin: @typescript-esLint /recommended as base rules

plugins

Purpose: Enhances ESlint functionality

Remember when we first installed @typescript-eslint/eslint-plugin? The eslint-plugin- can be omitted from the name of the plugin to provide esLint with some additional rules applicable to the TS syntax:

plugins: ['@typescript-eslint'],
Copy the code

rules

Purpose: Create a custom rule.

List of rules:

  • eslint-plugin-vue

Rule definition values:

  • Off or 0 – Turns off the rule
  • Warn or 1 – Opens the rule. Using the warning program does not exit
  • Error or 2 – Start the rule and exit using the error program

Example:

Rules: {// Disallow the unused variable 'no-unused-vars': 'error', / / indenting using four Spaces, and a switch statement in Case need to be indented 'text-indent: / / https://eslint.org/docs/rules/indent ['error', 4, { 'SwitchCase': 1, 'flatTernaryExpressions': True}], / / only one parameter, the arrow in the function body can omit parentheses' arrow - parens' : / / https://eslint.org/docs/rules/arrow-parens' off '}Copy the code

Although we introduce some rules for industry best practices through extends, each team has its own development habits, so we can add or modify the rules in extends through Rules.

Here I would like to share the rules that our team likes to use. At that time, the team leader pulled several of our old employees out one by one.

Definition of rules more, in order not to occupy the position, not directly put the code, interested can directly go to the code warehouse to view.

other

After doing the above steps, some people may find: Why doesn’t it work?

This is because ESlint is not enabled in their respective editors, such as Webstorm:

Friends using other editors can also search for the opening method.

In addition to the editor’s built-in one-click fix for ESlint issues, you can also add the following command to package.json

"lint": "eslint --ext .js,.vue,.ts src",
"lint:fix"": "npx eslint ./src/**/*.vue --fix",
Copy the code

NPM Run Lint: Fix fixes ESlint problems quickly and automatically, although some problems need to be fixed manually. NPM Run Lint: Fix

Stylelint

Above we take care of checking HTML and JavaScrript via ESlint, CSS certainly can’t be absent, so we can standardize CSS writing style by adding Stylelint.

The installation

We chose to use SCSS to enhance the syntactic capabilities of CSS by installing the following packages

npm install sass stylelint stylelint-scss --save-dev
Copy the code

In daily development, we mainly use the hierarchical capabilities provided by SCSS, so that the parent-child level display is very clear, using examples:

<template> <div class="test"> <div class="test2"></div> </div> </template> <! <style lang=" SCSS ">.test {.test2 {border: 1px solid black; width: 100px; height: 200px; } } } </style>Copy the code

Of course, SCSS also has other variables, mixing, and other useful features that you can learn from the documentation

StyleLint is initialized similar to ESlint, creating two new files in the project root directory:

  • Stylelintrc. js Configurs the stylelint rule

  • Stylelintignore is used to configure files that do not need to pass the stylelint constraint. We add the following files:

    # Other types of files *.js *.ts *.jpg *.woff # Test and pack directory /dist/ /node_modules/Copy the code

configuration

We install all dependencies with the latest version, so there are some additional configurations, such as those required for Stylelint 14:

Stylelint 14+ no longer contains csS-like precompiler parsing from Scss, Sass,Less, or SugarSS, so we can extend the shared configuration to include when parsing, We use stylelint-config-standard-SCSS as the common rule

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

Use:

"extends": ["stylelint-config-standard-scss"],
Copy the code

Of course, in order for stylelint to read vue (.html,.xml,.svelte,.vue etc.) files, we also need to install postCSS-html

npm install --save-dev postcss-html
Copy the code

Then configure the customSyntax property

"customSyntax": "postcss-html"
Copy the code

A rule definition

We can use some custom rules. To save space, check out the code repository

use

Enjoy the feeling of accomplishment from constraints by opening stylelint in editor /IDE:

Next add the following command to package.json:

"stylelint": "npx stylelint --aei .vue src"."stylint:fix": "npx stylelint ./src/**/*.vue --fix"
Copy the code

You can use NPM Run Stylelint to quickly view the specific code for files that do not match the stylelint in the console, and NPM Run StyLint :fix one-click fixes.

.editorconfig

What if all these rules are defined, but the editor isn’t smart enough?

Hit a TAB, enter the indented key is always wrong, each manual alignment that is not uncomfortable very?

Editorconfig can be added to the project root directory to help developers define and maintain a consistent code style across different editors and ides, using an example:

# 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 = 4 # # end_of_line indentation size = lf control line type (lf | cr | CRLF) (lf is \ n, cr is \ r, CRLF is \r\n) trim_trailing_whitespace = true # Insert_final_newline = true # Always insert a newline at the end of the file [*.md] # indicating md only The following rules apply to files: max_LINe_length = off TRIM_trailing_whitespace = falseCopy the code

git hooks

Now that you’ve defined so many rules, how do you prevent code that doesn’t conform to the ESlint code specification from being committed to a Git repository? Husky and Lint-staged can be used

  • Husky is the hook that controls code submission, where you can do some pre-checking or formatting before committing code to a Git repository.
  • Lint-staged is a front-end file filtering tool (just file filters) that filters file systems so that you don’t have to validate all files per commit.

The installation

NPM install --save-dev [email protected] lint-stagedCopy the code

Note: The latest version of Husky has bugs, so we’ll just use the lower version

Modify package.json configuration

"husky": { "hooks": { "pre-commit": "lint-staged" } }, "lint-staged": { "src/**/*.{ts,vue}": [ "eslint --fix" ], "*.vue": [// stylelint14+ need --custom-syntax postcss-html configuration "stylelint --fix --custom-syntax postcss-html"]}Copy the code

ESlint –fix ESlint –fix ESlint –fix ESlint –fix ESlint –fix ESlint –fix ESlint –fix Example:

Now that the basic configuration is in place, it’s time to extend the application part of the framework:

The second part

5. Access the UI library

Naive UI is a vue3 UI library that is fully written in TypeScript, but it is a relatively young UI library. Compared with the established players like Element and Ant Design, it is still a little inadequate. Naive UI should not be considered in a true project-level environment for the time being. For the purpose of learning something new, we can still look at it.

In fact, the use of UI libraries are very different, in the framework of the introduction we need to consider the following two points:

  • According to the need to introduce
  • Packaging optimization

The ability to apply tree-shaking flexibly on demand eliminates unused parts and avoids redundancy in packaging volume; Before packaging optimization in Webpack is more commonly used for large tripartite libraries to do separate packaging, avoid repeated packaging, etc., how to do packaging optimization in Vite? Haha, in fact, I am not familiar with it, I will take time to focus on the study and then add in.

First take a look at the dependent versions supported by Naive UI

  • Vue > 3.0.5
  • TypeScript > 4.1

Okay, that’s fine. Let’s get back on track, okay

Installation & Introduction

We used NPM to install naive- UI, the supporting font vfonts will not be installed, use the default

npm i -D naive-ui
Copy the code

In terms of usage, of course the best practice is to introduce as needed:

Create a new demand-import.ts in our SRC /utils file and import the components we use frequently in our daily development

import {
    // create naive ui
    create,
    // component
    NButton
} from 'naive-ui'
​
export const naive = create({
    components: [NButton]
})
Copy the code

It is then introduced in main.ts

import { createApp } from 'vue'
import App from './App.vue'
import { naive } from './utils/demandimport'
​
const app = createApp(App as any)
app.use(naive)
Copy the code

Then you can use it on the page:

<template>
    <n-button type="tertiary">
        Tertiary
    </n-button>
</template>
Copy the code

In use, directly according to the official documents can be happy to do CV xia, I will not repeat this

If you are extremely clean about performance, you can use import on demand + import directly, that is, import on demand for commonly used components to register globally, and import XXX from ‘naive- UI ‘directly for less commonly used components.

6. Access vuE-Router

Vue’s powerful single-page application capability actually relies on the seamless switching based on vue-Router.

The installation

npm install vue-router --save
Copy the code

configuration

SRC /views/home creates an empty index.vue file

<script lang="ts" setup>
// .
</script>
​
<template>
    <div>hello  vue3</div>
</template>
Copy the code

Then create an index.ts file in the SRC /router directory and import the newly created file route address as home /

import { createRouter, createWebHashHistory, RouteRecordRaw, } from 'vue-router' const routes: Array<RouteRecordRaw> = [ { path: '/', name: 'Home', component: () => import('views/home/index.vue')} ] const router = createRouter({ history: CreateWebHashHistory (), // history uses createWebHistory() routes,}) export default routerCopy the code

We use hash mode, of course, this is our team’s habit, history mode and hash are similar, just choose what works for you

This file is then imported in SRC /main.ts

import { createApp } from 'vue'
import App from './App.vue'
import router from './router/index'
​
const app = createApp(App as any)
app.use(router)
Copy the code

Add a router-view component to SRC/app. vue

<template>
    <div class="app-view">
        <router-view></router-view>
    </div>
</template>
Copy the code

Run the service, you can see the home page, and our basic routing is configured successfully

7. Access the status management tool Pinia

Pinia is a lightweight state management library that is a new member of the Vue3 ecosystem. It can also be considered as Vuex5. It supports both VUe2 and vue3, and its modular design makes its structure very clear.

The installation

npm install pinia --save
Copy the code

There is a warning after running:

PeerDependencies WARNING pinia@latest requires a peer of @vue/ commination-api @^1.4.0 but none was installed PeerDependencies WARNING [email protected] › VUe-demi @* requires a peer of @vue/composition-api@^1.0.0-rc.1 but none was installedCopy the code

Pinia relies on the @vue/composition-api@^1.4.0 package, but the composition-API is used by VUe2, we can use vue3’s composition-API in vue2, we just ignore it.

The introduction of

Introduced in main.ts

import { createPinia } from 'pinia'
​
app.use(createPinia())
Copy the code

use

Let’s take a simple accumulator as an example: create a new counters.ts file under SRC /stores

First, we need to define a store using defineStore()

import { defineStore } from 'pinia'
​
export const useCounterStore = defineStore('counter', {
    state: () => {
        return {
            count: 0
        }
    },
    getters: {
        count() {
            return this.count
        }
    },
    actions: {
        increment() {
            this.count++
        }
    }
})
Copy the code

Note: The first parameter in defineStore needs to be unique throughout your application.

This writing method is almost the same as vuex we used before, the only difference is that Pinia has eliminated mutations. In fact, mutations and actions functions overlap to a great extent in the process of using them before, and this upgrade is perfect.

Of course, pinia’s appeal goes beyond that, but Vue’s setup syntax brings a series of improvements:

We can use class setup in defineStore to simply replace the above configuration item with a function:

import { defineStore } from 'pinia'
​
export const useCounterStore = defineStore('counter', () => {
    const count = ref(0)
    function increment() {
      count.value++
    }
​
    return { count, increment }
})
Copy the code

It can then be used in a page like this:

<script lang="ts" setup>
    import { useCounterStore } from '@/stores/counter'
​
    const counter = useCounterStore()
</script>
<template>
    <div @click="counter.increment()">
        {{ counter.count }}
    </div>
</template>
Copy the code

Counter can be thought of as a reactive object, so counter, like props in setup, is deprecated:

const counter = useCounterStore()
const { count } = counter
​
<div @click="counter.increment()">{{ count }}</div>
​
Copy the code

We’ll see that no matter how we click on count, it doesn’t change the value, just its initial value.

Of course pinia was kind enough to provide the storeToRefs method for us to enjoy deconstructing:

const { count } = storeToRefs(counter)
Copy the code

8. Access chart library ECharts5

B-end product charts are frequently used. After horizontal comparison of several popular chart libraries on the market, ECharts is still the most fragrant. Echarts5, in particular, includes many new features and optimizations for the previous version, so without further ado, let’s get started:

Installation & Introduction

npm install echarts --save
Copy the code

I highlight version 5 because in this release, Echarts adds a performance party favorite, on-demand import:

Create a new echarts.ts under SRC /utils/ to import the components we need to use

Import * as echarts from 'echarts/core' import {BarChart, // SeriesOption BarSeriesOption, LineSeriesOption} from 'echarts/charts' import {TitleComponent, // TooltipComponent, TooltipComponentOption, GridComponent, GridComponentOption, DatasetComponentOption, // Built-in data converter component (filter, sort) LegendComponent } from 'echarts/components' import { LabelLayout, UniversalTransition} from 'echarts/features' import {CanvasRenderer} from 'echarts/renderers' // via ComposeOption To compose a must component and charts only Option type export type ECOption poseOption < = echarts.Com | BarSeriesOption | LineSeriesOption | TitleComponentOption | TooltipComponentOption | GridComponentOption | DatasetComponentOption > / / registered must component echarts. Use ([ TitleComponent, TooltipComponent, GridComponent, DatasetComponent, TransformComponent, BarChart, LabelLayout, UniversalTransition, CanvasRenderer, LegendComponent ]) // eslint-disable-next-line no-unused-vars const option: ECOption = { // ... } export const $echarts = echartsCopy the code

Then you can use it in the page:

<script lang="ts" setup> import { onMounted } from 'vue' import { $echarts, ECOption} from '@utils /echarts' onMounted(() => {const ele = document.getelementById ('echarts') as HTMLCanvasElement const myChart = $echarts.init(ele) const option: ECOption = { title: { text: 'ECharts starter sample '}, Tooltip: {}, Legend: {data: [' sales ']}, xAxis: {data: [' shirts' and 'sweater', 'snow spins unlined upper garment,' pants', 'high heels',' socks']}, yAxis: {}, series: [{name: 'sales' type:' bar 'data: [5, 20, 36, 10, 10, 20] } ] } </script>Copy the code

Note: Only after onMounted can the dom element on the page be retrieved via document.getelementByID and initialized with $echarts.init(ele). Effect:

Configure unified AXIOS processing

The axios library stands out as the most popular ajax library on the front end.

In addition to simple calls like GET/POST, you can add status code interception, request cancellation, error handling, and more. However, due to the limited space, this paper will not do so complex encapsulation. Later, I will write a special paper from axios principle analysis to complete encapsulation processing.

Installation & Introduction

npm install axios --save
Copy the code

Let’s create a new axios.ts under SRC /utils that encapsulates the basic axios functionality

We’ll start with our protagonist, Axios, the error handling type interface, AxiosError, and the response result interface, AxiosResponse

import Axios, {AxiosError, AxiosResponse} from 'axios'
Copy the code

We can create a custom configured instance of Axios with the axios.create () method

const BASE_URL = 'https://api.example.com'
const TIME_OUT = 10 * 1000
​
const instance = Axios.create({
    baseURL: BASE_URL,
    timeout: TIME_OUT
})
Copy the code

For example, specify the baseURL for each request and specify a timeout of 10 seconds for the request

We then use a post-interceptor to intercept the received response:

instance.interceptors.response.use( (res: AxiosResponse) => { if (String(res.status).indexOf('2') ! = = 0) {return {code: res. The status, the message: res. Data. The message | | 'abnormal request, please refresh retry', the result: false } } return Promise.reject(res.data) }, (error: AxiosError) => { if (error && error.response) { errorHandle(error.response.status, Error. Response) return promise.reject (error. Response)} console.log(' Network request failed, please refresh and retry ') return promise.reject (error)})Copy the code

When we get a response status code that does not start with 2, we consider the response failed

When an error request is caught, you can customize error handling:

Const errorHandle = (status: number, error): void => {// Switch (status) {case 401: Return alert (` Error Code: ${status}, Message: ${Error. The MSG | | 'login failed, please login again'} `) case 403: return alert (` Error Code: ${status}, Message: ${error. The MSG | | 'you do not have access to'} `) case 500: return alert (` error Code: ${status}, the Message: . ${error MSG | | 'background error, please contact your administrator'} `) case 502: return alert (` error Code: ${status}, the Message: . ${error MSG | | 'abnormal platform environment} `) default: alert (` error Code: ${status}, Message: ${error. The MSG | |' unknown error, please refresh retry '} `)}}Copy the code

Finally, we will export our common request methods:

const getPromise = (method, url, params, config = {}) => { return new Promise((resolve, reject) => { instance[method](method, url)(params, config).catch(e => e.response.data) .then(res => resolve(res)) .catch(err => reject(err)) }) } const get = (url: string, params? : any) => getPromise('get', url, { params }) const post = (url: string, params: any, config? : AxiosRequestConfig) => getPromise('post', url, params, config) export { get, post, }Copy the code

Reference/guidance documents

Vue.js

Home | Vite official Chinese documents

Node.js

TypeScript: JavaScript With Syntax For Types.

ESLint – Pluggable JavaScript linter

Home | Stylelint

Naive UI: A library of Vue 3 components

pinia

TypeScript tutorial

Introduction · TypeScript Handbook (Chinese Version)

Getting Started | Axios Docs

conclusion

However, I have been busy recently, and I have omitted many details. Of course, the initial writing outline is much more than that. We can also add unit tests, mock data and so on. The follow-up will continue to supplement and improve ~