我的项目的版本是基于@vue/cli 5.0.4webpack@5.73.0

vue-cli5版本曾经内置了webpack5,且很多配置都内置化了,换言之,根底打包无需在vue.config.js中配置了,大大简化了配置过程。因为次要是针对我的项目的优化,所以创立的过程会简略,上面是优化的具体详情。

我的项目初始化

  • 装置 vue-cli

    npm install -g @vue/cli
  • 创立我的项目
    应用vue create xx创立我的项目,依据本人的我的项目自行抉择即可;初始化我的项目结束后,可看到我的项目的目录构造中曾经存在vue.config.js文件了。

    publicPath

    配置打包后的门路,须要留神的一点是当路由是history模式时,门路须要设置为绝对路径,即/而不是./。同时 nginx 须要配置try_files $uri $uri/ /index.html;

    module.exports = defineConfig({publicPath: process.env.NODE_ENV === 'production' ? '/' : '/',})

    outputDir

    配置打包文件的寄存目录。

    module.exports = defineConfig({outputDir: 'dist',})

    productionSourceMap

    是否在生产环境中应用 sourcemap,用于定位到谬误源码。(不倡议应用,会影响打包速度,且会让人看到本人的代码)

    module.exports = defineConfig({outputDir: 'dist',})

    devServer

    配置 api 以及跨域端口等设置。

    module.exports = defineConfig({devServer: {  port: 8887,  hot: true,  compress: true, // 是否启动压缩 gzip  proxy: {    '/api': {      target: 'http://www.galaxychips.com',      changeOrigin: true,      pathRewrite: {        '^/api': ''      }    }  }},})

    css 优化

    创立我的项目时曾经抉择了 sass,打包时会主动转化为根底 css,且文件会独立分离出来。所以这里我只引入了一个全局变量文件。

    module.exports = defineConfig({css: {  loaderOptions: {    scss: {      additionalData: '@import "@/assets/scss/variables.scss";'    }  }},})

    js 优化

    生产环境下内置的插件曾经会解决压缩并用 babel 转化代码的操作。

    cdn 减速

    将专用库改为cdn引入形式,放慢访问速度,注入html的插件无需装置,曾经内置。externalscdn常量依据本人的我的项目而定。(文末会贴出代码)

    module.exports = defineConfig({chainWebpack: config => {  if (process.env.NODE_ENV === 'production') {    config.externals(externals)    // 通过 html-webpack-plugin 将 cdn 注入到 index.html 之中    config.plugin('html')      .tap(args => {        args[0].cdn = cdn        return args      })  }}})

    public/index.html 中须要写入注入代码。

    <head>  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vuetify@2.6.0/dist/vuetify.min.css">  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css">  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap">  <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/hover.css/2.3.1/css/hover-min.css"><% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.css) { %>  <link rel="stylesheet" href="<%= htmlWebpackPlugin.options.cdn.css[i] %>"><% } %></head><body>  <!-- built files will be auto injected -->  <% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.js) { %>    <script type="text/javascript" src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>  <% } %></body>
    留神:我应用的 ui 框架是vuetify,应用 cdn 引入的话就不须要通过 import 引入款式,否则打包时会出错。

    代码宰割

    lru-cache是我的项目中的额定插件,提取为一个独自的 chunk。

    config  .optimization.splitChunks({    cacheGroups: {      styles: {        name: 'styles',        test: /\.(s?css|less|sass)$/,        chunks: 'all',        priority: 10      },      common: {        name: 'chunk-common',        chunks: 'all',        minChunks: 2, // 拆分前必须共享模块的最小 chunks 数。        maxInitialRequests: 5, // 打包后的入口文件加载时,还能同时加载js文件的数量(包含入口文件)        minSize: 0, // 生成 chunk 的最小体积(≈ 20kb)        priority: 1, // 优化将优先思考具备更高 priority(优先级)的缓存组        reuseExistingChunk: true // 如果以后 chunk 蕴含已从主 bundle 中拆分出的模块,则它将被重用,而不是生成新的模块      },      vendors: {        name: 'chunk-vendors',        test: /[\\/]node_modules[\\/]/,        chunks: 'all',        priority: 2,        reuseExistingChunk: true      },      lrucache: {        name: 'chunk-lrucache',        test: /[\\/]node_modules[\\/]_?lru-cache(.*)/,        chunks: 'all',        priority: 3,        reuseExistingChunk: true      }    }  })

    gzip压缩

    运行npm install compression-webpack-plugin -D装置压缩插件。

    config.plugin('CompressionPlugin').use('compression-webpack-plugin', [{  filename: '[path][base].gz',  algorithm: 'gzip',  test: /\.js$|\.css$|\.html$/,  threshold: 10240, // 只解决比这个值大的资源。按字节计算  minRatio: 0.8 // 只有压缩率比这个值小的资源才会被解决}])

    整个配置详情如下

    const { defineConfig } = require('@vue/cli-service')const path = require('path')// 门路解决办法function resolve (dir) {return path.join(__dirname, dir)}const externals = [{  vue: 'Vue'},{  'vue-router': 'VueRouter'},{  axios: 'axios'},{  vuetify: 'Vuetify'},{  md5: 'MD5'},{  qs: 'Qs'}]const cdn = {css: [],js: [  'https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js',  'https://cdn.jsdelivr.net/npm/vue-router@3.5.1/dist/vue-router.min.js',  'https://cdn.jsdelivr.net/npm/axios@0.27.2/dist/axios.min.js',  'https://cdn.jsdelivr.net/npm/vuetify@2.6.0/dist/vuetify.min.js',  'https://cdn.jsdelivr.net/npm/md5@2.3.0/dist/md5.min.js',  'https://cdn.jsdelivr.net/npm/qs@6.11.0/dist/qs.min.js']}module.exports = defineConfig({publicPath: process.env.NODE_ENV === 'production' ? '/' : '/',outputDir: 'dist',productionSourceMap: false,lintOnSave: process.env.NODE_ENV !== 'production',devServer: {  port: 8887,  hot: true,  compress: true, // 是否启动压缩 gzip  proxy: {    '/api': {      target: 'http://www.xxxx.com',      changeOrigin: true,      pathRewrite: {        '^/api': ''      }    }  }},css: {  loaderOptions: {    scss: {      additionalData: '@import "@/assets/scss/variables.scss";'    }  }},configureWebpack: {  resolve: {    extensions: ['.vue', '.js', '.json', 'scss', 'css'],    alias: {      '@': resolve('src')    },    modules: [resolve('src'), 'node_modules']  },  module: {  },  plugins: [  ]},chainWebpack: config => {  if (process.env.NODE_ENV === 'production') {    config.externals(externals)    // 通过 html-webpack-plugin 将 cdn 注入到 index.html 之中    config.plugin('html')      .tap(args => {        args[0].cdn = cdn        return args      })    config.plugin('CompressionPlugin').use('compression-webpack-plugin', [{      filename: '[path][base].gz',      algorithm: 'gzip',      test: /\.js$|\.css$|\.html$/,      threshold: 10240, // 只解决比这个值大的资源。按字节计算      minRatio: 0.8 // 只有压缩率比这个值小的资源才会被解决    }])    config      .optimization.splitChunks({        cacheGroups: {          styles: {            name: 'styles',            test: /\.(s?css|less|sass)$/,            chunks: 'all',            priority: 10          },          common: {            name: 'chunk-common',            chunks: 'all',            minChunks: 2, // 拆分前必须共享模块的最小 chunks 数。            maxInitialRequests: 5, // 打包后的入口文件加载时,还能同时加载js文件的数量(包含入口文件)            minSize: 0, // 生成 chunk 的最小体积(≈ 20kb)            priority: 1, // 优化将优先思考具备更高 priority(优先级)的缓存组            reuseExistingChunk: true // 如果以后 chunk 蕴含已从主 bundle 中拆分出的模块,则它将被重用,而不是生成新的模块          },          vendors: {            name: 'chunk-vendors',            test: /[\\/]node_modules[\\/]/,            chunks: 'all',            priority: 2,            reuseExistingChunk: true          },          lrucache: {            name: 'chunk-lrucache',            test: /[\\/]node_modules[\\/]_?lru-cache(.*)/,            chunks: 'all',            priority: 3,            reuseExistingChunk: true          }        }      })  }}})