update

√ 2020-08-23 Added VW adaptation

√ 2020-04-21 Optimize documents and projects

√ 2020-02-05 Upgrade vuE-CLI4, add Eslint+Pettier, add Vant component global import on demand

describe

Based on vuE-CLI4.0 + WebPack 4 + Vant UI + SASS + REM adaptation scheme + AXIOS packaging, the scaffolding of mobile end template was constructed

Project address: Github

Node Version Requirements

Vue CLI requires Node.js version 8.9 or later (8.11.0+ recommended). You can use NVM or NVM-Windows to manage multiple versions of Node on the same computer.

This example node.js 12.14.1

Start the project

git clone https://github.com/sunniejs/vue-h5-template.git

cd vue-h5-template

npm install

npm run serve
Copy the code

directory

  • Tick the Vue – cli4
  • √ Configure multiple environment variables
  • √ REM adaptation
  • √ VM adaptation solution
  • √ Load VantUI components as required
  • √ Sass global style
  • √ Vuex status management
  • Tick the Vue – the router
  • √ Axios encapsulation and interface management
  • √ Webpack 4 Vue.config. js Basic configuration
  • √ Configure the alias
  • √ Configure proxy across domains
  • √ Configure package analysis
  • √ Configure externals to import CDN resources
  • Tick off the console. The log
  • √ splitChunks package third-party modules separately
  • √ Add COMPATIBILITY with IE
  • √ Eslint+Pettier Unified development specification

Multi-environment development

The scripts in package.json are configured to serve stage builds, using –mode XXX to execute different environments

  • throughnpm run serveStart the local PC and rundevelopment
  • throughnpm run stagePackage the tests and execute themstaging
  • throughnpm run buildPackage formally, executeproduction
"scripts": {
  "serve": "vue-cli-service serve --open",
  "stage": "vue-cli-service build --mode staging",
  "build": "vue-cli-service build",
}
Copy the code

Configuration is introduced

Variables that begin with VUE_APP_ are accessible in code through process.env.vue_app_. For example,VUE_APP_ENV = ‘development’ is accessed through process.env.vue_app_env. In addition to the VUE_APP_* variable, two special variables NODE_ENV and BASE_URL are always available in your application code

Create.env.* in the project root directory

  • .env.development Local development environment configuration
NODE_ENV='development'
# must start with VUE_APP_
VUE_APP_ENV = 'development'
Copy the code

  • Env.staging test environment configuration
NODE_ENV='production'
# must start with VUE_APP_
VUE_APP_ENV = 'staging'
Copy the code

  • .env.production Specifies the environment configuration
 NODE_ENV='production'
# must start with VUE_APP_
VUE_APP_ENV = 'production'
Copy the code

We haven’t defined many variables here, just the basic VUE_APP_ENV development staging Production variables which we manage in SRC /config/env.*.js.

There is a problem here, since there is a file for setting variables for different environments, why go to config and create three corresponding files?

Easy to modify, do not need to restart the project, in line with the development habit.

config/index.js

Process.env. NODE_ENV const config = require('./env.' + process.env.vue_app_env) module.exports = configCopy the code

Configure environment variables. The local environment file env.develop. js is used as an example. You can modify the variables as required

Module. exports = {title: 'vue-h5-template', baseUrl: 'http://localhost:9018', // module.exports = {title: 'vue-h5-template', baseUrl: 'http://localhost:9018', 'https://test.xxx.com/api', // local API request address APPID: 'XXX ', APPSECRET:' XXX '}Copy the code

Depending on the environment, the variables will be different

Import {baseApi} from '@/config' console.log(baseApi) import {baseApi} from '@/config' console.log(baseApi)Copy the code

Rem adaptation scheme

Many friends will ask me about adaptation. Because we use Vant UI, we have to follow the design specification of Vant UI 375. Generally, our design will be on the UI diagram
Send it to Blue Lake, and we’ll have the size we need. So let’s generalize rem.

By default, styles in Vant use px units. If you want to use REM units, the following two tools are recommended:

  • postcss-pxtoremIs apostcssPlug-in for converting units torem
  • lib-flexibleUsed to set theremAt baseline
PostCSS configuration

The following provides a basic PostCSS configuration that can be modified based on project requirements

// https://github.com/michael-ciniawsky/postcss-load-config module.exports = { plugins: { autoprefixer: {overrideBrowserslist: ['Android 4.1', 'iOS 7.1', 'Chrome > 31', 'ff > 31', 'IE >= 8']}, 'postcss-pxtorem': {rootValue: 37.5, propList: ['*']}}}Copy the code

More details: Vant

Beginners must see, old birds skip

A lot of people ask me about fit.

We know that 1rem is equal to the font-size PX value of the HTML root element. Vant UI set rootValue: 37.5, which you can see on iPhone 6 (1rem equals 37.5px) :

< HTML data - DPR = "1" style = "font, size: 37.5 px;" ></html>Copy the code

The root element may have a different font size when switching between different models. When you write CSS PX, the program converts it to REM to match.

Since we are using Vant components, we need to write the style as rootValue: 37.5.

For example: the design gives you a 750px by 1334px image that covers the screen on the iPhone6 and other models.

  • whenrootValue: 70, the stylewidth: 750px; height: 1334px;The picture will fill up the iPhone6 screen, and when you switch to another model, the picture will fill up as well.
  • whenRootValue: 37.5When stylewidth: 375px; height: 667px;Images will fill the iPhone6 screen.

That’s 375px CSS for iPhone 6. Other you can according to your design, to write the corresponding style can be.

Of course, you can use 100% if you want to fill the screen, but this is just an example.

<img class="image" src="https://imgs.solui.cn/weapp/logo.png" /> <style> /* rootValue: 75 */ .image { width: 750px; height: 1334px; } /* rootValue: 37.5 */. Image {width: 375px; height: 667px; } </style>Copy the code

Vm Adaptation Scheme

This project uses rem adaptation scheme. In fact, no matter which scheme you use, you do not need to calculate how much REM or VW 12px is, there will be special tools to help you do it. If you want to use a VW, you can switch as follows.

1. Install dependencies

npm install postcss-px-to-viewport -D
Copy the code

2. Modify. Postcssrc. Js

Modify the.postcsrc. Js file in the root directory as follows

// https://github.com/michael-ciniawsky/postcss-load-config module.exports = { plugins: { autoprefixer: {overrideBrowserslist: ['Android 4.1', 'iOS 7.1', 'Chrome > 31', 'ff > 31', 'ie >= 8']}, 'postcss-px-to-viewPort ': {viewportWidth: 375, // The width of the window corresponds to the width of our design, usually 750 unitPrecision: 3, // Specify the decimal number of the window unit value converted to 'px' (many times not divisible) viewportUnit: 'vw', // specify the window unit to convert to. Recommend using vw selectorBlackList: ['.ignore', '.hairlines'], // Specify a class that is not converted to Windows units. It can be customized, and can be added indefinitely. 1, // less than or equal to '1px' does not convert to window units, you can also set to the value you want mediaQuery: false // Allows conversion of 'px' in media queries}}}Copy the code

3. Delete the original REM related code

SRC /main.js delete the following code

// Mobile adaptation import 'lib-flexible/flexible.js'Copy the code

Package. json remove the following code

"Lib - flexible", "^ 0.3.2", "postcss - pxtorem" : "^ 5.1.1."Copy the code

When it runs, the F12 element CSS is vw units

VantUI components are loaded on demand

Vant automatically import components on demand (recommended)

Babel-plugin-import is a Babel plug-in that automatically converts the way import is written to import on demand during compilation

Installing a plug-in

npm i babel-plugin-import -D
Copy the code

In the Babel. Config. Js Settings

// For users using babel7, const plugins = [['import', {libraryName: 'vant', libraryDirectory: 'es', style: true }, 'vant' ] ] module.exports = { presets: [['@vue/cli-plugin-babel/preset', {useBuiltIns: 'usage', corejs: 3}]], plugins }Copy the code

However, every time the page is used, it still needs to be imported, which is very troublesome. The project manages the components under SRC /plugins/ ant

Import Vue from 'Vue' import {Button, List, Cell, Tabbar, TabbarItem} from 'vant' Vue.use(Button) Vue.use(Cell) Vue.use(List) Vue.use(Tabbar).use(TabbarItem)Copy the code

Sass global style

First of all, you may encounter node-sass installation failure, don’t give up trying again!!

Each page’s own style is written in its own.vue file scoped adds the concept of a domain to CSS as its name suggests.

<style lang="scss">
    /* global styles */
</style>

<style lang="scss" scoped>
    /* local styles */
</style>
Copy the code

The directory structure

Vue-h5-template All global styles are set in the @/ SRC /assets/ CSS directory

├── Assets │ ├─ CSS │ ├─ ├.scSS # ├─ mixin. SCSS # Mixin │ ├─ variablesCopy the code

Custom Vant-UI styles

Now let’s talk about how to rewrite the vuant-UI style. Since the styles of the Ant-UI are introduced globally, you can’t add scoped if you want to cover only the vant styles of the page. If you want to cover only the Vant styles of the page, you can add a class to its parent and use the namespace to solve the problem.

.container {/* Your namespace */. Van-button {/* ant- UI element */ margin-right: 0px; }}Copy the code

The parent component changes the child component style depth selector

When you want to modify the style of the child component when the child component is scoped, go to >>> :

<style scoped>
.a >>> .b { /* ... */ }
</style>
Copy the code

The global variable

The vue. Config. js configuration uses the css.loaderOptions option to inject sass’s mixin variables into the global, Instead of importing manually, configure $CDN to import the CDN address as a variable, passing shared global variables to all Sass/Less styles:

const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV) const defaultSettings = require('./src/config/index.js') module.exports = { css: {extract: IS_PROD, sourceMap: false, loaderOptions: {// Pass the SCSS option to SCSS: {// Inject 'sass' 'mixin' 'variables' to global, $CDN can configure picture CDN // details: https://cli.vuejs.org/guide/css.html#passing-options-to-pre-processor-loaders prependData: ` @import "assets/css/mixin.scss"; @import "assets/css/variables.scss"; $cdn: "${defaultSettings.$cdn}"; ',},},},}Copy the code

$CDN can be accessed in.vue files using this.$CDN

Import {$CDN} from '@/config' import {$CDN} from '@/config' Vue.prototype.$cdn = $cdnCopy the code

Use in CSS and JS

<script>
    console.log(this.$cdn)
</script>
<style lang="scss" scoped>
    .logo {
        width: 120px;
        height: 120px;
        background: url($cdn+'/weapp/logo.png') center / contain no-repeat;
    }
</style>
Copy the code
[](https://sunniejs.github.io/vue-h5-template/#/zh-cn/vant)

Vuex status management

The directory structure

├ ─ ─ store │ ├ ─ ─ modules │ │ └ ─ ─ app. Js │ ├ ─ ─ index. The js │ ├ ─ ─ getters. JsCopy the code

Introduced the main. Js

import Vue from 'vue'
import App from './App.vue'
import store from './store'
new Vue({
  el: '#app',
  router,
  store,
  render: h => h(App)
})
Copy the code

use

<script> import {mapGetters} from 'vuex' export default { computed: { ... mapGetters(['userName']) }, methods: {this.$store. Dispatch('setUserName', 'setUserName'); The organization is waiting for you.Copy the code

Vue-router

This case uses the hash mode, and the developer modifies the mode base as required

Note: If you use history mode, the publicPath in vue.config.js needs to be modified accordingly

Go to: vue.config.js basic configuration

import Vue from 'vue' import Router from 'vue-router' Vue.use(Router) export const router = [ { path: '/', name: 'index', Component: () => import('@/views/home/index'), // keepAlive: {title: 'home ', // False // keep-alive flag}}] const createRouter = () => new Router({// mode: Js publicPath // base: '/app/', scrollBehavior: () => ({y: 0}), routes: router }) export default createRouter()Copy the code

More: Vue Router

Axios encapsulation and interface management

Utils /request.js encapsulates AXIOS and developers need to make changes based on the background interface.

  • service.interceptors.request.useRequest headers can be set, such as Settingstoken
  • config.hideloadingIt is set in the interface parameters in the API folder, as described below
  • service.interceptors.response.useIn the interface can return data processing, such as 401 delete local information, login again

Interface management

Unify the management interface in the SRC/API folder

  • You can set up multiple module docking interfaces, such ashome.jsHere is the interface of the home pageuser.js
  • urlInterface address, which will be concatenated when requestedconfigUnder thebaseApi
  • methodRequest method
  • dataRequest parametersqs.stringify(params)Is the data serialization operation
  • hideloadingThe defaultfalse, is set totrueSome interfaces in the loading UI interaction do not need to be aware of by the user
Import qs from 'qs' // axios import request from '@/utils/request' //user API //user information export function getUserInfo(params) { return request({ url: '/user/userinfo', method: 'post', data: qs.stringify(params), hideloading: True // Hide loading component})}Copy the code

How to call

Import {getUserInfo} from '@/ API /user.js' const params = {user: 'sunnie'} getUserInfo(params) .then(() => {}) .catch(() => {})Copy the code

Webpack 4 Vue.config.js basic configuration

If your Vue Router mode is hash

publicPath: './',
Copy the code

If your Vue Router mode is History, the publicPath here is consistent with your Vue Router Base

publicPath: '/app/',
Copy the code

const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV) module.exports = { publicPath: './', // The basic URL of the application package. Vue-router Hash mode: // publicPath: '/app/', // Basic URL of the application package. Vue -router history mode uses outputDir: 'dist', // production build file directory assetsDir: 'static', // outputDir static resources (js, CSS, img, fonts) directory lintOnSave: false, productionSourceMap: False, // If you don't need the source map for production, you can set it to false to speed up production builds. DevServer: {port: 9020, // port number open: false, // Open browser overlay: {// Display full-screen overlay overlay in the browser when compiler errors or warnings occur: false, errors: true } // ... }}Copy the code

Configuring alias Alias

const path = require('path') const resolve = dir => path.join(__dirname, dir) const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV) module.exports = { chainWebpack: Set ('@', resolve(' SRC ')).set('assets', resolve(' SRC /assets')).set(' API ', resolve('src/api')) .set('views', resolve('src/views')) .set('components', resolve('src/components')) } }Copy the code

Configuring proxy across domains

If your project requires cross-domain Settings, you need to annotate the vue.config.js proxy and configure the parameters accordingly

Note: you will also need to SRC/config/env. Development. In the js baseApi set to ‘/’

module.exports = { devServer: { // .... Proxy: {// configure cross-domain '/ API ': {target: 'https://test.xxx.com', // interface domain name // ws: true, // whether to enable webSockets changOrigin: True, // Enable the proxy and create a virtual server locally pathRewrite: {'^/ API ': '/'}}}}}Copy the code

Use for example: SRC/API /home.js

export function getUserInfo(params) {
  return request({
    url: '/api/userinfo',
    method: 'get',
    data: qs.stringify(params)
  })
}
Copy the code

Configuration packaging analysis

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin module.exports = { chainWebpack: Plugin ('webpack-report'). Use (BundleAnalyzerPlugin, [{analyzerMode: 'static' } ]) } } }Copy the code

npm run build
Copy the code

Configure externals to import CDN resources

In this version, CDN is no longer introduced. I tested using CDN and not using CDN. Not using CDN takes less time than using CDN. Many articles on the net test CDN speed fast, this developer can be tested with the actual.

In addition, the public CDN used in the project is unstable, and it takes time to resolve the domain name (please try to use the same domain name if you want to use it).

Because the page stops parsing every time it encounters a

The research has not been put on our own CDN server, and will continue to be optimized later

const defaultSettings = require('./src/config/index.js') const name = defaultSettings.title || 'vue mobile template' const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV) // externals const externals = { vue: 'Vue', 'vue-router': 'VueRouter', vuex: 'Vuex', vant: 'vant', axios: // dev dev: {CSS: [], js: []}, // build: {CSS: [] [' https://cdn.jsdelivr.net/npm/[email protected]/lib/index.css '], js: [' https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.min.js', 'https://cdn.jsdelivr.net/npm/[email protected]/dist/vue-router.min.js', 'https://cdn.jsdelivr.net/npm/[email protected]/dist/axios.min.js', 'https://cdn.jsdelivr.net/npm/[email protected]/dist/vuex.min.js', 'https://cdn.jsdelivr.net/npm/[email protected]/lib/index.min.js'].}} the module exports = {configureWebpack: Config => {config.name = name // Modify the configuration for the production environment... if (IS_PROD) { // externals config.externals = externals } }, chainWebpack: Plugin (' HTML ').tap(args => {if (IS_PROD) {args[0].cdn = cdn.build } else { args[0].cdn = cdn.dev } return args }) } }Copy the code

Add to public/index.html

<! - use the CDN CSS file - > < % for (I in htmlWebpackPlugin var. The options. The CDN && htmlWebpackPlugin. Options. The CDN. CSS) {% > < link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="preload" as="style" /> <link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet" /> <% } %> <! -- Using CDN accelerated JS files, Under configuration in vue. Config. Js - > < % for (I in htmlWebpackPlugin var. The options. The CDN && htmlWebpackPlugin. Options. The CDN. Js) {% > < script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script> <% } %>Copy the code

Remove the console log

Console. log for the test environment and local environment are retained

npm i -D babel-plugin-transform-remove-console
Copy the code

Configure in babel.config.js

// get VUE_APP_ENV non-node_env, Console const IS_PROD = ['production', 'prod']. Includes (process.env.vue_app_env) const plugins = [[' import', { libraryName: 'vant', libraryDirectory: 'es', style: true }, 'vant']] // Remove console.log if (IS_PROD) {plugins.push('transform-remove-console')} module.exports = {presets: exports: [['@vue/cli-plugin-babel/preset', {useBuiltIns: 'entry'}]], plugins }Copy the code

SplitChunks packages third-party modules separately

module.exports = { chainWebpack: config => { config.when(IS_PROD, config => { config .plugin('ScriptExtHtmlWebpackPlugin') .after('html') .use('script-ext-html-webpack-plugin', [{/ / the runtime as inline introduced not exist alone the inline: / runtime \.. * \. Js $/}]). The end () config. Optimization. SplitChunks ({chunks: Commons: {name: 'chunk-commons', test: {name: 'chunk-commons', test: {name: 'chunk-commons', test: Resolve (' SRC /components'), minChunks: 3, // will be used at least three times to separate chunks True // Indicates whether to use the existing chunk. If true, it indicates that if the chunk contains modules that have been extracted, no new chunk will be generated. }, node_vendors: {name: 'chunk-libs', chunks: 'initial', // only package initially dependent third parties test: /[\\/]node_modules[\\/]/, priority: 10}, vantUI: {name: 'chunk-vantui ', // unpack vantUI priority: 20, // /[\\/]node_modules[\\/]_? vant(.*)/ } } }) config.optimization.runtimeChunk('single') }) } }Copy the code

Adding COMPATIBILITY with IE

Please, use required parts of core-JS and regenerator-runtime/ Runtime Separately

@babel/polyfill deprecated, using core-js and regenerator-Runtime

npm i --save core-js regenerator-runtime
Copy the code

Add it in main.js

// Compatible with IE // https://github.com/zloirock/core-js/blob/master/docs/2019-03-19-core-js-3-babel-and-a-look-into-the-future.md#babelpolyf ill import 'core-js/stable' import 'regenerator-runtime/runtime'Copy the code

Configure the Babel. Config. Js

const plugins = []

module.exports = {
  presets: [['@vue/cli-plugin-babel/preset', {useBuiltIns: 'usage', corejs: 3}]],
  plugins
}
Copy the code

Eslint+Pettier unified development specification

Vue files format using vetur, others use Prettier, how to use the three things together

Prettierrc write your own Pettier rule in the file. Prettierrc

{
   "printWidth": 120,
   "tabWidth": 2,
   "singleQuote": true,
   "trailingComma": "none",
   "semi": false,
   "wrap_line_length": 120,
   "wrap_attributes": "auto",
   "proseWrap": "always",
   "arrowParens": "avoid",
   "bracketSpacing": false,
   "jsxBracketSameLine": true,
   "useTabs": false,
   "overrides": [{
       "files": ".prettierrc",
       "options": {
           "parser": "json"
       }
   }]
}
Copy the code

Vscode setting. Json Settings

{// Put the Settings in this file to override the default setting "files.autoSave": "off", // control the font family. "Editor. FontFamily" : "Consolas," Courier New "monospace, 'song typeface", "terminal. Integrated. Shell. Windows" : "C:\ Program Files\\Git\ bin\ bash.exe", // controls the size in pixels. SuggestFontSize ": 16, // Check whether the selection has rounded corners. "suggestFontSize": false, // suggestFontSize": 16, // The number of editors displayed in the Open Editors pane. Set it to 0 to hide the pane. Explorer. OpenEditors. "visible" : 0, / / if enabled automatically refresh "git. Autorefresh" : true, / / font size in pixels control terminal, it is the editor. FontSize default values. "Terminal. Integrated. FontSize" : 14, / / control terminal cursor is flashing. "Terminal. Integrated. CursorBlinking" : true, / / a TAB is equal to the number of Spaces. This setting is overridden based on the file contents when 'editor.detectindentation' is enabled. // Tab Size "editor.tabSize": 2, // By default, common template. Do not modify it!!!!! "editor.formatOnType": true, "window.zoomLevel": 0, "editor.detectIndentation": false, "css.fileExtensions": ["css", "scss"], "files.associations": { "*.string": "html", "*.vue": "vue", "*.wxss": "css", "*.wxml": "WXML ", "*.wxs": "javascript", "*.cjson": "jsonc", "*.js": "javascript"}, // Define a configuration file for a specified syntax or use a configuration file with a specific rule. "emmet.syntaxProfiles": { "vue-html": "html", "vue": "html" }, "search.exclude": { "**/node_modules": True, "**/bower_components": true}, // EsLint automatically fixes errors with "editor.formatOnSave" when saving: True, // Enable per-language // Configure the file types that ESLint checks. "editor.quickSuggestions": {"strings": True}, / / add the vue support / / here is for vue file format setting, vue rules come into force in here "vetur. Format. The options. TabSize" : 2, "vetur. Format. The options. UseTabs" : false, "vetur.format.defaultFormatter.html": "js-beautify-html", "vetur.format.defaultFormatter.css": "prettier", "vetur.format.defaultFormatter.scss": "prettier", "vetur.format.defaultFormatter.postcss": "prettier", "vetur.format.defaultFormatter.less": "prettier", "vetur.format.defaultFormatter.js": "vscode-typescript", "vetur.format.defaultFormatter.sass": "sass-formatter", "vetur.format.defaultFormatter.ts": "prettier", "vetur.format.defaultFormatterOptions": { "js-beautify-html": { "wrap_attributes": Always-multiple ", // always-multiple ", // always-multiple ", // always-multiple ", // always-multiple ", // always-multiple ", // always-multiple ", // always-multiple ", // always-multiple ", // always-multiple ", // always-multiple ", // Always-multiple ", // Always-multiple ", // 120, "tabWidth": 2, "singleQuote": false, "trailingComma": "none", "semi": false, "wrap_line_length": 120, "wrap_attributes": "always-multiple ", // more than 150 lines "proseWrap": "always", "arrowParens": "avoid", "bracketSpacing": true, "jsxBracketSameLine": true, "useTabs": false, "overrides": [ { "files": ".prettierrc", "options": { "parser": "json" } } ] } }, // Enable per-language "[json]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, "vetur.validation.template": false, "html.format.enable": false, "json.format.enable": false, "javascript.format.enable": false, "typescript.format.enable": false, "javascript.format.insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, "[html]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, "[javascript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, "[jsonc]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, "[vue]": { "editor.defaultFormatter": "octref.vetur" }, "emmet.includeLanguages": { "wxml": "html" }, "[typescriptreact]": {"editor.defaultFormatter": "esbenp.prettier-vscode"}, // Enable esLint to automatically fix js/ts "editor.codeActionsOnSave": { "source.fixAll.eslint": true }, "minapp-vscode.disableAutoConfig": true, "javascript.implicitProjectConfig.experimentalDecorators": true, "editor.maxTokenizationLineLength": 200000 }Copy the code

conclusion

Github address of the project

About me

For more technology-related articles, follow the public account “Maentonjuku” and join “Front-end Fairy Group”.

If it will be helpful to you, send me a little star (the better you guys will be)

Please contact the author for reprint!