preface

Uvu recently announced that Vue3 will become the new default version of VUE on February 7, 2022, which is not a good idea. It took some time to complete a set of startup templates for Vue3. I stepped on the pit for my friends in advance.

  • The first half of this article is the templateOut of the box features overview

  • The second half of the article is for some of the partners who want to start their own configuration explainedConfiguration process

This article is too long to avoid omissions or mistakes. If you find them, feel free to discuss them in the comments section or issue them on Github

Out of the box functions configured:

  • Programming languages: TypeScript 4.x, JavaScript

  • Front-end framework: Vue 3.x

  • Build tool: Vite 2.x

  • UI framework: Element Plus

  • Icon tool: ICones

  • CSS precompilation: Sass

  • CSS framework: Windi CSS

  • HTTP tool: Axios

  • Route management: Vue Router 4.x

  • State management: Pinia

  • Code specification: EditorConifg, Prettier, ESLint, Airbnb JavaScript Style Guide

  • Submit specifications: HusKY, Commitlint, Lint-Staged

There are some other plug-ins for various functions:

  • Implement automatic loading on demand (recommended for wall cracks) : unplugin-auto-import, unplugin-vue-components, vite-plugin-style-import, unplugin-icons

  • Componentization of SVG ICONS: viet-SVG-loader

  • Let the various apis support responsiveness: VueUse

  • Let the page load with feedback: NProgress

  • Markdown: viet-plugin-MD is supported

All of the above features have been configured and verified, and you can have fun using the template!

This template doesn’t configure GitHub Actions, change documents, unit tests, etc. If you need to, check out my other document to configure # Build a canonical TypeScript SDK project from scratch

Github

Github.com/nekobc19989…

Method of use

download

  • Click the Use This Template button to jump to the address where the project was created
  • Or just use Git Clone
git clone https://github.com/nekobc1998923/vue3-ts-template.git
Copy the code

The installation

npm install
Copy the code

run

npm run dev
Copy the code

packaging

npm run build
Copy the code

vetur -> volar

As a side note, vetur is obviously not as good as Volar when it comes to vue3 support, so we recommend that you disable vuetur and use Volor instead

If you are also maintaining a vue2 project, you can use vscode’s workspace feature for standalone use

Configuration process:

The following is a configuration process of the entire template. If you need to configure a template by yourself, you can read ~

Code directory structure

The structure of the entire template code directory looks like this:

  • .husky: configuration folder for husky hooks
  • .vscode: used to put vscode configuration in the project
  • presetsPlugin configuration for vite plugins, and some.d.ts declaration files
  • public: is used to store common files such as header ICONS that are packaged in the dist root directory
  • src: Used to put project code files
  • api: Some interface configuration for HTTP
  • assets: used to store static resources such as CSS
  • components: Used to hold Vue components
  • layout: Used to put the layout of the project
  • router: is used to store the routing configuration of the project
  • store: used to put the configuration of state management Pinia
  • utils: used to put tool method classes in the project
  • views: the.vue view used to hold the project

Vite

Vite initialization

Vite creates a vue3 + typescript basic project with just a short command. Here my-vue-app needs to be changed to your project name:

npm init vite@latest my-vue-app --template vue-ts
Copy the code
Alias using alias

We configure vite.config.ts

Resolve: {alias: {' @ ': resolve (__dirname,'. / SRC), / / @ pointing to the SRC directory to},},Copy the code

Don’t forget to configure tsconfig.json as well

Configure vite service Settings

Let’s configure vite.config.ts and add the following configuration

It is worth noting that only after host is configured can we access the project locally via IP

Port: 8080, // port number open: true, // automatically open the browser cors: StrictPort: true, // Cross-domain Settings allow strictPort: true, // Exit if the port is occupied // proxy: {'/ API ': {// Local 8000 front-end code interface proxy to 8888 service port target: 'http://localhost:8888/', changeOrigin: true, / / allow cross-domain rewrite: (path) = > path. The replace ('/API/', '/'),,}},},Copy the code
Build configuration

We can set up the package to remove console from the code, and configure the packaged static resources to different directories under Dist

Build: {brotliSize: false, // Remove the warning chunkSizeWarningLimit: 2000, // remove console.log terserOptions in production: { compress: { drop_console: false, pure_funcs: ['console.log', 'console.info'], drop_debugger: true, }, }, assetsDir: RollupOptions: {output: {chunkFileNames: 'static/js/[name]-[hash].js', entryFileNames: 'static/js/[name]-[hash].js', assetFileNames: 'static/[ext]/[name]-[hash].[ext]', }, }, },Copy the code
Configure vite environment variables

Often, we need to distinguish between production and development environments. We create three new files in the root directory to store environment variables:

  • .env
  • .env.development
  • .env.production

Env is configured as follows:

VITE_API_BASEURL = /api

VITE_BASE = /base-vue3/

VITE_APP_TITLE  = base-vue3
Copy the code

VITE_API_BASEURL is the API base prefix for the project

VITE_BASE is the base path prefix for the project

VITE_APP_TITLE is the web page title of the project

Automatically load apis & components & styles on demand

  • Do you get tired of using it every timevueWhen,You need to constantly import vue’s API
  • Do you get tired of using it every timeComponent libraryWhen,Components need to be introduced continuously on demand
  • Are you tired of using it sometimesThird-party Component LibraryWhen,Additional CSS styles need to be introduced

Unplugin-auto-import: automatically introduce vue\vue-router\pinia, etc. apis on demand

Unplugin-vue-components: Automatically introduce third-party component library components and our own custom components on demand

Viet-plugin-style-import: Automatically introduces the style styles we use in third-party component libraries, such as Element Plus’s Message component

Now there are two plug-ins that can help us solve this problem. We can use them directly when we call them without import, and when we package them, only the apis and components that we actually use will be built into the final product. They are unplugin-vue-components and unplugin-auto-import

Install the configuration

We’ll start by installing dependencies:

npm install -D unplugin-vue-components unplugin-auto-import vite-plugin-style-import
Copy the code

Then we configure vite.config.ts to add the following;

// vite.config.ts import AutoImport from 'unplugin-auto-import/vite' import Components from 'unplugin-vue-components/vite' export default { plugins: [ // ... AutoImport({ dts: './presets/auto-imports.d.ts', imports: ['vue', 'pinia', 'vue-router', '@vueuse/core'], // Generate corresponding .eslintrc-auto-import.json file. // eslint globals Docs - https://eslint.org/docs/user-guide/configuring/language-options#specifying-globals eslintrc: { enabled: true, // Default `false` filepath: './.eslintrc-auto-import.json', // Default `./.eslintrc-auto-import.json` globalsPropValue: true, // Default `true`, (true | false | 'readonly' | 'readable' | 'writable' | 'writeable') }, }), Components({ dts: '. / presets/components. Which s', / / imports specify the component location, the default for SRC/components dirs: ['src/components/'], }), styleImport({ }), ], }Copy the code

Since we are using ESLint we also need to configure.eslintrc.js:

// .eslintrc.js

module.exports = { 
  /* ... */
  extends: [
    // ...
    './.eslintrc-auto-import.json',
  ],
}
Copy the code

@vitejs/plugin-vue-jsx

This plugin allows us to support JSX writing

npm i @vitejs/plugin-vue-jsx -D
Copy the code

Then configure vite.config.ts

import vueJsx from '@vitejs/plugin-vue-jsx';

export default defineConfig({
  plugins: [...,vueJsx()]
})
Copy the code

vite-svg-loader

This plugin allows us to import SVG files directly to use, just like using Vue components

The installation process
npm i vite-svg-loader -D
Copy the code

Then configure vite.config.ts

import svgLoader from 'vite-svg-loader'

export default defineConfig({
  plugins: [...,svgLoader()]
})
Copy the code
Use the sample
<script setup lang="ts"> import MyIcon from '@/assets/example.svg? component'; </script> <template> <MyIcon /> </template>Copy the code

@vitejs/plugin-legacy

npm i @vitejs/plugin-legacy -D
Copy the code

Then configure vite.config.ts

import svgLoader from 'vite-svg-loader'

export default defineConfig({
  plugins: [...,
    legacy({
      targets: ['defaults', 'not IE 11'],
    }),
  ]
})
Copy the code

vite-plugin-md

This plug-in helps us introduce MarkDown for use as a Vue component

It is worth noting that since we have configured automatic import on demand components above, all we need to do is to put the.md file in the Components directory and use it directly

Install the configuration
npm i vite-plugin-md -D
Copy the code

Then configure vite.config.ts

// vite.config.ts
import Markdown from 'vite-plugin-md';

export default {
  plugins: [
    Markdown(),
  ]
}
Copy the code

TypeScript configuration

The full tsconfig.json configuration is directly pasted here

{ "compilerOptions": { "target": "esnext", "useDefineForClassFields": true, "module": "esnext", "moduleResolution": "node", "strict": true, "jsx": "preserve", "sourceMap": true, "resolveJsonModule": true, "esModuleInterop": True, "lib": [" esNext ", "dom"], // baseUrl tells the compiler where to look for modules. All non-relative module imports are treated as relative to baseUrl. "BaseUrl" : ". ", / / the relative module into the path of the map configuration "paths" : {" @ / * ": [" SRC / *"],}}, "include" : ["/SRC / * * * ts "and"/SRC / * * *. Which s ", "/ SRC / * * *. The TSX", "/ SRC / * * *. Vue", "presets. / / * * * which s",], / / compilers excluded by default file "exclude" : ["node_modules"] }Copy the code

Code style specification

I have detailed the configuration process in another of my articles: Build a canonical TypeScript SDK project from scratch

We only need to install an additional dependency, which will automatically install it for us when we select the Vue environment during ESLint initialization

npm i -D eslint-plugin-vue
Copy the code

Then the final.eslintrc.js configuration will have some different configuration, I posted the complete configuration here:

module.exports = { env: { browser: true, es2021: true, node: true, }, globals: { defineEmits: true, document: true, localStorage: true, GLOBAL_VAR: true, window: true, defineProps: true, defineExpose: true, }, extends: [ './.eslintrc-auto-import.json', 'airbnb-base', 'plugin:@typescript-eslint/recommended', 'the plugin: vue/vue3 - it', 'the plugin: prettier/it', / / add prettier plugins], parserOptions: {ecmaVersion: 'latest', parser: '@typescript-eslint/parser', sourceType: 'module', }, plugins: ['vue', '@typescript-eslint', 'import'], rules: { 'no-console': 'off', 'import/no-unresolved': 'off', 'import/extensions': 'off', 'import/no-extraneous-dependencies': 'off', }, };Copy the code

Vue Router 4.x

Install the configuration

We need to install the vuE-Router4.x version

npm install vue-router@4 --save
Copy the code

We will create an index.ts file under SRC /router to store our router configuration

Mount the configured router to vue: modify the entry main.ts file

unplugin-icons

We often struggle to find different ICONS, but now there is a great plugin and a great library to solve the problem of finding and using ICONS

Icones: is a very good icon library, which integrates many ICONS

Unplugin-icons: Automatically import the ICONS we want to use on demand, without manually importing them

Install the configuration
npm i -D unplugin-icons @iconify/json
Copy the code

Once installed, we configure vite.config.ts to add the following

// vite.config.ts
import Icons from 'unplugin-icons/vite'
import IconsResolver from 'unplugin-icons/resolver'
import Components from 'unplugin-vue-components/vite'

export default {
  plugins: [
    Components({
      resolvers: IconsResolver(),
    }),
    Icons({
      compiler: 'vue3',
      autoInstall: true,
    }),
  ],
}
Copy the code
Use the sample

To start, go to icones.net lilify. app/ and choose an icon

And I’m gonna hit Copy

Going back to our code, just a short sentence is enough to use:

<template>
  <i-mdi-account-reactivate style="font-size: 2em; color: red" />
</template>
Copy the code

ElementPlus

I don’t have to say much about The Element UI. There are already a lot of people using Vue2 to build projects, and Element Plus is their component library based on Vue3. Although there are still some problems in use, the official website message says: stable version released on February 7, still worth looking forward to and use;

Install the configuration

Let’s start by installing Element-Plus

npm install element-plus --save
Copy the code

We then configure the AutoImport and Components and styleImport configured above in vite.config.ts

// vite.config.ts
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import styleImport, { ElementPlusResolve } from 'vite-plugin-style-import';
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

export default {
  plugins: [
    // ...
    AutoImport({
      resolvers: [ElementPlusResolver()],
    }),
    Components({
      resolvers: [ElementPlusResolver()],
    }),
    styleImport({
      resolves: [ElementPlusResolve()],
    }),
  ],
}
Copy the code

After configuration, it will automatically import the components we use in our code on demand

Set Chinese theme

Element Plus is in English by default, so if we want to use a Chinese theme, we can set it in app.vue

<script setup lang="ts">
import zhCn from 'element-plus/lib/locale/lang/zh-cn';
const locale = zhCn;
</script>

<template>
  <el-config-provider :locale="locale">
    <router-view></router-view>
  </el-config-provider>
</template>
Copy the code

Remaining component libraries

If you want to use other component libraries such as Ant-Design-Vue or Naive UI, you can also refer to the configuration. It is worth mentioning that they all support automatic import on demand configuration

Ant Design of Vue

Naive UI

Automatic import on demand, you can refer to the configuration here: github.com/antfu/unplu…

Pinia

Pinia. Js is a new generation of state management tools, can be considered as the next generation of Vuex, namely vex5.x; It has several obvious changes compared to Vuex:

  • bettertypescriptsupport
  • removedmutationsLeaving onlyactions; actionsSupport synchronous and asynchronous
  • No need to manually addstore
Install the configuration
npm install pinia --save
Copy the code

Create index.ts in the SRC /store folder and configure it as follows:

import { createPinia } from 'pinia';

const store = createPinia();

export default store;
Copy the code

Then we use the exported store under main.ts

Pinia usage

We can create a new theme. Ts file in the store directory and write it as follows:

import { defineStore } from 'pinia'; Const theme = defineStore({// Where id must be a unique ID ID: 'theme', state: () => {return {themeType: 'bright blue ', themeColor: '#2080F0FF', }; }, // Equivalent to vuex's getter getters: {getThemeType: (state) => state.themeType, getThemeColor: (state) => state.themecolor,}, // Pinia abandons mutations and uses actions only: SetThemeType (type: string) {this.themeType = type; ,}}}); export default theme;Copy the code

Call as follows:

<script setup lang="ts"> import theme from '@/store/theme' const myTheme = theme() mytheme.setthemetype (' dark color ') </script>  <template> {{myTheme.themeColor}} </template>Copy the code

SCSS

I don’t have to tell you too much about this, but who hasn’t used sass or less? Let’s go straight to the configuration process:

Install the configuration
npm i sass -D
Copy the code

We will create a variable. SCSS file under SRC/Assets to store our global CSS variables. We will first configure only one theme color:

At the same time, we also create a new index. SCSS in SRC/Assets directory and import the SCSS file we will create in the future. And introduce it in main.ts

$theme-color: #2080F0FF
Copy the code

Then open the vite.config.ts file, plus the introduction of CSS configuration

css: {
  preprocessorOptions: {
    scss: {
      additionalData: `
      @import "@/assets/styles/variables.scss";
    `,
      javascriptEnabled: true,
    },
  },
},
Copy the code
Usage in components

After the above configuration, we can use the variables we defined in variables.scss directly in the component without any introduction:

<style lang="scss">
.myclass {
  color: $theme-color;
}
</style>
Copy the code

Windi CSS

Windi CSS can be seen as a superior alternative to Tailwind CSS, offering faster load times, full compatibility with Tailwind V2.0, and a host of additional cool features.

We can do atomized CSS programming, and the framework automatically does the importing on demand work for us;

Install the configuration
npm i -D vite-plugin-windicss windicss
Copy the code

After installing the dependencies, we installed the plug-in in viet.config.ts

import WindiCSS from 'vite-plugin-windicss'

export default {
  plugins: [
    WindiCSS(),
  ],
}
Copy the code

We then introduce it in main.ts

import 'virtual:windi.css'
Copy the code

Axios

Install the configuration
npm i axios -S
Copy the code
The basic package

After the installation, we will create a new http.ts configuration file in the SRC/API directory to encapsulate the AXIos method.

// src/api/http.ts import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios'; import { ElMessage } from 'element-plus'; import showCodeMessage from '@/api/code'; const BASE_PREFIX = '/api'; Const service: AxiosInstance = axios.create({baseURL: BASE_PREFIX, // timeout: Headers: {' content-type ': 'application ',},}); / / request interceptor service. Interceptors. Request. Use ((config: AxiosRequestConfig) => {// TODO = // TODO = // TODO = // TODO = // }, (error: AxiosError) => { return Promise.reject(error); }); / / response interceptor service. Interceptors. Response. Use ((the response: AxiosResponse) => { if (response.status === 200) { return response; } ElMessage.info(JSON.stringify(response.status)); return response; }, (error: AxiosError) => { const { response } = error; if (response) { ElMessage.error(showCodeMessage(response.status)); return Promise.reject(response.data); } elmessage. warning(' Network connection is down, please try again later! '); return Promise.reject(error); }); export default service;Copy the code

Let’s create a new code.ts to store the processing logic for the status code we receive after the HTTP request

// src/api/code.ts declare interface codeMessageMapTypes { 400: string; 401: string; 403: string; 404: string; 405: string; 500: string; [key: string]: string; } const codeMessageMap: codeMessageMapTypes = {400: '[400]: request parameter error ', 401: '[401]: account not logged in ', 403: '[403]: access denied ', 404: '[404] : request path error, 405:' [405] : request method error, 500: '[500] : server error'}; const showCodeMessage = (code: number | string): String = > {return codeMessageMap [JSON stringify (code)] | | 'abnormal network connection, please try again later. '; }; export default showCodeMessage;Copy the code

VueUse

VueUse is a collection of reactive Vue utilities that allow us to make all sorts of things reactive without having to write the hooks manually

Install the configuration
npm i npm i @vueuse/core -D
Copy the code

After installing dependencies, we also need to configure automatic import on demand in viet.config. ts

import { VueUseComponentsResolver } from 'unplugin-vue-components/resolvers';

export default defineConfig({
  plugins: [
    AutoImport({
      imports: ['@vueuse/core'],
    }),
    Components({
      resolvers: [VueUseComponentsResolver()],
    }),
  ],
});
Copy the code

Once configured, we don’t need to import methods ourselves and can use them directly

NProgress

This plugin, which I’m sure most of you have used, helps us add a page loading hint at the top: a loading progress bar and a turning circle

Install the configuration
npm i --save nprogress
Copy the code

We also need to install typescript types because we use typescript

npm i @types/nprogress -D
Copy the code

After the installation, we went back to SRC /router/index.ts to configure our route guard

import NProgress from 'nprogress';
router.beforeEach((to, from) => {
  if (!NProgress.isStarted()) {
      NProgress.start();
  }
});

router.afterEach((to, from) => {
  NProgress.done();
});
Copy the code

Create a new nprogress. SCSS file in SRC /assets/styles and configure it as follows:

/* Make clicks pass-through */ #nprogress { pointer-events: none; } #nprogress .bar { background: $theme-color; position: fixed; z-index: 1031; top: 0; left: 0; width: 100%; height: 2px; } /* Fancy blur effect */ #nprogress .peg { display: block; position: absolute; right: 0px; width: 100px; height: 100%; box-shadow: 0 0 10px $theme-color, 0 0 5px $theme-color; Opacity: 1.0; -webkit-transform: rotate(3deg) translate(0px, -4px); -ms-transform: rotate(3deg) translate(0px, -4px); transform: rotate(3deg) translate(0px, -4px); } /* Remove these to get rid of the spinner */ #nprogress .spinner { display: block; position: fixed; z-index: 1031; top: 15px; right: 15px; } #nprogress .spinner-icon { width: 18px; height: 18px; box-sizing: border-box; border: solid 2px transparent; border-top-color: $theme-color; border-left-color: $theme-color; border-radius: 50%; -webkit-animation: nprogress-spinner 400ms linear infinite; animation: nprogress-spinner 400ms linear infinite; } .nprogress-custom-parent { overflow: hidden; position: relative; } .nprogress-custom-parent #nprogress .spinner, .nprogress-custom-parent #nprogress .bar { position: absolute; } @-webkit-keyframes nprogress-spinner { 0% { -webkit-transform: rotate(0deg); } 100% { -webkit-transform: rotate(360deg); } } @keyframes nprogress-spinner { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); }}Copy the code