webpack - 性能优化

108 阅读5分钟

内容来源:webpack.wuhaolin.cn/4%E4%BC%98%…

webpack.wuhaolin.cn/4%E4%BC%98%…

1.缩小文件搜索范围

1.1 通过优化loader的 test、include、exclude

如下,如果只有js文件可以配置/.js$/而不要再匹配jsx等 通过include 调整,只对某个文件目录下的采用loader 通过exclude排除不需要使用的文件

image.png

1.2 resolve.modules 使用绝对目录

resolve.modules用于配置webpack 去哪个目录下寻找第三方模块,如果我们能知道具体的第三方模块存放的路径,可以指定一下,这样可以减少搜索步骤

image.png

resolve.mainFields用于指定第三方模块的入口文件,我们可以把它设置的尽量少,减少搜索步骤 resolve.alias 用于配置别名 image.png

1.3 优化 module.noParse 配置

module.noParse 可以让webpack忽略没采用模块化(例如:commonjs)的文件的递归解析处理。 一些库,例如jquery、chartJS等等,如果没有采用模块化标准,并且体积比较庞大,可以让webpack忽略对这些文件进行解析。

image.png

2.使用自动刷新

2.1文件监听

webpack提供了两个模块,一个是webpack,一个是webpack-dev-server,其中,文件监听watch是 webpack提供的

ignored:/node_modules/ aggregateTimeout:300 设置监听后,300ms再去执行,避免文件更新太快导致 重新编译频率太高 poll: 1000 判断文件是否更新是通过不停去询问指定文件有没有变化实现的

image.png 原理

image.png

2.2自动刷新浏览器

image.png

image.png

3.模块热替换 HMR

原理也是网页中注入一个代理客户端,用于连接网页和DevServer。 webpack-dev-server --hot 优点

  1. 实时预览,反应更快,等待时间更短。
  2. 不刷新浏览器,能保存当前网页运行状态,页面中其他的信息保持不变。

3.1优化HMR

1.使用NameModulesPlugin --显示热替换时的模块名称

image.png 2. 监听更少的模块,ignored忽略node_modules

image.png

4. 区分环境

    process.env.NODE_ENV === 'production'
    true --线上环境
    false --开发环境

image.png

5. 压缩代码

image.png

5.1 压缩JavaScript

目前成熟的 UglifyJS. 它会分析JS语法数,理解代码含义,从而可以做到 去掉无效代码、去掉日志输出代码、缩短变量名等优化。

  • . UglifyJSPlugin 通过封装UglifyJS实现压缩
  • . ParallelUglifyPlugin 多线程并行处理压缩

image.png

image.png

5.2 压缩ES6

image.png

5.3 压缩CSS

image.png 通过css-loader?minimize 开启压缩css选项

image.png

6. CDN加速

CDN 又叫内容分发网络,通过把资源部署到世界各地,用户在访问时按照就近原则从离用户最近的服务器获取资源,从而加速资源的获取速度。 CDN服务一般都会开启很长时间的缓存,例如用户从 CDN 上获取到了 index.html 这个文件后, 即使之后的发布操作把 index.html 文件给重新覆盖了,但是用户在很长一段时间内还是运行的之前的版本,这会新的导致发布不能立即生效

比较常见的做法是: html文件:不开启缓存,把HTML文件放在自己服务器上,而不是CDN服务器。 针对静态JS、CSS、图片等文件,开启CDN和缓存,上传到CDN服务上去,同时给每个文件名上带上** Hash值**,这样文件名会随着内容而变化,只要文件名发生改动,对应的 URL 就会改变,重新下载。

image.png

  • output.publicPath 中设置 JavaScript 的地址。
  • css-loader.publicPath 中设置被 CSS 导入的资源的的地址。
  • WebPlugin.stylePublicPath 中设置 CSS 文件的地址。

image.png

7.Tree Shaking

  • tree Shaking 用于剔除JS中用不上的死代码,它依赖静态ES6模块化语法,通过import、export导入导出。

  • 它的原理是因为ES6模块化语法是静态的,它的导入导出语句是静态的字符串,这样webpack可以简单的分析出哪些export 被import过了。

image.png

7.1 接入Tree Shaking

  1. .babelrc中 modules 设置为 false,关闭bable将es6转化为es5
    
  2. 运行时带上 `--display-used-exports`
    

image.png 3. 做完上述操作后,代码中其实还是保留了用不上的代码,想要剔除可以用UglifyPlugin来实现,也可以通过 webpack --display-used-exports --optimize-minimize 来实现。

  1. 当使用大量第三方库时,效果并不明显, 因为很多都是CommonJS的语法,但是越来越多的库考虑到这点,在发布到npm上时会提供两种,CommonJS 和Es6模块化的语法,并在packge.json指出两个模块的入口 我们可以** resolve.mainFields优先采用es6的语法**。

image.png

8.提取公共代码

image.png 利用CommonsChunkPlugin 提取公共代码 可以抽离某几个页面的公共代码,也可以抽所有页面都依赖的公共代码

image.png

image.png 公共代码抽离完后,原页面内容会变小,我们需要把每一个公共的模块都引入进去。

image.png

9.按需加载

image.png 内置了import,import返回是一个Promise,当文件加载成功时,可以通过Promise.then拿到导出的内容。

image.png

10.Prepack

image.png

image.png

11.Scope Hoisting

Scope Hoisting 可以让Webpack打包出来文件更小,运行更快,译作:作用域提升

  • 原理:分析出模块之间的依赖关系,在保证不造成代码冗余的情况下,尽可能把打散的模块整合到一个函数中去,这样可以减少申明语句、代码在运行时创建的作用域更少了,内存开销也更少。

  • 同Tree-shaking一样,依赖Es6 modules. image.png

image.png

12.输出分析

image.png

image.png

13.DllPlugin

image.png

常见plugin

  1. DefinePlugin -- 定义环境变量
  2. ParallelUglifyPlugin、UglifyJSPlugin 代码压缩
  3. CommonsChunkPlugin 提取公共代码
  4. DllPlugin 动态链
  5. NameModulesPlugin 指定热替换模块 的name hot-module-replacement-plugin
  6. web-webpack-plugin \html-webpack-plugin 为单页应用输出HTML
  7. prepack-webpack-plugin facebook提供的prepack 直接修改逻辑