webpack性能优化:
开发环境性能优化
1)优化打包构建速度 —— HMR
2)优化代码调试—— source-map
生产环境性能优化
1)优化打包构建速度——oneOf、babel缓存、 多进程打包
2)优化代码运行的性能——文件缓存、tree shaking、code split、dll、懒加载和预加载、pwa、externals
开发环境配置–优化打包构建的速度
使用HMR(hot module repalcement),热模块替换,作用是一个模块发生改变,只会重新打包这个模块,而不是全部更新。极大地提升了构建速度。
**样式文件:**不必做特殊处理,使用的style-loader内部实现了热模块替换功能。
**js文件:**在默认情况下不会使用HMR功能,需要在js代码中添加支持HMR功能的代码。
if (module.hot) {
module.hot.accept('./logon.js', () => {
logon();
});
}
以上代码表示只有在logon模块发生改变时内部函数才会执行处理。其他模块不会重新打包构建,这段代码在那个中监听的logon模块在哪个js文件中引入,就在哪个js文件中添加即可。注意:HMR功能只能对非入口文件进行处理,入口文件无法处理。一旦入口文件被修改,整个项目代码都会被重新构建。
**html文件:**不能使用hot功能,需要在webpack配置入口修改配置,将html文件作为入口文件引入。但是修改完成之后,一旦html文件发生变化,所有文件都会被重新编译加载。
entry:["./src/js/index.js","./src/index.html"],
开发环境配置–优化代码调试
使用工具:source-map——提供一种源代码到构建后代码的映射技术,如果构建后代码出错,可以通过追踪源代码错误信息的位置。需要在webpack.config.js中新增配置项:
devtool:"source-map"
新增的配置会在构建后的输文件夹中输出对应的sourceMap文件,以方便在浏览器中通过源码进行调试,devtool取值的不同输出的sourceMap输出的方式也不同,关于devtool的取值如下如所示:
devtool | 含义 |
---|---|
空 | 不生成 Source Map,错误代码提示准确,没有任何的源代码信息 |
eval | 每个 module 会封装到 eval 里包裹起来执行,并且会在每个 eval 语句的末尾追加注释 //# sourceURL=webpack:///./main.js |
source-map | 会额外生成一个单独 Source Map 文件,并且会在 JavaScript 文件末尾追加 //# sourceMappingURL=bundle.js.map 。错误代码提示准确,并且提示源代码的错误位置。 |
hidden-source-map | 和 source-map 类似,但不会在 JavaScript 文件末尾追加 //# sourceMappingURL=bundle.js.map 。不能追踪源代码的错误位置,只能提示到构建后代码的错误位置 |
inline-source-map | 和 source-map 类似,但不会额外生成一个单独 Source Map 文件,而是把 Source Map 转换成 base64 编码内嵌到 JavaScript 中。错误代码提示准确,并且提示源代码的错误位置。 |
eval-source-map | 和 eval 类似,但会把每个模块的 Source Map 转换成 base64 编码内嵌到 eval 语句的末尾,例如 //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW... 。错误代码提示准确,并且提示源代码的错误位置。 |
cheap-source-map | 和 source-map 类似,但生成的 Source Map 文件中没有列信息,因此生成速度更快。错误代码提示准确,并且提示源代码的错误位置,只能精确到行,不能精确到列。 |
cheap-module-source-map | 和 cheap-source-map 类似,但会包含 Loader 生成的 Source Map错误代码提示准确,并且提示源代码的错误位置。 |
根据以上的配置,或生成独立的sourceMap文件或直接内敛至js文件的末尾。除了生成的sourceMap文件的不同之外,对源代码的映射也不同,即有错误可提示到源代码的具体位置,或是提示至打包构建后代码的位置。
打包后浏览器中sourceMap映射的源码:
生成单独map文件:
没有单独的sourceMap文件,内敛在js中的sourceMap:
那么问题来了,如何选择合适的source-map?
秉着开发环境构建速度更快,调试更加友好的原则,建议:
速度快(eval-source-map/eval-cheap-source-map),调试友好(source-map/cheap-module-source-map/cheap-sourcemap),所以在开发环境下把 devtool
设置成 cheap-module-eval-source-map
,因为生成这种 Source Map 的速度最快,能加速构建。由于在开发环境下不会做代码压缩,Source Map 中即使没有列信息也不会影响断点调试;
生产环境主要是考虑代码要不要隐藏,要不要做调试,因为内敛的sourceMap会让代码的体积变得巨大,所以内敛的方式都不会被采用,建议:
hidden-source-map 隐藏源代码,会提示构建后的代码错误信息。
生产环境需要调试的则直接使用source-map或者cheap-module-source-map
优化的配置项:
oneOf:优化module中loader的执行方式
如果你的module中配置了多个loader,webpack打包每一个文件的时候都会有序执行每一个loader配置,相当于每一个文件都会被所有的loader过一遍,会减缓webpack的打包速度。使用oneOf配置项可以使每一个文件只会匹配一个loader,oneof里面不能有两项配置处理同一个类型的文件:如果需要,则可以将其中一个优先执行的提取到oneOf外面进行配置:
module: {
//loader的详细规则
rules: [
{
test: /\.js$/,
loader: "eslint-loader",//js检查语法
exclude: /node_modules/,
enforce: 'pre',//优先执行
options: {
fix: true
}
<