gogogo
管理员
管理员
  • UID25
  • 粉丝0
  • 关注0
  • 发帖数1377
阅读:2265回复:1

webpack打包优化的几种方案

楼主#
更多 发布于:2022-06-02 09:45
实现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.Dll Plugin
该插件可以将特定的类库提前打包然后引入,这种方式可以极大的减少类库的打包次数,只有当类库有更新版本时才会重新打包,并且也实现了将公共代码抽离成单独文件的优化方案。



// 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中只要启动了mode为production就默认开启了该配置

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

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中只要开启生产环境就会自动启动这个功能

gogogo
管理员
管理员
  • UID25
  • 粉丝0
  • 关注0
  • 发帖数1377
沙发#
发布于:2022-06-02 09:45
游客


返回顶部