Facing a situation

Without caching, the first browser load takes 8 to 9 seconds

The typed package is relatively large, 18.7m down the whole folder

1, first remove the map file, set not map file or this will be typed out, very strange

productionSourceMap: false// Do you want the map fileCopy the code

It turns out that this configuration affects it

module.exports = {
    configureWebpack: () => ({
        devtool: 'source-map',}})Copy the code
  • The official explanation for this property is on the Webpack website

1. Use the SourceMapDevToolPlugin for more granular configuration. View source-map-loader to process the existing source map.

2. Select a Source Map format to enhance the debugging process. Different values significantly affect the speed of build and rebuild.

Note devtool: ‘source-map’ after the type of package instead become larger, full folder down 22.2m

Change to eval, and then the whole file comes down 11M

module.exports = {
    configureWebpack: () => ({
        devtool: 'eval',}})Copy the code

Package is too big, it is estimated that the introduction of a package is too big, guess or pinyin, or voice input, looking for a circle, finally found that echart is too big

2. Introduction of EChart’s CDN, referring to the blogVue-cli4 Project Configures the CDN to import static resources

My page reported an error after modification according to the configuration

Can not deal with, or see the official Internet cafeVue – cli’s official website

configureWebpack

  • If the value is an object, it is merged into the final configuration using webpack-Merge.

  • If the value is a function, the parsed configuration is accepted as an argument. This function can either modify the configuration and return nothing, or it can return a cloned or merged version of the configuration.

1. I’m using object configuration here. The official documentation means that if you want to determine whether it is production or development, you should use function mode, and use object mode without distinction

Externals prevents package import dependencies from being added to the bundle, and instead gets these dependencies from the runtime. For example, import jQuery from the CDN instead of packaging it

// configureWebpack configureWebpack: {devtool:'eval', resolve: {// Configure the project aliasalias: {
        'assets': path.resolve('./src/assets'),
        'api': path.resolve('./src/api'),
        'components': path.resolve('./src/components'),
        'utils': path.resolve('./src/utils'),
        'views': path.resolve('./src/views'),
        'styles': path.resolve('./src/styles'),
        The '@': resolve('src')
      }
    },
    externals: {
      vue: 'Vue',
      axios: 'axios'.'vant': 'VANT'.'echarts': 'echarts'.'vue-router': 'VueRouter',
      vuex: 'Vuex'.'element-ui': 'ELEMENT'}},Copy the code

4. Vue – PAGES of the CLI

Build the application in multi-Page mode. Each “page” should have a corresponding JavaScript entry file. The value should be an object whose key is the name of the entry and whose value is:

An object specifying entry, template, filename, title, and chunks (all optional except entry); Or a string specifying its entry.

pages: {
    index: {
      entry: 'src/main.js',
      template: 'public/index.html',
      filename: 'index.html',
      chunks: ['chunk-vendors'.'chunk-common'.'index'],
      cdn: {
        css: [
          'https://cdn.jsdelivr.net/npm/[email protected]/lib/theme-chalk/index.css'
        ],
        js: [
          "https://cdn.staticfile.org/vue/2.5.22/vue.min.js"."https://cdn.staticfile.org/vue-router/3.0.2/vue-router.min.js"."https://cdn.staticfile.org/axios/0.19.0-beta.1/axios.min.js".'https://cdn.jsdelivr.net/npm/[email protected]/lib/vant.min.js'."https://cdn.staticfile.org/vuex/3.1.1/vuex.min.js"."https://cdn.jsdelivr.net/npm/[email protected]/lib/index.js"."https://cdn.bootcss.com/echarts/4.8.0/echarts.simple.min.js",]},}},Copy the code

After configuring pages to configure index.html, with asp statement dynamic dynamic production secript tag and link tag

<! DOCTYPE html> <html lang="en">

<head>
  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <!-- 适配iPhone X viewport-fit=cover -->
  <meta name="viewport"
    content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, viewport-fit=cover" />
  <meta name="format-detection" content="telephone=yes" />
  <link rel="icon" href="<%= BASE_URL %>app_logo.svg"/ > < %for(var js of htmlWebpackPlugin.options.cdn.js) { %>
  <link href="<%=js%>" rel="preload" as="script" />
  <script src="<%=js%>"></script>
  <% } %>
  <meta http-equiv="pragma" content="no-cache" />
  <meta http-equiv="cache-control" content="no-cache" />
  <meta http-equiv="expires" content="0" />
  <title></title>
</head>

<body>
  <noscript>
    <strong>We're sorry but vue-cli3-project doesn't work properly without
      JavaScript enabled. Please enable it to continue.</strong>
  </noscript>
  <div id="app"></div>
</body>

</html>
Copy the code

After CDN is configured, the packaged files significantly reduce bootCND

If you run into problems, import AXIos from CDN, attach axios to prototype in main.js, configure axios in other files with this.$axios will not work

// import axios from "axios"
Vue.prototype.$axios = axios
Copy the code

In staff-login. js, the request will not be token, and axios will not import the CDN

this.$axios.defaults.headers.common['token'] = this.queryData.token
Copy the code

6, the package is still large, check the analysis

  • Start by installing the analysis plug-in Webpack-bundle-Analyzer

1, specific use of this can be copied

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer'Module.exports = {configureWebpack:{// configure plugins:[new BundleAnalyzerPlugin({). analyzerPort: 8919 }) ] } }Copy the code

After the package is packaged, a site with port 8919 will automatically appear. The site content is as follows:

ChainWebpack is a function that takes an instance of a ChainableConfig based on webpack-chain. Allows for more fine-grained changes to the internal WebPack configuration.

7, configuration optimization, unpacking

Module. exports = {configureWebpack:{// optimization // optimization: {// Tell WebPack to compress bundles using TerserPlugin or other plugins defined in Optimization.minimizer. minimize:true, // For dynamically imported modules, the new generic chunking policy splitChunks provided by WebPack V4 + is used by default: {chunks:'async'// minRemainingSize: 0, minChunks: 1, maxAsyncRequests: 6, maxInitialRequests: 4, automaticNameDelimiter:'~',
        cacheGroups: {
          defaultVendors: {
            test: /[\\/]node_modules[\\/]/,
            priority: -10
          },
          default: {
            minChunks: 2,
            priority: -20,
            reuseExistingChunk: true
          }
        }
      }
    }
    }
}
Copy the code

Add that and it’s a little bit smaller, so it’s 10.3

8. That leaves large SVG and vconsole, which should not be used in production

  • The Vsonsole forgot to comment it out, so it won’t be packaged in, or you can configure the Vconsole to only be displayed in production
// import Vconsole from "vconsole"
// const vConsole = new Vconsole()
// Vue.use(vConsole)
Copy the code

  • SVG is easy to solve, just delete the unwanted ones

As a result, from 18.7m at the beginning to 3.36m at the end, the package size has been optimized quite a lot, and the loading time has also increased from 8s to about 1s now

Finally, paste vue.config.js,

const CompressionPlugin = require('compression-webpack-plugin')
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer'Const autoprefixer = require().BundleAnalyzerPlugin // automatically add browser prefixes to improve compatibility'autoprefixer')
const path = require('path')
const resolve = dir => path.join(__dirname, dir)
const IS_PROD = process.env.NODE_ENV === 'production'
const cdnDomain = '/'
module.exports = {
  publicPath: IS_PROD ? cdnDomain : '/',
  productionSourceMap: false// Map file lintOnSave:false, // Sets whether esLint validation is enabled every time code is saved in the development environment. devServer: { hot:true// Set the port to 9527, HTTPS:false,
    hotOnly: false,
    overlay: {
      warnings: true,
      errors: true}, // Configure multiple proxies proxy: {[process.env.vue_app_base_API]: {target: process.env.base_url, changeOrigin:true,
        pathRewrite: {
          [A '^' + process.env.VUE_APP_BASE_API]: ' '
        }
      }
    }
  },
  chainWebpack: config => {
    const svgRule = config.module.rule('svg'// Find svG-loader svgRule.uses.clear() // Clear the existing loader, If not, add svgRule. Exclude. add(/node_modules/) // regular match after this loader to exclude node_modules directory svgRule // add SVG new loader processing .test(/\.svg$/) .use('svg-sprite-loader')
      .loader('svg-sprite-loader')
      .options({
        symbolId: 'icon-[name]'}) const imagesRule = config.module.rule()'images')
    imagesRule.exclude.add(path.resolve('src/assets/icons'Config.module. rule(config.module.'images') .test(/\.(png|jpe? g|gif|svg)(\? . *)? $/) .use('img-loader')
      .loader('img-loader').options({
        plugins: [
          require('imagemin-jpegtran')(),
          require('imagemin-pngquant'({quality: [0.75, 0.85]})]}) // Enable GZip compression config.plugin ('compression')
      .use(CompressionPlugin, {
        asset: '[path].gz[query]',
        algorithm: 'gzip'.test: new RegExp('\ \. (' + ['js'.'css'].join('|') + '$'),
        threshold: 10240,
        minRatio: 0.8,
        cache: true}).tap(args => {})}, CSS: {loaderOptions: {postcss: {plugins: [autoprefixer(),'postcss-px-to-viewport')({
            unitToConvert: 'px', viewportWidth: 375, // The width of the window corresponds to the width of our design draft, usually 750 viewportHeight: UnitPrecision: 3; // Specify the decimal number of Windows converted to the px unit value. ViewportUnit:'vw'Vw selectorBlackList: [] is recommended. // Specify a class that is not to be converted to a window unit. It can be customized and can be added without limit. 1, // less than or equal to '1px' does not convert to window units, you can also set to the value you want mediaQuery:false// Allow conversion 'px'})]}, less: {modifyVars: {black:'# 313131',
          red: '#F44',
          blue: '# 666666',
          orange: '#F89516',
          green: '#268AED'.'text-color': '# 313131'.'background-color': '#F5F5F5'// Button reset'button-default-height': '38px'.'button-default-line-height': '36px'.'button-default-font-size': '14px'.'button-default-color': '#34394A'.'button-default-border-color': '#DDD'.'button-large-height': '47px'.'button-large-line-height': '45px'.'button-border-radius': '4px'.'button-small-font-size': '14px'.'button-small-min-width': '64px'// nav resets'nav-bar-arrow-size': '18px'.'nav-bar-title-font-size': '17px'}}}}, // configureWebpack configureWebpack: {// devtool:'eval',
    devtool: 'source-map', resolve: {// Configure the project aliasalias: {
        'assets': path.resolve('./src/assets'),
        'api': path.resolve('./src/api'),
        'components': path.resolve('./src/components'),
        'utils': path.resolve('./src/utils'),
        'views': path.resolve('./src/views'),
        'styles': path.resolve('./src/styles'),
        The '@': resolve('src')
      }
    },
    externals: {
      vue: 'Vue',
      // axios: 'axios'// Can not use CDN, otherwise the configuration can not be used'vant': 'VANT'.'echarts': 'echarts'.'vue-router': 'VueRouter',
      vuex: 'Vuex',
      // swiper: 'swiper'// CDN loading is too slow //"vue-ls": "vue-ls"// CDN loading is too slow'lottie-web': 'lottie-web'.'element-ui': 'ELEMENT'}, plugins: [// New BundleAnalyzerPlugin({analyzerPort: 8919})], // Optimization: {// Tell WebPack to compress bundles using TerserPlugin or other plugins defined in Optimization.minimizer. minimize:true, // For dynamically imported modules, the new generic chunking policy splitChunks provided by WebPack V4 + is used by default: {chunks:'async'// minRemainingSize: 0, minChunks: 1, maxAsyncRequests: 6, maxInitialRequests: 4, automaticNameDelimiter:'~',
        cacheGroups: {
          defaultVendors: {
            test: /[\\/]node_modules[\\/]/,
            priority: -10
          },
          default: {
            minChunks: 2,
            priority: -20,
            reuseExistingChunk: true
          }
        }
      }
    }
  },
  pages: {
    index: {
      entry: 'src/main.js',
      template: 'public/index.html',
      filename: 'index.html',
      chunks: ['chunk-vendors'.'chunk-common'.'index'], // Configure dynamically generated tags in index.html CDN: {CSS: ['https://cdn.jsdelivr.net/npm/[email protected]/lib/index.css'
        ],
        js: [
          "https://cdn.staticfile.org/vue/2.5.22/vue.min.js"."https://cdn.staticfile.org/vue-router/3.0.2/vue-router.min.js", / /"https://cdn.staticfile.org/axios/0.19.0-beta.1/axios.min.js"// Can not use CDN, otherwise the configuration can not be used'https://cdn.jsdelivr.net/npm/[email protected]/lib/vant.min.js'."https://cdn.staticfile.org/vuex/3.1.1/vuex.min.js"."https://cdn.jsdelivr.net/npm/[email protected]/lib/index.js"."https://cdn.bootcss.com/echarts/4.8.0/echarts.simple.min.js"."https://cdn.staticfile.org/lottie-web/5.7.1/lottie.min.js", / /"https://cdnjs.cloudflare.com/ajax/libs/Swiper/4.0.2/js/swiper.min.js"// CDN loading is too slow //"https://cdn.bootcdn.net/ajax/libs/vue-ls/3.2.1/vue-ls.js",// CDN loading too slow]},}}}Copy the code

This paper is mainly to record their own optimization process, configuration is not perfect, many places to write too messy, organized is not good, have time to slowly change…