I. VuE-CLI3 single page construction scheme

1. Execute in the target folder

vue ui ; A UI version interface for creating vUE projects;Copy the code

2. Open index in the router folder and set the router mode to hash or history.

Ps: Personal promotion history mode, because if embedded in the H5 page of the APP, some apps may not allow ‘#’ on the page, and hash will use # in the URL for routing and forwarding.
Ps: History mode needs to be configured by Nginx before publishing to the server. Please search for details.
const router = new VueRouter({
  base: '/',
  mode: 'history', // Can also be set to'hash'Model routes})Copy the code

3. Create vue.config.js in the root directory, overwrite the webpack configuration, and copy the following content to the file as the initial configuration


// const webpack = require('webpack')

module.exports = {
    lintOnSave: false, // disable esLint devServer: {open:true}, configureWebpack: {plugins: [// global configureWebpack: {plugins: [// global configureWebpack: {plugins: [// global configureWebpack: {plugins: [// global configureWebpack: {// new webpack.providePlugin ({$:"jquery",
                jQuery: "jquery"."windows.jQuery": "jquery"})]}, // WebPack link API for generating and modifying webapck configuration chainWebpack: (config) = > {/ / cancel chunks, each page only corresponds to a single JS/CSS config. Optimization. SplitChunks ({cacheGroups: {}}); // config // .plugin('webpack-bundle-analyzer')
        //     .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin)
    },

    pluginOptions: {

    }

}
Copy the code

4. After these are configured, NPM Run Serve starts the project and loads the following two JS

npm run serve
Copy the code

App.js: is the js that must be loaded for the first rendering of all single pages. It internally incorporates frames and JS (such as Vue, VUE-x, vue-Router and modules in non-asynchronous components that reference node_modules), and modules common to all pages.

About.js: is a page-by-page JS that depends on how modules are referenced in the Router.

Detailed explanation is as follows:

1.
import Home from '.. /views/Home.vue'
Copy the code
This way of referencing the page template component, the about.js file will not appear, because it is a synchronous module, and the js created by the current component will be packaged into app.js. But as the number of pages increases, the common app.js will get bigger and bigger. App.js size is acceptable under the premise of trade-offs;
2,
const routes = [
  {
    path: '/',
    name: 'Home',
    // component: Home
    component: () => import(/* webpackChunkName: "home"* /'.. /views/Home.vue'// webpack's magic annotation, name the split js as home}, {path:'/about',
    name: 'About',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about"* /'.. /views/About.vue')}]Copy the code
This reference method is asynchronous reference template component, will not be the current component js package into app.js, there will be no problem of 1. As long as the corresponding page is not loaded, the corresponding page js will not be loaded. Js of the corresponding page will be dynamically introduced by the most independent JS, just like the about.js in the figure above, which will be introduced when entering the About page.
3,

If the node_modules package is introduced in main.js, it will be packaged directly into app.js, and it will not escape.

Ps: As a final conclusion, it is recommended that each page reference the page template asynchronously.

5. Each page that introduces node_mudules will have corresponding vendor-home.js, and if node_mudules is not introduced, there will be no vendor-home.js file for the vendor-home.js component on demand on each page, as shown below:

Distinguish between local, test, and online environments

Ps: The official website provides a solution, but need to create multiple environment configuration configuration file, too troublesome, do not use the official way, use the following plug-in split environment:
Cross – env:Github.com/kentcdodds/…
CNPM I cress-env --save-dev // Change node environment variables pluginCopy the code

Then add the following three lines of configuration to package.json to distinguish between local, test, and online environments

"scripts": {
    "serve": "cross-env NODE_ENV=development vue-cli-service serve"."test": "cross-env NODE_ENV=test vue-cli-service build"."build": "cross-env NODE_ENV=production vue-cli-service build"
  },
Copy the code
To print the current environment, execute the following code in vue.config.js.
console.log(process.env.NODE_ENV)
Copy the code
Create a new config directory under the SRC directory, go to the directory, create a gateway.config.js file to configure different environment interface host, code is as follows:
The contents of the gateway.config.js file are as follows:
// Dev environment address (NPM run serve) const devHost = {'https://abc.com'} // Test environment address (NPM runtest)
const testHost = {// Interface address domain name related baseApi:'https://abc.com'} // build (NPM run build) const proHost = {// baseApi:'https://abc1.com'} const env = process.env.node_envlet exportConfig = ' '
if (env === 'production') {
  exportConfig = proHost
} else if (env === 'test') {
  exportConfig = testHost
} else {
  exportConfig = devHost
}

export default exportConfig
Copy the code
End: Then you just need to import this file in the JS file of the interface API. Separate environment packaging at release time.

7. Introduction of third-party plug-ins into the project

Ps: Principle: the size of a single JS on the mobile terminal should not exceed 200K; A single JS file on PC should not exceed 400K.
1. Vue modularity introduced node_modules package plug-in:
The premise is that each page is loaded asynchronously, which has the advantage that the js of a single page is not packaged into the common app.js. Then introduce third-party libraries into a single JS. However, according to the test, this kind of modularization introduces third-party plug-ins, which is at least 2 larger than the JS volume introduced by CDN mode, because webpack conducts secondary processing for each third-party library, which will increase the JS volume. Weigh the JS size used.
2. Third-party plug-ins introduced in CDN mode:
This method is provided because some libraries do not support VUE and only support CDN mode introduction, which is relatively lightweight. You can choose this method, asynchronous CDN mode introduction of third-party plug-ins, and these methods have demo in the bottom scaffolding example.

8. Package plug-ins and third-party libraries commonly used in the project

1.vue cn.vuejs.org
2.vue-router router.vuejs.org
3.vue-x vuex.vuejs.org
4.sass www.sass.hk
5.axios www.axios-js.com/
6.normalize.css Necolas. Making. IO/normalize. C…
7.n-zepto Npm.taobao.org/package/n-z…
8.webpack-bundle-analyzer Github.com/webpack-con…

Below is the vuE-cli3 built-in plug-in (directly configured in vue.config.js):
The following plug-ins can be configured using vuE-CLI3 official website:

Cli.vuejs.org/zh/config/#…

8. Autoprefixer: Automatically adds browser prefixes. (e.g. -webkit- etc.)
7. Url-loader: changes the reference path of static resources
7.ProvidePlugin: globally configure the module in node_modules
The specific configuration method is as follows (complete vue.config.js configuration) :

const webpack = require('webpack') const processEnv = process.env.VUE_APP_ENV; // Distinguish the environment (values: production, development,test)
const isPro = processEnv === 'production'; Production environment const outputDir ='dist'; // Output file directory (default dist) const assetsDir =' '; // Configure the directory to place generated static resources (js, CSS, img, fonts) (as opposed to outputDir)let publicPath = ' 'Static resource reference pathlet fontPublicPath = ' '// CDN path referenced by the font iconlet imgPublicPath = ' '// c2c/static/imgif (processEnv === 'production') {
    publicPath = 'https://abc.com/c2c/shop'/ / formal environment static resource CSS, js CDN path fontPublicPath = ` https://abc.com/c2c/shop/${assetsDir ? assetsDir + '/' : '/'}Fonts ` / / formal environment fonts icon reference path of CDN imgPublicPath = ` https://abc.com/c2c/shop/${assetsDir ? assetsDir + '/' : '/'}/img '// official environment CSS reference image CDN path}else if (processEnv === 'test') {
    // publicPath = '/'// CDN path of static resources such as CSS and JS publicPath ='https://bcd.com/c2c/shop/dist'// Test environment static resources such as CSS and JS CDN path fontPublicPath =' '
    imgPublicPath = ' '
} else {
    publicPath = '/'
    fontPublicPath = ' '
    imgPublicPath = ' '
}

const devServerHost = 'localhost';
const devServerPort = '8080'; // Port number const devServerOpen =true; Module. exports = {static CDN resource path (dist) {// static CDN resource path (dist) {// static CDN resource path (dist) {// module.exports = { // Configure the generated static resources (js, CSS, img, fonts) in the assetsDir directory (relative to outputDir). { host: devServerHost, port: devServerPort, open: // overlay: {// warnings: // overlay: {// warnings: // overlay: {// warnings:true,
        //     errors: true
        // }
    },
    lintOnSave: processEnv === 'development' ? true : false// The development environment enables ESLint, tests and online editing code to disable ESLint // WebPack configurations, merges configurations for key objects and overwrites configurations for methods: Config => {// Expand resources without adding js resources to the package to reference CDN resourceslet externals = {
            // 'swiper': 'Swiper'}; config.externals = externals; // Warning webpack about performance hints config.performance = {hints: isPro?'warning' : false// maxEntrypointSize: 512000, // 500kib // maxAssetSize: AssetFilter (assetFilename) {return assetFilename.endsWith('.js'); }}; }, // WebPack link API for generating and modifying webapck configuration chainWebpack: (config) = > {/ / cancel chunks, each page only corresponds to a single JS/CSS config. Optimization. SplitChunks ({cacheGroups: {}}); // configure the module in node_modules globally without importing config.plugin('provide').use(webpack.ProvidePlugin, [{
            $: "n-zepto",
            Zepto: "n-zepto"."window.Zepto": "n-zepto"
        }]);

        config.module
            .rule('images')
            .use('url-loader')
            .loader('url-loader')
            .tap(options => Object.assign(options, {
                limit: 10240, // Less than 10K, compressed image => base64 //limit: 3000,
                publicPath: imgPublicPath,
                name: `[name].[hash[ext] '})) // Set the path referenced by the fonts file config.module.rule ('fonts') .test(/\.(woff2? |eot|ttf|otf)(\? . *)? $/i) .use('url-loader')
            .loader('file-loader')
            .tap(options => Object.assign(options, {
                limit: 5000,
                publicPath: fontPublicPath,
                name: '[name].[hash:8].[ext]'}) // NPM run report; Print module report of app.js and view each module;if (processEnv === 'report') {
            config
                .plugin('webpack-bundle-analyzer')
                .use(require('webpack-bundle-analyzer').bundleAnalyzerPlugin)}}, // CSS configuration processing CSS: {// Whether to use CSS ExtractTextPlugin;true: Separate page CSS,false: the same page CSS packaging; extract:true// Enable the CSSsourceMaps (the defaultfalseOnline off, test and local onsourceMap: isPro ? false : true, // CSS default loaderOptions: {sass: {// sass public methods and variables, need to be precompiled; prependData: ` @import"@/assets/css/global.scss";
                    @import "@/assets/css/func.scss"; }, postcss: {plugins: // browsers automatically prefix require('autoprefixer')({
                        overrideBrowserslist: [
                            "Android 4.0"."iOS 7"."Chrome > 31"."ff > 31"."ie >= 8"
                        ]
                    }),
                ]
            }

        },
        /** 启用 CSS modules forall css / pre-processor files. Import third-party UI libraries and must be set to if CSS is referenced in JStrueBecause if set tofalseIt's going to start the CSS modules that are introduced through JS, and it's going to hash the CSS class name of the third-party UI, and it's going to be a problem. Reference documentation (vue - cli website) : https://cli.vuejs.org/zh/config/# CSS - requiremoduleextension and
         https://cli.vuejs.org/zh/guide/css.html#css-modules
         **/
        requireModuleExtension: true}, // parallel: require('os').cpus().length > 1,

    pwa: {
        iconPaths: {
            favicon32: 'favicon.ico',
            favicon16: 'favicon.ico',
            appleTouchIcon: 'favicon.ico',
            maskIcon: 'favicon.ico',
            msTileImage: 'favicon.ico'},}, // pluginOptions: {//... }}Copy the code

9. Scaffolding of a single page project scheme based on VUE-CLI3 with relatively complete basic configuration:

The project scaffolding collection project-init
Within the CLI-start-spa folder, the internal readme has project details.