update
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
- through
npm run serve
Start the local PC and rundevelopment
- through
npm run stage
Package the tests and execute themstaging
- through
npm run build
Package 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
By default, styles in Vant use px units. If you want to use REM units, the following two tools are recommended:
- postcss-pxtoremIs a
postcss
Plug-in for converting units torem
- lib-flexibleUsed to set the
rem
At 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.
- when
rootValue: 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. - when
RootValue: 37.5
When 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
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.use
Request headers can be set, such as Settingstoken
config.hideloading
It is set in the interface parameters in the API folder, as described belowservice.interceptors.response.use
In 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 as
home.js
Here is the interface of the home pageuser.js
url
Interface address, which will be concatenated when requestedconfig
Under thebaseApi
method
Request methoddata
Request parametersqs.stringify(params)
Is the data serialization operationhideloading
The defaultfalse
, is set totrue
Some 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!