webpack的打包优化的一些具体操作

·  阅读 220

这是我参与更文挑战的第30天,活动详情查看: 更文挑战

不扯别的,直接主题,主要整理一下我们项目中较为常用的一些优化操作:比如多线程打包,缩小打包作用域,动态链接库思想,还有tree shaking。

HappyPack

Happypack是一个通过多线程来提升webpack打包速度的工具,小项目可能看不出明显效果,但是大中型工程而言,HappyPack确实可以显著地缩短打包时间。

工作原理

webapck需要一步步的获取更深层级的资源,然后做个进行转译。这里的问题在于webpack是单线程的,假设一个模块依赖于几个其他模块,webpack必须对这些模块一个个进行转译。虽然这些转译任务批次之间没有任何的以来关系,却必须串行的执行。HappyPack恰恰以此为切入点,它的核心特性是可以开启多个线程,并行地对不同的模块进行转译,这样就可以充分利用本地的计算资源来提升打包速度。

Happypack适用与那些转译工作比较重的工程,一般作用于babel-loader,ts-loader等,对于sass-loader、less-loader本身消耗时间并不是太多的工程效果一般。

使用方式

单个loader优化

const HappyPack = require('happypack');
module.exports = {
    // ...
    module: {
        rule: [
            {
                test: /\.js$/,
                exclude: /node_modules/.
                loader: 'happypack/loader',
            }
        ]
    }
    plugins: [
        new Happypack({
            loaders: [
                {
                    loader: 'babel-loader',
                    options: {
                        presets: ['react']
                    }
                }
            ]
        })
    ]
}
复制代码

多个loader

const HappyPack = require('happypack');
module.exports = {
    // ...
    module: {
        rule: [
            {
                test: /\.js$/,
                exclude: /node_modules/.
                loader: 'happypack/loader?id=js',
            },
            {
                test: /\.ts$/,
                exclude: /node_modules/.
                loader: 'happypack/loader?id=ts',
            }
        ]
    }
    plugins: [
        new Happypack({
            id: 'js',
            loaders: [
                {
                    loader: 'babel-loader',
                    options: {
                        presets: ['react']
                    }
                }
            ]
        }),
        new Happypack({
            id: 'ts',
            loaders: [
                {
                    loader: 'ts-loader',
                }
            ]
        })
    ]
}
复制代码

缩小打包作用域

从前端的宏观角度来讲,提升性能的方法无非有两种,增加资源或者缩小范围,增加资源就是指使用更多的CPU和内存,用更多的计算能力来缩短执行任务的时间;缩小范围就是针对任务本身,尽量不做重复性工作。

exclude、include

对于js来说,一般要把node_modules目录排除掉,另外当exclude和incude规则有重叠的部分,exclude优先级更高。写法如下:

 module: {
    rule: [
        {
            test: /\.js$/,
            include: /src\/sciprts/.
            loader: 'babel-loader',
        },
    ]
}
复制代码

noParse

有些库我们是希望webapack不用去解析的,即不希望应用任何loader规则,库的内部也不会有对其他模块的以来,这种情况可以使用noParse对其进行忽略。

module:{
    noParse: /lodash/  //此处还算可以是function,return返回路径
}
复制代码

IgnorePlugin

exclude和include是确定loader的规则范围,noParse是不去解析,但仍会打包到bundle中的,而IgnorePlugin是可以完全排除一些模块,被排除的模块即便被引用也不会被打包进资源文件中。

plugins:[
    new webpack.IgnorePlugin({
        resourceRegExp: /^\.\/locale$/, // 匹配资源文件
        contextRegExp: /moment$/, // 匹配检索目录
    })
]
复制代码

Dllplugin

dll借鉴了动态链接库的这种思路,对于第三方模块或者一些不常变化的模块,可以将他们预先编译和打包,然后在项目实际构建工程中直接取用即可。dll和code splitting有点类似,都可以用来提取公共模块,但本质上有一些区别,code splitting的思路是设置一些特定的规则并在打包过成功根据这些规则提取模块。dll是将vendor完全拆出来,有自己的一整套webpack的配置,并独立打包,在实际工程构建时就不用在对他进行任何处理,直接取用即可。因此,理论上来说dll比code splitting在打包速度上更胜一筹,但也响应的增加了配置,以及资源管理的复杂度。 这里不写具体代码,因为有点复杂,每个人设置的不一定一样,请参考官网即可。

tree shaking

es module依赖关系的构建是在代码编译时而非运行时。基于这项特性webpack提供了tree shaking 功能,它可以在打包过程中帮助我们检测工程中没有被引用过的模块,这部分代码将永远无法被执行到,因此也被称为死代码。webpack会对这部分代码进行抛弃,并且在资源压缩时将他们从最终的bundle中去除

tree shaking只能对ES5 module 生效,有时我们会发现虽然只因用了某个库中的一个接口,却把整个库加载进来了,而bundle的体积并没有因为tree shaking而减小。这可能是由于该库是使用commonjs 的形式到处的,为了获得更好的兼容性,目前大部分的npm包还在使用commonjs的形式。也有一些npm包同时提供了es module和commonjs两种形式到处,我们应该尽可能使用es module形式的模块,这样 tree shaking的效率更高。

关于webapck的一些优化说明就到这了,当理论看吧,代码还是看看官网,官网更详细!!!

分类:
前端
标签: