VueWeb前端之路webpack学习

webpack打包优化

2019-09-22  本文已影响0人  不思量q

实现webpack打包优化,有两个优化点:


减少打包时间

  1. 优化Loader

    对于Loader来说,首先优化的当是babel了,babel会将代码转成字符串并生成AST,然后继续转化成新的代码,转换的代码越多,效率就越低。

    首先可以优化Loader的搜索范围

    module.exports = {
        module: {
            rules: [
                test: /\.js$/, // 对js文件使用babel
                loader: 'babel-loader',
                include: [resolve('src')],// 只在src文件夹下查找
                // 不去查找的文件夹路径,node_modules下的代码是编译过得,没必要再去处理一遍
                exclude: /node_modules/ 
            ]
        }
    }
    

    另外可以将babel编译过文件缓存起来,以此加快打包时间,主要在于设置cacheDirectory

    loader: 'babel-loader?cacheDirectory=true'
    
  2. HappyPack

    因为受限于Node的单线程运行,所以webpack的打包也是单线程的,使用HappyPack可以将Loader的同步执行转为并行,从而执行Loader时的编译等待时间。

    module: {
        loaders: [
            test: /\.js$/,
            include: [resolve('src')],
            exclude: /node_modules/,
            loader: 'happypack/loader?id=happybabel' //id对应插件下的配置的id
        ]
    },
    plugins: [
        new HappyPack({
            id: 'happybabel',
            loaders: ['babel-loader?cacheDirectory'],
            threads: 4, // 线程开启数
        })
    ]
    
  3. DllPlugin

    该插件可以将特定的类库提前打包然后引入,这种方式可以极大的减少类库的打包次数,只有当类库有更新版本时才会重新打包,并且也实现了将公共代码抽离成单独文件的优化方案。

    // webpack.dll.conf.js
    const path = require('path')
    const webpack = require('webpack')
    module.exports = {
        entry: {
            vendor: ['react'] // 需要统一打包的类库
        },
        output: {
          path: path.join(__dirname, 'dist'),
            filename: '[name].dll.js',
            library: '[name]-[hash]'
        },
        plugins: [
            new webpack.DllPlugin({
                name: '[name]-[hash]', //name必须要和output.library一致
                context: __dirname, //注意与DllReferencePlugin的context匹配一致
                path: path.join(__dirname, 'dist', '[name]-manifest.json')
            })
        ]
    }
    

    然后在package.json文件中增加一个脚本

    'dll': 'webpack --config webpack.dll.js --mode=development'
    //运行后会打包出react.dll.js和manifest.json两个依赖文件
    

    最后使用DllReferencePlugin将刚生成的依赖文件引入项目中

    // webpack.conf.js
    module.exports = {
        //...其他配置
        plugins: [
            new webpack.DllReferencePlugin({
                context: __dirname,
                manifest: require('./dist/vendor-manifest.json') //此即打包出来的json文件
            })
        ]
    }
    

    更多有关webpack配置DllPlugin请参考如何使用 Webpack 的 Dllpluginwebpack中DllPlugin用法

  4. 代码压缩相关

    • 启用gzip压缩

    • webpack3中,可以使用UglifyJS压缩代码,但是它是单线程的,因此可以使用webpack-parallel-uglify-plugin来运行UglifyJS,但在webpack4中只要启动了modeproduction就默认开启了该配置

    • 压缩html和css代码,通过配置删除console.logdebugger等,防止可能造成的内存泄漏

      new UglifyJsPlugin({
          UglifyOptions: {
              compress: {
                  warnings: false,
                  drop_console: true,
                  pure_funcs: ['console.log']
              }
          },
          sourceMap: config.build.productionSourceMap,
          parallel: true
      })
      //或使用以下配置
      new webpack.optimize.UglifyJsPlugin({
          compress: {
              warnings: false,
              drop_debugger: true,
              drop_console: true
          }
      })
      

减少打包大小

  1. 按需加载,首页加载文件越小越好,将每个页面单独打包为一个文件,(同样对于loadsh类库也可以使用按需加载),原理即是使用的时候再去下载对应的文件,返回一个promise,当promise成功后再去执行回调。

  2. Scope Hoisting

    它会分析出模块之前的关系,尽可能的把打包出来的模块合并到一个函数中去

    // 如在index.js问价中引用了test.js文件
    export const a = 1  // test.js
    import {a} from './test.js'  // index.js
    // 以上打包出来的文件会有两个函数,类似如下
    [
        function(module, exports, require) {} // **0**
        function(module, exports, require) {} // **1**
    ]
    

    如果使用scope hoisting的话会尽量打包成一个函数,在webpack 4中只需开启concatenateModules即可

    module.exports = {
        optimize: {
            concatenateModules: true
        }
    }
    
  3. Tree shaking

    它会删除项目中未被引用的代码,而如果在webpack 4中只要开启生产环境就会自动启动这个功能

上一篇下一篇

猜你喜欢

热点阅读