preface

The day before yesterday, I had the honor to see you Yuxi, Yuying, Guo Hui, Qu Guangyu several leaders of the “Chat Vue 3.0 & new trend of front-end technology”, true vuE3 ecological surrounding daquan a wave of good guys to shock;

Although I see the live broadcast said the most is don’t update, learn not to move, but as a front-end brick master, and how many people have secretly rolled up?

Therefore, WE specially prepared a package of one-stop services around VUE3 project to bring to you

You can learn from this article

  • How to build a project using Vite
  • How do I integrate in Vitetypescript
  • How do I integrate in Vitevue-router4pinia
  • How to use vuE3 matevueuse
  • How is it integrated in a projecteslintprettierEnsure code quality
  • How to normalizegitSubmit information
  • How to develop for the teamProprietary project templates

Environment-dependent version

  • Node: v14.15.4
  • Vite: ^ 2.8.0
  • Vue: ^ 3.2.25
  • The typescript: ^ 4.5.4
  • Pinia: ^ 2.0.12
  • Vue – the router: ^ 4.0.14
  • Vueuse: ^ 8.2.0
  • Eslint: ^ 8.12.0
  • Prettier: ^ 2.6.1
  • Commitizen:
  • Husky: ^ 7.0.4

Quick look

  • The warehouse address

To make a long story short, get straight to work

1. Initialize the project

Follow the steps to initialize:

  1. Use the vite-cli command
# pnpm
pnpm create vite

# npm
npm init vite@latest

# yarn
yarn create vite
Copy the code
  1. Enter the project name:
? Project name:  vite-vue3-ts-pinia
Copy the code
  1. Select a Framework (VUE)
? Select a framework: Use arrow-keys. Return to submit. Vanilla // native js > vue3 react // react preact // Lightweight react framework lit // Lightweight Web component Svelte // Svelte frameworkCopy the code
  1. Use the typescript
? Select a variant: › -use arrow-keys. Return to submit. Vue ❯ vue-tsCopy the code
  1. Start the project
cd vite-vue3-ts-pinia && pnpm install && pnpm run dev
Copy the code

Quick initialization (recommended) :

# pnpm pnpm create vite project-name -- --template vue-ts # npm 6.x npm init vite@latest project-name --template vue-ts # NPM 7+ requires additional double lines:  npm init vite@latest project-name -- --template vue-ts # yarn yarn create vite project-name --template vue-tsCopy the code

Integrated configuration

  1. To ensure the use of Node
pnpm i @types/node --save-dev
Copy the code
  1. Modify thetsconfig.json
{
  "compilerOptions": {
    "typeRoots": [
      "node_modules/@types"./ / the default value
      "src/types"]."target": "esnext"."useDefineForClassFields": true."module": "esnext"."moduleResolution": "node"."strict": true."jsx": "preserve"."sourceMap": true."resolveJsonModule": true."esModuleInterop": true."lib": ["esnext"."dom"]."baseUrl": ". /"."paths": {"@": ["src"]."@ / *": ["src/*"],}},"include": ["src/**/*.ts"."src/**/*.d.ts"."src/**/*.tsx"."src/**/*.vue"]}Copy the code
  1. Modify thevite.config.ts
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import * as path from 'path';

// https://vitejs.dev/config/
export default defineConfig({
    resolve: {
        // Set the alias
        alias: {
            The '@': path.resolve(__dirname, 'src')}},plugins: [vue()],
    server: {
        port: 8080.// Start port
        hmr: {
            host: '127.0.0.1'.port: 8080
        },
        // Set the HTTPS proxy
        proxy: {
            '/api': {
                target: 'your https address'.changeOrigin: true.rewrite: (path: string) = > path.replace(/^\/api/.' '(}}}});Copy the code

2. Uniform code quality style

Integrated eslint

  1. The installation
pnpm i eslint eslint-plugin-vue --save-dev
Copy the code

Since ESLint uses Espree for syntax parsing by default, some TypeScript syntax is not recognized, so we need to install @typescript-esLint /parser instead of the default parser

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

Install the corresponding @typescript-eslint/eslint-plugin, which supplements the esLint default rules by providing additional rules for TS syntax.

pnpm install @typescript-eslint/eslint-plugin --save-dev
Copy the code
  1. Create a configuration file:.eslintrc.js 或 .eslintrc.json
module.exports = {
    parser: 'vue-eslint-parser'.parserOptions: {
        parser: '@typescript-eslint/parser'.ecmaVersion: 2020.sourceType: 'module'.ecmaFeatures: {
            jsx: true}},extends: [
        'plugin:vue/vue3-recommended'.'plugin:@typescript-eslint/recommended',].rules: {
        // override/add rules settings here, such as:}};Copy the code
  1. Create ignore file:.eslintignore
node_modules/
dist/
index.html
Copy the code
  1. Command line: Modifypackage.json
{..."scripts": {..."eslint:comment": "Use ESLint to check and automatically repair all files with.js and.vue extensions in the SRC directory"."eslint": "eslint --ext .js,.vue --ignore-path .gitignore --fix src",}... }Copy the code

Integrated perttier

  1. The installation
pnpm i prettier eslint-config-prettier eslint-plugin-prettier --save-dev
Copy the code
  1. Create a configuration file:prettier.config.js.prettierrc.js
module.exports = {
    // A line of up to 80 characters
    printWidth: 80.// Use 4 Spaces for indentation
    tabWidth: 4.// Instead of using TAB indentation, use Spaces
    useTabs: false.// A semicolon is required at the end of the line
    semi: true.// Use single quotes instead of double quotes
    singleQuote: true.// The key of the object is quoted only when necessary
    quoteProps: 'as-needed'.JSX uses double quotes instead of single quotes
    jsxSingleQuote: false.// Use a comma at the end
    trailingComma: 'all'.{foo: bar}}
    bracketSpacing: true.// JSX tag Angle brackets require line breaks
    jsxBracketSameLine: false.// Arrow functions with only one argument also need parentheses
    arrowParens: 'always'.// The range in which each file is formatted is the entire content of the file
    rangeStart: 0.rangeEnd: Infinity.// There is no need to write @prettier at the beginning of the file
    requirePragma: false.// There is no need to automatically insert @prettier at the beginning of a file
    insertPragma: false.// Use the default line folding standard
    proseWrap: 'preserve'.// Depending on the display style, HTML should be folded or not
    htmlWhitespaceSensitivity: 'css'.// Use lf for line breaks
    endOfLine: 'lf'
}

Copy the code
  1. Modify the.eslintrc.jsconfiguration
module.exports = {
    ...

    extends: [
        'plugin:vue/vue3-recommended'.'plugin:@typescript-eslint/recommended'.'prettier'.'plugin:prettier/recommended'],... };Copy the code
  1. Command line: Modifypackage.json
{..."scripts": {..."prettier:comment": "Automatically format all files in the current directory"."prettier": "prettier --write"}... }Copy the code

Integration of 3.pinia

Pinia, pronounced ‘PI ːnə, is a lightweight status management library recommended by the official Vue team to replace Vuex.

Pinia has the following characteristics:

  • Full typescript support;
  • Lightweight enough, compressed volume is only 1.6KB;
  • Remove mutations, only state, getters, actions (one of my favorite features);
  • Actions support synchronous and asynchronous;
  • There is no module nesting, only the concept of stores, stores can be used freely, better code segmentation;
  • There is no need to manually add stores, stores are automatically added once created;

The installation

 pnpm i pinia --save
Copy the code

use

  1. Create a SRC /store directory and create index.ts under it to export store
 import { createPinia } from 'pinia'

 const store = createPinia()

 export default store
Copy the code
  1. Introduced and used in main.ts
 import { createApp } from 'vue'
 import App from './App.vue'
 import store from './store'
 ​
 // Create a vue instance
 const app = createApp(App)
 ​
 / / mount pinia
 app.use(store)
 ​
 // Mount the instance
 app.mount('#app');
Copy the code
  1. Define State: create a user.ts under SRC /store
 import { defineStore } from 'pinia'

 export const useUserStore = defineStore({
   id: 'user'.// ID Must be unique
   state: () = > {
     return {
       name: 'Joe'}},actions: {
     updateName(name) {
       this.name = name
     }
   }
 })
Copy the code
  1. Access to the State: in SRC/components/usePinia vue
 <template>
   <div>{{ userStore.name }}</div>
 </template>

 <script lang="ts" setup>
 import { useUserStore } from '@/store/user'

 const userStore = useUserStore()
 </script>
Copy the code
  1. Modify the State:
 // 1. Modify state directly (not recommended)
 userStore.name = 'bill'

 // 2. Use actions to modify it
 <script lang="ts" setup>
 import { useUserStore } from '@/store/user'

 const userStore = useUserStore()
 userStore.updateName('bill')
 </script>
Copy the code

More detailed getting started guide: Link Official documentation: link

Integration of 4.vue-router4

The installation

 pnpm i vue-router --save
Copy the code

use

  1. Create a SRC /router directory and create index.ts under it to export the router
 import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';

 const routes: Array<RouteRecordRaw> = [
   {
     path: '/login'.name: 'Login'.meta: {
         title: 'login'.keepAlive: true.requireAuth: false
     },
     component: () = > import('@/pages/login.vue')}, {path: '/'.name: 'Index'.meta: {
           title: 'home'.keepAlive: true.requireAuth: true
       },
       component: () = > import('@/pages/index.vue')}]const router = createRouter({
   history: createWebHistory(),
   routes
 });
 export default router;
Copy the code
  1. Introduced and used in main.ts
 import { createApp } from 'vue'
 import App from './App.vue'
 import store from './store'
 import router from '@/router';

 // Create a vue instance
 const app = createApp(App);

 app.use(router);

 // Mount the instance
 app.mount('#app');
Copy the code
  1. Modify the App. Vue
 <template>
   <RouterView/>
 </template>
Copy the code

Integration of 5.vueuse

VueUse is a collection of utility functions based on the Composition API.

The installation

 pnpm i @vueuse/core
Copy the code

use

  1. Create a new SRC /page/ vueuse. vue page to do a simple demo
 <template>
   <h1>Test vueUse's mouse coordinates</h1>
   <h3>Mouse: {{x}} x {{y}}</h3>
 </template>

 <script lang="ts">
     import { defineComponent } from 'vue';
     import { useMouse } from '@vueuse/core'

     export default defineComponent({
         name: 'VueUse'.setup() {
           const { x, y } = useMouse()

           return {
             x, y
           }
         }
     });
 </script>
Copy the code

UseMouse is just a basic library for Vueuse. There are many more.

More functions official documentation: links

6. CSS integration

New features of native CSS Variable

Native support, no need for third-party plug-ins, specific use of the document can be viewed

  1. Create a new file SRC /styles/index.css
 :root{-main-bg-color: pink;
 }
 ​
 body {
   background-color: var(--main-bg-color);
 }
Copy the code

Note: You can also add a PostCSS configuration (any format supported by postCSs-load-config, such as postcss.config.js), which will automatically apply to all imported CSS.

Scheme 2: SCSS or LESS:

  1. The installation
 # .scss and .sass
 pnpm add -D sass

 # .less
 pnpm add -D less
Copy the code
  1. Used in.vue file templates
// .scss
 <template>
     <div class="root">
         <h3>Welcome to SCSS</h3>
     </div>
 </template>
 <style lang="scss">
   .root {}
 </style>

// .less
 <template>
     <div class="root">
         <h3>Welcome to less</h3>
     </div>
 </template>
 <style lang="less">
   .root {}
 </style>
Copy the code

Integration of 7.axios

Axios is a Promise-based HTTP library that can be used in browsers and Node.js.

The installation

 pnpm i axios
Copy the code

Use:

  1. New SRC/utils/axios. Ts
 import axios, { AxiosResponse, AxiosRequestConfig } from 'axios';

 const service = axios.create();

 // Request interceptors
 service.interceptors.request.use(
     (config: AxiosRequestConfig) = > {
         // do something
         return config;
     },
     (error: any) = > {
         Promise.reject(error); });// Response interceptors
 service.interceptors.response.use(
     async (response: AxiosResponse) => {
         // do something
     },
     (error: any) = > {
         // do something
         return Promise.reject(error); });export default service;
Copy the code
  1. Use it on the page
<script lang="ts">
    import request from '@/utils/axios';
    const requestRes = async() = > {let result = await request({
                    url: '/api/xxx'.method: 'get'
                  });
    }

</script>
Copy the code

All apis that encapsulate request parameters and response data (optional)

  1. newsrc/api/index.ts
import * as login from './module/login';
import * as index from './module/index';

export default Object.assign({}, logins, index);

Copy the code
  1. newsrc/api/module/login.tssrc/api/module/index.ts
import request from '@/utils/axios';

/** * login */
 
interfaceIResponseType<P = {}> { code? :number;
    status: number;
    msg: string;
    data: P;
}
interface ILogin {
    token: string;
    expires: number;
}
export const login = (username: string, password: string) = > {
    return request<IResponseType<ILogin>>({
        url: '/api/auth/login'.method: 'post'.data: {
            username,
            password
        }
    });
};
Copy the code
  1. Because typescript is used, it needs to be addedsrc/types/shims-axios.d.ts
import { AxiosRequestConfig } from 'axios';
/** * Custom extension axiOS module *@author Maybe* /
declare module 'axios' {
    export interface AxiosInstance {
        <T = any>(config: AxiosRequestConfig): Promise<T>;
        request<T = any>(config: AxiosRequestConfig): Promise<T>;
        get<T = any>(url: string, config? : AxiosRequestConfig):Promise<T>;
        delete<T = any>(url: string, config? : AxiosRequestConfig):Promise<T>;
        head<T = any>(url: string, config? : AxiosRequestConfig):Promise<T>;
        post<T = any>(url: string, data? :any, config? : AxiosRequestConfig):Promise<T>;
        put<T = any>(url: string, data? :any, config? : AxiosRequestConfig):Promise<T>;
        patch<T = any>(url: string, data? :any, config? : AxiosRequestConfig):Promise<T>; }}Copy the code
  1. insrc/pages/request.vuePage use
<script lang="ts">
    import API from '@/api';
    
    const requestRes = async() = > {let result = await API.login('zhangsan'.'123456');
    }

</script>

Copy the code

8. CSS UI style library

There are many options, according to the needs of their own projects to choose

Note: UI libraries generally need to be imported on demand (see below)element-plusAs an example)

  1. The installationvite-plugin-style-import
pnpm i vite-plugin-style-import --save-dev
Copy the code
  1. Modify thevite.config.ts
.import styleImport from 'vite-plugin-style-import'


export default defineConfig({
    ...
    plugins: [
        vue(),
        styleImport({
            libs: [{libraryName: 'element-plus'.esModule: true.resolveStyle: (name) = > {
                        return `element-plus/lib/theme-chalk/${name}.css`;
                    },
                    ensureStyleFile: true // Ignore whether the file exists to prevent errors when importing non-existent CSS files.}]})],... })Copy the code

Use 9.commitizenSpecification git commit

In order to make the team multi-person collaboration more standardized, it is necessary to make a hard specification submission every time git submission, and standardize git submission information

The installationcommitizen(Interactive submission + custom prompt copy + Commit specification)

  1. The installation
pnpm install -D commitizen cz-conventional-changelog @commitlint/config-conventional @commitlint/cli commitlint-config-cz cz-customizable
Copy the code
  1. configurationpackage.json
{..."scripts": {
    "commit:comment": "Bootstrap set normalized submission information"."commit":"git-cz",},"config": {
      "commitizen": {
        "path": "node_modules/cz-customizable"}},... }Copy the code
  1. The new configurationcommitlint.config.js
module.exports = {
    extends: ['@commitlint/config-conventional'.'cz'].rules: {
        'type-enum': [
            2.'always'['feature'.// New feature
                'bug'.// This item is specific to the bug number and is used to feedback the changes of the bug list to the test
                'fix'./ / repair the bug
                'ui'./ / update the UI
                'docs'.// Documentation
                'style'.// Format (changes that do not affect code execution)
                'perf'.// Performance optimization
                'release'./ / release
                'deploy'./ / deployment
                'refactor'.// Refactoring (i.e. not new features, not code changes to fix bugs)
                'test'.// Add tests
                'chore'.// Changes to the build process or accessibility tools
                'revert'.// feat(pencil): Add 'graphiteWidth' option
                'merge'.// Merge branches, for example: merge (front-end page) : feature-xxxx changes thread address
                'build'./ / packaging]],// 
      
        in lowercase format
      
        'type-case': [2.'always'.'lower-case'].// 
      
        cannot be empty
      
        'type-empty': [2.'never'].// 
      
        The scope cannot be empty
      
        'scope-empty': [2.'never'].// 
      
        Scope format
      
        'scope-case': [0].// 
      
        Main message cannot be empty
      
        'subject-empty': [2.'never'].// 
      
        with what closing flag, disable
      
        'subject-full-stop': [0.'never'].// 
      
        format, disabled
      
        'subject-case': [0.'never'].//  starts with a blank line
        'body-leading-blank': [1.'always'].'header-max-length': [0.'always'.72],}};Copy the code
  1. Custom prompt is added.cz-config.js
module.exports = {
    types: [{value: 'feature'.name: 'Feature: Add new features'},
        {value: 'bug'.name: 'Bug: Bug number in test feedback bug list'},
        {value: 'fix'.name: 'fix: fix bugs'},
        {value: 'ui'.name: 'update UI: UI'},
        {value: 'docs'.name: 'docs: Document changes'},
        {value: 'style'.name: 'style: code format (changes that do not affect code execution)'},
        {value: 'perf'.name: 'PERF: Performance Tuning'},
        {value: 'refactor'.name: 'refactor: refactoring (neither adding features nor fixing bugs)'},
	{value: 'release'.name: 'released release:},
	{value: 'deploy'.name: 'the deploy: deploy'},
        {value: 'test'.name: 'test: add test '},
        {value: 'chore'.name: 'chore: Changes to the Build process or helper (changes to configuration files)'},
        {value: 'revert'.name: 'revert:   回退'},
    	{value: 'build'.name: 'build: package'}].// override the messages, defaults are as follows
    messages: {
        type: 'Please select submission type :'.customScope: 'Please enter the range you modified (optional):'.subject: 'Please briefly describe submitting message (required):'.body: 'Please enter a detailed description (optional, to be optimized to remove, skip):'.footer: 'Please enter the issue to close :'.confirmCommit: 'Confirm submission using the above information? (y/n/e/h)'
    },
    allowCustomScopes: true.skipQuestions: ['body'.'footer'].subjectLimit: 72
};
Copy the code
  1. Interactive interface testing

  • For example, ESLint, Prettier, etc. After all, everyone neglects sometimes.
  • And here comes husky

Install the husky

  1. The installation
# 1. The installation
pnpm i husky lint-staged -D

# 2. Generate the.husky folder
npx husky install

# 3. Add hooks to generate a pre-commit script in the.husky directory
npx husky add .husky/pre-commit "npx --no-install lint-staged"

# 4. Add commit- MSG
npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'

Git commit -m "message"
Copy the code
  1. Add the configurationpackage.json
{..."lint-staged": {
    	"*.{js,ts}": [
            "npm run eslint"."npm run prettier"]}... }Copy the code

Submit logs (optional)

  • Standard version or but — changelog

Project template address

portal

The last

This series will be a continuous update series, about the whole “Vite from entry to master”, I will mainly from the following picture several aspects, please wait and see!!

Pretty boy pretty girls, all see here, don’t click a “like” and then go 🌹🌹🌹