webpack4+vuecli3 项目打包优化

  • List item

vue.config.js基本配置

// 基本路径
 baseUrl: '/',
 // 输出文件目录
 outputDir: 'dist',
 // eslint-loader 是否在保存的时候检查
 lintOnSave: true,
 compiler: false,
 // webpack配置
 chainWebpack: () => {
    
    },
 configureWebpack: () => {
    
    },
 // vue-loader 配置项
 vueLoader: {
    
    },
 // 生产环境是否生成 sourceMap 文件
 //是否在构建生产包时生成 sourceMap 文件,false将提高构建速度(map文件能看到具体报错位置)
 productionSourceMap: true,
 // css相关配置
 css: {
    
    
  // 是否使用css分离插件 ExtractTextPlugin
  extract: true,
  // 开启 CSS source maps?
  sourceMap: false,
  // css预设器配置项
  loaderOptions: {
    
    },
  // 启用 CSS modules for all css / pre-processor files.
  modules: false
 },
 parallel: require('os').cpus().length > 1,
 // 是否启用dll
 dll: false,
 // PWA 插件相关配置
 pwa: {
    
    },
 // webpack-dev-server 相关配置
 devServer: {
    
    
  //...
 },
 // 第三方插件配置
 pluginOptions: {
    
    
  // ...
 }

打包性能优化

1.利用webpack-bundle-analyzer查看资源树

chainWebpack: (config) => {
    
    
      if (process.env.NODE_ENV === 'production') {
    
    
        //添加分析工具
        config
          .plugin('webpack-bundle-analyzer')
          .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin)
          .end()
      }
    }

2.去除map文件

productionSourceMap: false

3.关闭预加载
vuecli 3默认开启prefetch(预先加载模块),提前获取用户未来可能会访问的内容在首屏会把这十几个路由文件都下载下来

chainWebpack: (config) => {
    
    
      /* 生产环境下 */
      if (process.env.NODE_ENV === 'production') {
    
    
        //关闭预加载关闭prefetch
        //vuecli 3默认开启prefetch(预先加载模块),提前获取用户未来可能会访问的内容在首屏会把这十几个路由文件都下载下来
        config.plugins.delete('prefetch')
        config.plugins.delete('preload')
    }
}

4.压缩分割代码

chainWebpack: (config) => {
    
    
      /* 生产环境下 */
      if (process.env.NODE_ENV === 'production') {
    
    
        // 压缩代码
        config.optimization.minimize(true)
        // 分割代码
        config.optimization.splitChunks({
    
    
          chunks: 'all'
        })
    }
}

5.按需加载

利用babel-plugin-component
配置babel.config.js

module.exports = {
    
    
  presets: [
    '@vue/app'
  ],
  plugins: [
    ['import', {
    
    
      libraryName: 'vant',
      libraryDirectory: 'es',
      style: true
    }, 'vant'],
    [
      'component',
      {
    
    
        libraryName: 'element-ui',
        styleLibraryName: 'theme-chalk'
      }
    ]
  ]
}

6.cdn加速

cdn加速要注意寻找稳定的cdn地址

vue.config.js内配置

const cdn = {
    
    
    css: [
      'https://unpkg.com/[email protected]/lib/theme-chalk/index.css',
      'https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css'
    ],
    js: [
      'https://cdn.bootcss.com/vue/2.6.11/vue.min.js',
      'https://cdn.bootcss.com/vue-router/3.2.0/vue-router.min.js',
      'https://cdn.bootcss.com/vuex/3.1.2/vuex.min.js',
      'https://cdn.bootcss.com/axios/0.19.2/axios.min.js',
      'https://unpkg.com/[email protected]/lib/index.js',
      'https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js'
    ]
}
chainWebpack: (config) => {
    
    
  // 生产环境注入cdn
  config.plugin('html')
  .tap(args => {
    
    
      args[0].cdn = cdn
      return args
  })
}
configureWebpack: {
    
    
	  //忽略将这些加入打包
	  externals: {
    
    
	    vue: 'Vue',
	    'vue-router': 'VueRouter',
	    vuex: 'Vuex',
	    'element-ui': 'ELEMENT',
	    axios: 'axios',
	    lodash: '_'
	  }
 }

在index.htm中加入

动态加入css

<% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.css) { %>
      <link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet">
<% } %>

动态加入js

<% for (var i in htmlWebpackPlugin.options.cdn && htmlWebpackPlugin.options.cdn.js) { %>
      <script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
<% } %>

或者直接把vue,axios,vue-router,vant, iconfont等长期不需要更新的包整理到/public/cdn目录下然后引入
在这里插入图片描述
7.图片压缩
安装image-webpack-loader

不知道为什么我用yarn 安装一直装不全后来就用cnpm了

cnpm install mini-css-extract-plugin --save

vue.config.js配置

chainWebpack: (config) => {
    
    
     config
       .module.rule('images')
       .use('image-webpack-loader')
       .loader('image-webpack-loader')
       .options({
    
     bypassOnDebug: true })
       .end()
   }
}

8.gzip

安装compression-webpack-plugin

yarn add compression-webpack-plugin

配置

configureWebpack: {
    
    
     plugins: isProduction ? [
       new CompressionPlugin({
    
    
         test: /\.js$|\.html$|\.css/, //匹配文件名
         threshold: 10240, //对超过10k的数据进行压缩
         deleteOriginalAssets: true //是否删除原文件
       })
     ] : []
 }

nginx的配置文件nginx.conf中


location ~ .*\.(jpg|png|gif)$ {
    
    
       gzip on;
       gzip_static on;
       gzip_min_length 1k;
       gzip_http_version 1.1;
       gzip_comp_level 3;
       gzip_types image/jpeg image/png image/gif;
       root html;
    }
 
    location ~ .*\.(html|js|css)$ {
    
    
        gzip on;
        gzip_static on;
        gzip_min_length 1k;
        gzip_http_version 1.1;
        gzip_comp_level 9;
        gzip_types  text/css application/javascript;
        root html;
	}

生产坏境去除console

configureWebpack: (config) => {
    
    
    const c = config;
    c.name = 'title名称';
    // 生产环境取消 console.log
    if (process.env.NODE_ENV === 'production') {
    
    
      c.optimization.minimizer[0].options.terserOptions.compress.drop_console = true;
    }
  },

浏览器兼容

安装js语法优化插件(babel-polyfill, classlist-polyfill

yarn add babel-polyfill classlist-polyfill

安装babel-polyfillclasslist-polyfill。Babel是一个广泛使用的转码器,可以将ES6代码转为ES5代码,从而可以在现有环境执行,所以我们可以用ES6编写,而不用考虑环境支持的问题;classList.js是完全实现的跨浏览器JavaScript填充程序element.classList,解决不同浏览器的兼容性问题

配置vue.config.js文件

chainWebpack: config => {
    
    
    const entry = config.entry('app')
    entry
      .add('babel-polyfill')
      .end()
    entry
      .add('classlist-polyfill')
      .end()
  }
}

开发和生产环境的测试

yarn serve // 开发环境运行项目 检查项目是否存在白屏/报错等情况。
确认开发环境没有问题后
yarn build // 打包项目,生产环境测试,检查各浏览器兼容性等。

  • mode使用history时,需要配置服务器域名后全部url路径

  • mode使用hash时,不需要进行配置。

总结

完整vue.config.js配置

const CompressionPlugin = require('compression-webpack-plugin')
const isProduction = process.env.NODE_ENV === 'production'
const Timestamp = new Date().getTime() //当前时间为了防止打包缓存不刷新,所以给每个js文件都加一个时间戳
const Version = process.env.VUE_APP_Version//当前版本号
const cdn = {
    
    
    css: [
      'https://unpkg.com/[email protected]/lib/theme-chalk/index.css',
      'https://cdn.jsdelivr.net/npm/@mdi/font@latest/css/materialdesignicons.min.css'
    ],
    js: [
      'https://cdn.bootcss.com/vue/2.6.11/vue.min.js',
      'https://cdn.bootcss.com/vue-router/3.2.0/vue-router.min.js',
      'https://cdn.bootcss.com/vuex/3.1.2/vuex.min.js',
      'https://cdn.bootcss.com/axios/0.19.2/axios.min.js',
      'https://unpkg.com/[email protected]/lib/index.js',
      'https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js'
    ]
}
const url = ''//代理地址
module.exports = {
    
    
    devServer: {
    
    
        disableHostCheck: true,
        proxy: {
    
    
            '/code': {
    
    
                target: url,
                ws: true,
                pathRewrite: {
    
    
                  '^/code': '/code'
                }
            },
            '/admin': {
    
    
                target: url,
                ws: true,
                pathRewrite: {
    
    
                  '^/admin': '/admin'
                }
            },

          '/api': {
    
    
            target: url,
            ws: true,
            pathRewrite: {
    
    
              '^/api': '/api'
            }
          },
        }
    },
    transpileDependencies: ['vuetify'],
    pluginOptions: {
    
    
        i18n: {
    
    
            locale: 'en',
            fallbackLocale: 'en',
            localeDir: 'locales',
            enableInSFC: false,
        },
    },
    //打包配置
    outputDir: 'dist', // 在build时 生成文件的目录 type:string, default:'dist'
    publicPath: './',//默认路径
    lintOnSave: true,//每次保存调用eslint验证
    productionSourceMap: false,// 是否在构建生产包时生成 sourceMap 文件,false将提高构建速度(map文件能看到具体报错位置)
    chainWebpack: (config) => {
    
    
      const path = require('path')
      const resolve = dir => path.join(__dirname, dir)
      config.resolve.alias
        .set('@', resolve('src')) // 使用 @ 代替 src 下的目录
        .set('_c', resolve('src/components')) // 使用 _c 代替 components 目录
      /* 生产环境下 */
      if (isProduction) {
    
    
        //添加分析工具
        config
          .plugin('webpack-bundle-analyzer')
          .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin)
          .end()
        //关闭预加载关闭prefetch
        //vuecli 3默认开启prefetch(预先加载模块),提前获取用户未来可能会访问的内容在首屏会把这十几个路由文件都下载下来
        config.plugins.delete('prefetch')
        config.plugins.delete('preload')
        // 压缩代码
        config.optimization.minimize(true)
        // 分割代码
        config.optimization.splitChunks({
    
    
          chunks: 'all'
        })
        config
          .module.rule('images')
          .use('image-webpack-loader')
          .loader('image-webpack-loader')
          .options({
    
     bypassOnDebug: true })
          .end()
      }
      // 生产环境注入cdn
      config.plugin('html')
      .tap(args => {
    
    
          args[0].cdn = cdn
          return args
      })
    },
    configureWebpack: {
    
    
      // webpack 配置
      output: {
    
    
        // 输出重构  打包编译后的 文件名称  【模块名称.版本号.时间戳】
        filename: `js/[name].${
      
      Version}.${
      
      Timestamp}.js`,
        chunkFilename: `js/[name].${
      
      Version}.${
      
      Timestamp}.js`
      },
      //忽略将这些加入打包
      externals: {
    
    
        vue: 'Vue',
        'vue-router': 'VueRouter',
        vuex: 'Vuex',
        'element-ui': 'ELEMENT',
        axios: 'axios',
        lodash: '_'
      },
      plugins: isProduction ? [
        new CompressionPlugin({
    
    
          test: /\.js$|\.html$|\.css/, //匹配文件名
          threshold: 10240, //对超过10k的数据进行压缩
          deleteOriginalAssets: true //是否删除原文件
        })
      ] : []
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_39308542/article/details/102412174