start

Vite2’s new front-end build tool can significantly improve the front-end development experience. Without further words, let’s try it out first

Build vITE project

Vite requires node.js version >= 12.0.0.

# NPM
npm init @vitejs/app

# YARN 
yarn create @vitejs/app
Copy the code

Then follow the operation, select the template you want to execute.

We can directly specify the project name and the template you want to use through the additional command line option. We can directly generate the project

# NPM 6. X NPM init @vitejs/app my-vue-app --template vue # NPM 7+  npm init @vitejs/app my-vue-app -- --template vue # yarn yarn create @vitejs/app my-vue-app --template vueCopy the code

Configuration items

First look at the project structure:

# my - vue - app ├ ─ ─ index. The HTML ├ ─ ─ package. The json ├ ─ ─ public │ └ ─ ─ the favicon. Ico ├ ─ ─ the SRC │ ├ ─ ─ app. Vue │ ├ ─ ─ assets │ │ └ ─ ─ Logo.png │ ├─ ├─ class.txt │ ├─ class.txt │ ├─ class.txt │ ├─ class.txt │ ├─ class.txt │ ├─ class.txtCopy the code

When we open the project, we see that the structure is similar to cli4, but much simpler.

There is no out-of-the-box template for Vite2 yet, but the documentation is fairly comprehensive. Vite Chinese document,

Let’s configure the following:

1. vue-router

# Vue-Router4.0 has been released, we use version 4.0 # If you want to download the latest version yarn add vue-router@4. # NPM NPM install [email protected] # YARN YARN add [email protected]Copy the code
1. Create the router folder in SRC and create the index.js file
 import { createRouter, createWebHashHistory } from 'vue-router'
 import Home from '.. /views/Home.vue'

 const routes = [
   {
     path: '/'.name: 'Home'.component: Home
   },
   {
     path: '/about'.name: 'About'.component: () = > import('@/views/About.vue') // @/views alias}]const router = createRouter({
   history: createWebHashHistory(import.meta.env.BASE_URL),
   routes
 })

 export default router

Copy the code
2. Import the router in main.js
import { createApp } from 'vue'
import router from './router'
import App from './App.vue'

createApp(App).use(router).mount('#app')
Copy the code
3. Modify the app. vue file
<template>
  <router-view />
</template>

<script setup>
</script>

<style></style>         
Copy the code
4. SRC /views Add home.vue
<template>
  <router-link to="/">
    Home
  </router-link>
  <router-link to="/about">
    About
  </router-link>
</template>

<script>
export default {

}
</script>
Copy the code
5. SRC /views Add about.vue
//  About.vue
<template>
  <div>About</div>
</template>

<script>
export default {

}
</script>

<style></style>

Copy the code

Enter http://localhost:8000/#/about in the link and the content shows about. Congratulations, you are configured successfully.

6. Modular

If you want to modularize your project, you can configure it as follows (similar to vuEX). If not, skip this step

├ ─ ─ index. The HTML ├ ─ ─ package. The json ├ ─ ─ public │ └ ─ ─ the favicon. Ico ├ ─ ─ the SRC │ ├ ─ ─ App. Vue │ ├ ─ ─ assets │ │ └ ─ ─ logo. The PNG │ ├ ─ ─ Components │ │ └ ─ ─ the HelloWorld. Vue │ ├ ─ ─ the main, js │ ├ ─ ─ the router │ │ └ ─ ─ index. The js │ └ ─ ─ views │ ├ ─ ─ Home. Vue │ ├ ─ ─ the about │ │ ├ ─ ─ index. Vue │ │ └ ─ ─ the router │ │ └ ─ ─ index. The js │ └ ─ ─ indo │ ├ ─ ─ index. The vue │ └ ─ ─ the router │ └ ─ ─ index. The js ├ ─ ─ tree. The md ├ ─ ─ Vite. Config. Js └ ─ ─ yarn. The lockCopy the code
 // about/router/index.js
 export default[{path: '/about'.name: 'About'.component: () = > import('.. /index.vue'),},];Copy the code

Each module contains a router folder. You can dynamically import routes in the module. Instead of importing routes one by one, set them in SRC/Router

// src/router/index.js import { createRouter, createWebHashHistory } from 'vue-router' import Home from '.. /views/Home.vue' const routesModules = import.meta.globEager('.. /views/**/*.js') const modules = [] Object.keys(routesModules).forEach(key => { modules.push(... routesModules[key].default) }) console.log('modules: ', modules); const routes = [ { path: '/', name: 'Home', component: Home }, ...modules ] const router = createRouter({ history: createWebHashHistory(import.meta.env.BASE_URL), routes }) export default routerCopy the code

Enter http://localhost:8000/#/info in the link to display Info, and you have successfully configured it.

2. Install the SCSS

# NPM
npm install sass -D 

# YARN 
yarn add sass -D 
Copy the code

Generally we are set up the public SCSS file, unified Settings of the public style, convenient unified modification of the unified style

1. Create a styles folder in SRC and a common. SCSS file
$themeColor: #f4364c;
Copy the code
Common. SCSS allows you to use common styles directly in vue files
import { defineConfig } from 'vite'
const {resolve} = require('path')
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  server: {
    port: 8000 // Configure the enabled port number
  },
  resolve: {// Set the alias
    alias: {'@/views': resolve(__dirname, 'src/views/'),
      '@/styles': resolve(__dirname, 'src/styles/')}},css: {
    preprocessorOptions: {
      // Introduce common styles
      scss: {
        additionalData: `@import "@/styles/common.scss"; `}}}})Copy the code

Testing:

# About.vue
<template>
 <div class="about">About</div>
</template>

<script>
export default {

}
</script>

<style lang="scss" scoped>
.about {
  color: themeColor;
 }
</style>

Copy the code

3. vuex

# Vuex official version has been released, we use version 4.0, # if you want to download the latest version yarn add vuex@4. # NPM NPM install [email protected] # YARN YARN add [email protected]Copy the code
1. Add the store folder under SRC and create index.js
 import {createStore} from 'vuex'
      
 const store = createStore({
   state: {
     count: 0
   },
   mutations: {
     increment (state) {
       state.count++
     }
   },
   getters: {},actions: {}})export default store
Copy the code
2. Introduce vuex in main.js
 import { createApp } from 'vue'
 import router from './router'
 import store from './store'
 import App from './App.vue'

 createApp(App).use(router).use(store).mount('#app')
Copy the code
3. For persistence, download Vuex-PersistedState
 # NPM
 npm [email protected]

 # YARN
 yarn add [email protected]
Copy the code
4. Configure it in store/index.js
  import { createStore } from 'vuex'
  import createPersistedState from 'vuex-persistedstate'

  const store = createStore({
    ...

    plugins: [
      createPersistedState({
        storage: window.sessionStorage // Change the state of the storage})]// State persistence
  })

  export default store
Copy the code
5. If you want to modular, you can refer todetails

4. Eslint

Let our code have better code specification and uniform code format, aspects of multi-person development, and read the code.

1. Install ESLint and other dependencies first
 # NPM
 npm install eslint eslint-config-airbnb eslint-plugin-import eslint-plugin-vue -D
 
 # YARN 
 yarn add eslint eslint-config-airbnb eslint-plugin-import eslint-plugin-vue -D
Copy the code
2. Add.eslintrc.js to the root directory
module.exports = {
  extends: ['plugin:vue/vue3-essential'.'airbnb-base'].parserOptions: {
    ecmaVersion: 2020.sourceType: 'module',},plugins: ['vue'].rules: {
    // Write your own rules you want to configure
    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off'.// Consele is disabled in production
    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'.// The production environment disables the debugger
    'linebreak-style': 'off'.// Ignore detecting the newline style
    'vue/max-attributes-per-line': 'off'.// Turn off force HTML tag wrap
    'no-param-reassign': ['error', { props: false}].// Allows you to modify attribute values in parameters
    'prefer-destructuring': ['error', { object: true.array: false}].// Allow arrays to be evaluated by subscript
    'max-len': 'off'.// Object options
    'no-use-before-define': 'off'.// allow use before definition
    'func-names': 'off'.// Allow anonymous functions
    'no-shadow': ['error', { allow: ['state']}],// Allow it to be shaded
    'import/prefer-default-export': 'off'.// Whether to add default when the module outputs only one variable
    'no-plusplus': 'off'.// Unary operator
  },
  overrides: [{files: ['*.vue'].rules: {
        // Write rules to override vue files}},]};Copy the code
3. The configuration vscode

Add the.vscode folder to the root directory and add settings.json to the folder

// settings.json
{
    "editor.formatOnSave": true."editor.codeActionsOnSave": {
        "source.fixAll": true."source.fixAll.eslint": true
    },
    "[json]": {
        "editor.defaultFormatter": "vscode.json-language-features"}},Copy the code
4. Test eslint

Open a random file. Let’s use main.js as an example,

If ESLint reports an error, congratulations that ESLint is working.

Press Ctrl + Shift + P, type ESLint: Manage Library Execution selection and press Enter

The following display will appear:

Select the Allow Everywhere option in the pop-up box, and the icon in the lower right corner changes to √√ESLint

Clicking Save automatically formats our code and normalizes our code.

ESLint Airbnb code specification Vue code specification

5. Install Element Plus

# NPM
npm install element-plus --save

# YARN
yarn add element-plus --save
Copy the code

Element-ui is introduced in main.js

import { createApp } from 'vue';
import ElementPlus from 'element-plus';
import router from './router';
import App from './App.vue';
import 'element-plus/lib/theme-chalk/index.css';

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

6. axios

1. Download axios
# NPM
npm install axios --save

# YARN
yarn add axios --save
Copy the code
2. Wrap the AXIOS request
/ * * *@file Axios requests encapsulation */
import axios from 'axios';
import { ElMessage } from 'element-plus';
// import { store } from '.. /store';

// Request failed error message
function checkCode(message) {
  // Error message is displayed
  ElMessage.closeAll();
  ElMessage({ message, type: 'error'.customClass: 'deep-message' });
  // ElMessage.error(message)
}

// Response time
axios.defaults.timeout = 10000;
// The 'withCredentails' option indicates whether the request is cross-domain
axios.defaults.withCredentials = true;
// Set the default request header
axios.defaults.headers = {
  'X-Requested-With': 'XMLHttpRequest'.'Content-Type': 'application/json; charset=UTF-8'};const pending = []; // Declare an array to store the cancellation function and ajax identifier for each Ajax request
const cancelToken = axios.CancelToken;
const removePending = (config) = > {
  const resUrl = `${config.url}&${config.method}`;
  // eslint-disable-next-line no-restricted-syntax
  for (const p in pending) {
    if (pending[p].url === resUrl) { // Execute the function body when the current request exists in the array
      pending[p].fn(); // Perform the cancel operation
      pending.splice(p, 1); // Remove this record from the array}}};// Add request interceptor
axios.interceptors.request.use(
  (config) = > {
    / / access token
    // if (store.state.common.token) {
    // // determines whether a token exists, and if so, adds a token to each HTTP header
    // config.headers.Authorization = store.state.common.token;
    // }
    removePending(config); // Perform a cancel operation before an Ajax send
    // eslint-disable-next-line new-cap
    config.cancelToken = new cancelToken((cf) = > {
      // The ajax identifier here is a string concatenated with the request address and request, of course you can choose some other way
      pending.push({ url: `${config.url}&${config.method}`.fn: cf });
    });
    return config;
  },
  (error) = >
    // endLoading()
    // eslint-disable-next-line implicit-arrow-linebreak
    Promise.reject(error),

);

// Add return interceptor
axios.interceptors.response.use(
  (response) = > {
    // endLoading()
    removePending(response.config); // Perform a cancel operation after an Ajax response to remove the completed request from pending
    const { data, data: { code } } = response || {};
    const listCode = [0.1001.1000.1100];
    if (typeofresponse ! = ='undefined') {
      if (listCode.includes(code)) return data;
      if (response.data.msg) return response.data;
      checkCode(response.data.message);
    }
    return ' ';
  },
  (error) = > {
    if (error && error.response) {
      switch (error.response.status) {
        case 400:
          error.message = 'Request error';
          break;
        case 401:
          error.message = 'Login expired, please log in again';
          // Jump to the login screen
          localStorage.clear();
          sessionStorage.clear();
          break;
        case 403:
          error.message = 'Access denied';
          break;
        case 404:
          error.message = 'Request failed';
          break;
        case 408:
          error.message = 'Request timed out';
          break;
        case 500:
          error.message = 'Server internal error';
          break;
        case 501:
          error.message = 'Service not implemented';
          break;
        case 502:
          error.message = 'Unable to connect to server';
          break;
        case 503:
          error.message = 'Service unavailable';
          break;
        case 504:
          error.message = 'Connection to server timed out';
          break;
        case 505:
          error.message = 'HTTP version not supported ';
          break;
        default:}}else {
      // error. Message = 'unable to connect to server'
    }
    // Error handling returned
    return Promise.reject(error); });export default {
  async get(url, params) {
    try {
      const res = await axios.get(url, { params });
      return typeofres.data ! = ='undefined' && res.data;
    } catch (err) {
      returncheckCode(err.message); }},async post(url, params) {
    try {
      const res = await axios({
        method: 'post',
        url,
        data: params,
      });
      return typeofres.data ! = ='undefined' && res.data;
    } catch (err) {
      returncheckCode(err.message); }},async put(url, params) {
    try {
      const res = await axios({
        method: 'put',
        url,
        data: params,
      });
      return typeofres.data ! = ='undefined' && res.data;
    } catch (err) {
      returncheckCode(err.message); }},async delete(url, params) {
    try {
      const res = await axios.delete(url, { params });
      return typeofres.data ! = ='undefined' && res.data;
    } catch (err) {
      returncheckCode(err.message); }},async all(url, params) {
    try {
      const res = await axios.all(url, { params });
      return typeofres.data ! = ='undefined' && res.data;
    } catch (err) {
      returncheckCode(err.message); }}};Copy the code
3. Local debugging Settings are cross-domain

You can view details about configuring cross-domains using proxy

// vite.config.js
export default {
  resolve: {
    proxy: {
      '/api': {
        target: 'https://xxx.com/api'.changeOrigin: true,},},},}Copy the code
Use 4.
// about/api/index.js
import $api from '@/utils/request';

export default {
  getData(params) {
    return $api.get('/api/basis/Data',params); }};Copy the code
// about/index.vue
<template>
  <div>about</div>
</template>

<script>
import aboutApi from './api';

export default {
  setup() {
    const test = async() = > {const result = await aboutApi.getData();
      console.log('result: ', result); }; test(); }};</script>

<style></style>
Copy the code

If you don’t want the hassle, install k-CLI and use templates directly.

Other features are in development, stay tuned!!