The main functions of mobile terminal shelf based on vue-cli3.0 include
- Web pack packaging extension
- Css: sass support, normalize.css, _mixin.scss, _variables.scss
- vw, rem layout
- Cross domain setup
- eslint settings
- Introduction of cdn
- Routing Design, Logon Interception
- axios, api design
- vuex state management
Project address: vue-cli3-H5
demo address: https://zhouyupeng.github.io/vuecli3H5/#/
Web pack packaging extension
After vue-cli3. *, the directory structure has been greatly changed. The previous build and config folders have been removed. To achieve the configuration changes, add vue.config.js to the root directory for configuration.
Css: sass support, normalize.css, _mixin.scss, _variables.scss
The css preprocessor used is sass. For css mixin, variables are introduced globally and introduced globally. normalize.css Make HTML element styles highly consistent across browsers
vue.config.js configuration
css: { // Whether to use ExtractTextPlugin, a css separation plug-in extract: true, // Open CSS source maps? sourceMap: false, // css preset configuration item // Enable CSS modules for all css/pre-processor files. modules: false, sass: { data: '@import "style/_mixin.scss";@import "style/_variables.scss";' // Global introduction } } }
vw, rem layout
For mobile adaptation scenarios, the NetEase News Method,
Using vw + rem layout
/** 750px Design draft With 1rem=100px as a reference, the width of the html element can be set to width: 7.5rem, so the font-size of html is deviceWidth / 7.5 **/ html { font-size: 13.33333vw } @media screen and (max-width: 320px) { html { font-size: 42.667PX; font-size: 13.33333vw } } @media screen and (min-width: 321px) and (max-width:360px) { html { font-size: 48PX; font-size: 13.33333vw } } @media screen and (min-width: 361px) and (max-width:375px) { html { font-size: 50PX; font-size: 13.33333vw } } @media screen and (min-width: 376px) and (max-width:393px) { html { font-size: 52.4PX; font-size: 13.33333vw } } @media screen and (min-width: 394px) and (max-width:412px) { html { font-size: 54.93PX; font-size: 13.33333vw } } @media screen and (min-width: 413px) and (max-width:414px) { html { font-size: 55.2PX; font-size: 13.33333vw } } @media screen and (min-width: 415px) and (max-width:480px) { html { font-size: 64PX; font-size: 13.33333vw } } @media screen and (min-width: 481px) and (max-width:540px) { html { font-size: 72PX; font-size: 13.33333vw } } @media screen and (min-width: 541px) and (max-width:640px) { html { font-size: 85.33PX; font-size: 13.33333vw } } @media screen and (min-width: 641px) and (max-width:720px) { html { font-size: 96PX; font-size: 13.33333vw } } @media screen and (min-width: 721px) and (max-width:768px) { html { font-size: 102.4PX; font-size: 13.33333vw } } @media screen and (min-width: 769px) { html { font-size: 102.4PX; font-size: 13.33333vw } } @media screen and (min-width: 769px) { html { font-size: 102.4PX; #app { margin: 0 auto } } }
vue.config.js configuration
loaderOptions: { postcss: { // This is the configuration of rem adaptation plugins: [ require('postcss-px2rem')({ remUnit: 100 }) ] } }
Development time cross-domain settings
devServer: { open: true, // Whether to open browser after starting service host: '127.0.0.1', port: 8088, // Service port https: false, hotOnly: false, proxy: 'https://easy-mock.com/'// Setting Agent }
After configuration, the baseUrl of axios in the local development environment is written as', that is, an empty string.
Publish online if the front-end code is not placed with the back-end api Homology Next, the background also needs to do cross-domain processing.
eslint standard settings
Used is JavaScript standard Code specifications, a good coding style can help reduce friction between teams, code reading is more refreshing, more readable, don't feel bored, use it well.
This is the full text of the JavaScript standard code specification
Custom configuration, modify in. eslintrc.js. Here is the configuration I gave. Four spaces are indented, the end semicolon is not checked, the single var declaration is closed and self-configurable.
rules: { 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', indent: [ 'error', 4, { SwitchCase: 1 } ], semi: 0, // Do not check the ending semicolon. // Mandatory use of single quotation marks quotes: ['error', 'single'], // Close the space rule between the function name and the following parentheses 'space-before-function-paren': 0, // Close the var declaration, each of which takes up one line of rules. 'one-var': 0 }
Introduction of cdn
For vue, vue-router, vuex, axios and other libraries that are not often changed, we let webpack not pack them. By introducing cdn, we can reduce the size of the code and the bandwidth of the server.
Here we use 360 cdn, with a public CDN review article Point me
vue.config.js configuration
const externals = { vue: 'Vue', 'vue-router': 'VueRouter', vuex: 'Vuex', 'mint-ui': 'MINT', axios: 'axios' } const cdn = { // development environment dev: { css: [ 'https://lib.baomitu.com/mint-ui/2.2.13/style.min.css' ], js: [] }, // production environment build: { css: [ 'https://lib.baomitu.com/mint-ui/2.2.13/style.min.css' ], js: [ 'https://lib.baomitu.com/vue/2.6.6/vue.min.js', 'https://lib.baomitu.com/vue-router/3.0.1/vue-router.min.js', 'https://lib.baomitu.com/vuex/3.0.1/vuex.min.js', 'https://lib.baomitu.com/axios/0.18.0/axios.min.js', 'https://lib.baomitu.com/mint-ui/2.2.13/index.js' ] } } configureWebpack: config => { if (isProduction) { // Modules in externals are not packaged Object.assign(config, { externals: externals }) } else { // Modify the configuration for the development environment. } }, chainWebpack: config => { // Finer-grained modifications are made to the web pack configuration within vue-cli. // Add CDN parameters to the HTML Web pack Plugin configuration, as detailed in the public/index.html modification config.plugin('html').tap(args => { if (process.env.NODE_ENV === 'production') { args[0].cdn = cdn.build } if (process.env.NODE_ENV === 'development') { args[0].cdn = cdn.dev } return args }) }
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <!-- DNS Pre parse --> <link rel="dns-prefetch" href="//lib.baomitu.com" /> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=0,minimal-ui,viewport-fit=cover" /> <link rel="icon" href="<%= BASE_URL %>favicon.ico" /> <!-- Use CDN Accelerated CSS File, configured in vue.config.js lower --> <% for (var i in htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.css) { %> <link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="preload" as="style" /> <link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet" /> <% } %> <title>vuedemo</title> </head> <body> <noscript> <strong>We're sorry but vuedemo doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> </noscript> <div id="app"></div> <!-- Use CDN Accelerated JS File, configured in vue.config.js lower --> <% for (var i in htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.js) { %> <script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script> <% } %> <!-- built files will be auto injected --> </body> </html>
Routing Design, Logon Interception
const router = new Router({ routes: [ { path: '/', name: 'home', component: Home, meta: { auth: false, // Do you need to log in? keepAlive: true // Whether to cache components } }, { path: '/about', name: 'about', component: () => import(/* webpackChunkName: "about" */ './views/About.vue'), meta: { auth: true, keepAlive: true } }, { path: '/login', name: 'login', component: () => import(/* webpackChunkName: "login" */ './views/login.vue'), meta: { auth: false, keepAlive: true } }, { path: '*', // Redirection when not matched to routing redirect: '/', meta: { // auth: true, // keepAlive: true } } ] }) // Global Routing Hook Function is Global Effective router.beforeEach((to, from, next) => { let auth = to.meta.auth let token = store.getters['login/token']; if (auth) { // Need to log in if (token) { next() } else { next({ name: 'login', query: { redirect: to.path } }) } } else { next() } })
Set whether to log in and cache the current component in meta.
In router.beforeEac routing hook function, the login authority is judged. Those who are not logged in jump to the login page, and pass the current page to the login page, then jump back to the page after login.
Page caching is handled in app.vue
<keep-alive> <router-view v-if="$route.meta.keepAlive"></router-view> </keep-alive> <router-view v-if="!$route.meta.keepAlive"></router-view>
axios, api design
The design of axios is mainly request interceptor, response interceptor, and secondary encapsulation of get and post.
axios.defaults.timeout = 12000 // Request timeout axios.defaults.baseURL = process.env.VUE_APP_BASE_API axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8' // Setting of post request header // axios request interceptor axios.interceptors.request.use( config => { // Here you can set the token to be sent let token = store.getters['login/token']; token && (config.headers.token = token) Indicator.open('Data loading') return config }, error => { return Promise.error(error) } ) // Axios response interceptor axios.interceptors.response.use( response => { // If the return status code is 200, the interface request is successful and the data can be obtained normally. // Otherwise, throw an error and write the response interceptor in conjunction with the interface state convention returned by your business and the background Indicator.close() console.log('response', response); if (response.status === 200 && response.data.code === 0) { return Promise.resolve(response) } else { Toast({ message: response.data.msg, position: 'middle', duration: 2000 }); return Promise.reject(response) } }, error => { Indicator.close() const responseCode = error.response.status switch (responseCode) { // 401: Not logged in case 401: break // 404 request does not exist case 404: Toast({ message: 'Network request does not exist', position: 'middle', duration: 2000 }); break default: Toast({ message: error.response.data.message, position: 'middle', duration: 2000 }); } return Promise.reject(error) } ) /** * Encapsulate the get method to correspond to the get request * @param {String} url [The url address of the request] * @param {Object} params [Parameters carried on request] */ function get (url, params = {}) { return new Promise((resolve, reject) => { axios .get(url, { params: params }) .then(res => { resolve(res.data) }) .catch(err => { reject(err.data) }) }) } /** * post Method, corresponding to post request * @param {String} url [The url address of the request] * @param {Object} params [Parameters carried on request] */ function post (url, params) { return new Promise((resolve, reject) => { axios .post(url, qs.stringify(params)) .then(res => { resolve(res.data) }) .catch(err => { reject(err.data) }) }) }
To facilitate the management of api paths, all requests are placed in the api folder, such as
import { get, post } from '@/axios/http.js' function getIndex (params) { return get('/mock/5cb48c7ed491cd741c54456f/base/index', params) } function login(params) { return post('/mock/5cb48c7ed491cd741c54456f/base/login', params) } export { getIndex, login }
Other
Remove console.log
Install uglify js-webpack-plugin plug-in
// On-line compression removes console and other information config.plugins.push( new UglifyJsPlugin({ uglifyOptions: { compress: { warnings: false, drop_console: true, drop_debugger: false, pure_funcs: ['console.log'] // Remove console } }, sourceMap: false, parallel: true }) )
Setting alias directory alias
Files from different places are often referenced in projects, which can be introduced more easily after configuration.
config.resolve.alias .set('assets', '@/assets') .set('components', '@/components') .set('view', '@/view') .set('style', '@/style') .set('api', '@/api') .set('store', '@/store')
Environmental variables and patterns
In the front-end development process of a product, it will generally go through local development, test script, development self-test, test environment, pre-online environment, and then it can be officially released. There may be differences for each environment, such as server address, interface address, websorket address... Wait. When switching between different environments, we need different configuration parameters, so we can use environment variables and patterns to facilitate our management.
.env # Loaded in all environments .env.local # Loaded in all environments, but ignored by git .env.[mode] # Load only in the specified mode .env.[mode].local # Loaded only in the specified mode, but ignored by git
The custom variable VUE_APP_starts with two special variables:
- NODE_ENV - will be one of "development", "production" or "test". The exact value depends on the mode in which the application runs.
- BASE_URL - will match the baseUrl option in vue.config.js, that is, the underlying path to which your application will be deployed.
As we define. env
NODE_ENV = 'development' BASE_URL = '/' VUE_APP_BASE_API = ''
.env.production
NODE_ENV = 'production' BASE_URL = './' VUE_APP_BASE_API = 'https://easy-mock.com/'
Defined values can be obtained in a project using process.env.VUE_APP_*, such as process.env.VUE_APP_BASE_API.
Global introduction of filter
Write the filters used in many places in one js and reuse the code.
// Filter date format, pass in timestamp, and return different formats according to parameters const formatTimer = function(val, hours) { if (val) { var dateTimer = new Date(val * 1000) var y = dateTimer.getFullYear() var M = dateTimer.getMonth() + 1 var d = dateTimer.getDate() var h = dateTimer.getHours() var m = dateTimer.getMinutes() M = M >= 10 ? M : '0' + M d = d >= 10 ? d : '0' + d h = h >= 10 ? h : '0' + h m = m >= 10 ? m : '0' + m if (hours) { return y + '-' + M + '-' + d + ' ' + h + ':' + m } else { return y + '-' + M + '-' + d } } } export default { formatTimer }
Introduction of main.js
import filters from './filters/index' // Injection global filter Object.keys(filters).forEach(item => { Vue.filter(item, filters[item]) })
Use
{{1555851774 | formatTimer()}}
Using mock.js in vue
Check out my previous articles Click on me
wepback Visual Resource Analysis Tool Plug-in - -- webpack-bundle-analyzer
It is used to analyze which modules introduce which code and optimize the code purposefully.
In a packaging environment, use the command npm run build --report
if (process.env.npm_config_report) { config.plugins.push(new BundleAnalyzerPlugin()) }
Code address
Project address: vue-cli3-H5
demo address: https://zhouyupeng.github.io/vuecli3H5/#/