You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
const TerserPlugin = require('terser-webpack-plugin');
// webpack 4.0 新增的terser-webpack-plugin插件, 可以支持sourcemap, parallel并行压缩, 开启缓存等提高效率的功能
optimization: {
minimizer: [
new TerserPlugin({
cache: true,
parallel: true,
sourceMap: false,
// Must be set to true if using source-maps in production
terserOptions: {}
})
]
}
前言
webpack是个很好很好的工具, 前端作为面对资源比较多的一个工种, 为了整理和对接各种各样的资源, 样式资源,脚本资源, 超文本标记语言html,svg, 图片展示资源, 字体等等, 提升用户的体验, 提升开发效率, 对前端的开发流程的痛点, 进行了各种工具的聚合和利用, webpack确实在这方面是前端一个标志性的工具,
webpack里面的许多功能是社区共同努力的结果, 但是为了我们苦逼的前端程序员 的开发,调试,部署提供了太多太多的便利了.
webpack目前进行到了webpack5.0的版本开发, 但是在HMR, Live Reload的的响应时间仍然是不够快.下面总结了一下怎么提高打包效率和减小的打包文件的体积的方法.
提升webpack优化打包速度
babel-loader的cacheDirectory
利用
babel-loader
我们无负担的使用ES的新特性, 但是webpack的使用,在开发过程中需要不断的重复编译,非常消耗cpu, 又要进行各种loader的处理, 所以如果有缓存, 这会大大减少不必要的重复劳动,cacheDirector
就是这么一个属性,可以缓存babel
的编译结果.第一次打包和二次打包的对比图
cacheDirectory的缓存内容
cache的内容是babel-loader的需要polyfill的各种库函数,比如上面需要支持Class的语法, 那么就会缓存进来, 当然缓存的结果是是根据babel的配置而生成的, 使用
@babel/polyfill
和@babel/plugin-transform-runtime
生成的库函数当然是会不一样, 详情请看我之前关于babel的文章webpack 学习笔记(7)-bable 的各种依赖理解,corejs, babel-runtime, babel-polyfill 等等-2019-10-13.这个文件能否应用缓存是有条件的, cacheDiretory的启用会去当前项目的目录下面寻找
node_modules/.cache/babel-loader
下寻找, 如果找不到则会全局环境下的node_modules/.cache/babel-loader
下寻找.此外, 如果想要缓存失效的话, 可以修改
cacheIdentifier
的值以强制更新缓存. 默认由@babel/core的版本, babelrc的信息, 环境变量等等生成的值, 如果这些信息改变, 那么也会更新缓存, 当然如果缓存对应的源文件有改动, 缓存也会重新生成, 所以, 一般我们使用的话, 直接开启, 如{cacheDirectory:true}或者'babel-loader?cacheDirector'
就可以.webpack的dllPlugin
这也是一个利用缓存,去减少重复编译的例子, dll简称动态链接库(Dynamic Link Library), 最常见到, 应该是在微软的系统里面, 安装完一个程序之后打开安装的文件夹会看看许多的xxx.dll的文件, 这就是动态链接库. 这是用来给应用程序用的.
来到webpack的编译, 就可以利用这个dllPlugin这个插件, 帮我们缓存已经加载的库, 这些库的文件, 比如
vue.js
,lodash
等等, 不会轻易变动. 自然也就是不需要重复编译.添加dll 动态链接库之前
添加dll 动态链接库之后
效果是很理想的, 如果想改进打包速度, 一定不要忘记了这个.
loader配置具体的include,exclude
loader的加载, 特别是babel-loader一定不要忘记添加exclude剔除node_modules的打包目录.
一般来说, 上npm的资源都会通过严格的浏览器的兼容测试, 否则也不是一个能够在生成环境使用的包,如果没有兼容, 这个时候就需要对该库的选择进行仔细的考量了, 所以在一般情况下不需要使用
babel-loader
进行二次的兼容转译的, 除非不得已的情况.resolve.modules
webpack
是用node
来实现的打包项目, 其中对于模块的引入, 是commonjs2的规范的, 第三方依赖模块会在安装node_modules
下, 而对于require('vue')
这样的语句, node会在当前的目录下去找node_modules
, 然后逐级向上一个目录寻找, 最后会到全局的node_modules目录寻找, 项目的层级越深对于模块的寻址负担越大.通过指定resolve.modules的属性,可以一定程度上减少模块寻址带来的压力
resolve.mainFields
当我们引入一个第三方模块的时候, 首先会去取当前项目目录node_module上去寻找, 查找并且分析模块的package.json文件, 然后加载main属性对应的文件模块.
在下面配置里面, webpack的mainFields属性, 这样如果导入模块
import foo from "foo";
的时候会先去mainFields里面寻找foo
这个模块, 然后在package.json
里面寻找brower
字段对应的文件, 如果没有再依次的寻找module
,main
.resolve.alias
我们平时配置别名的方式, 会大大的减少我们引入模块的路径书写长度.
比如
resolve.extensions
默认的后缀, 导入模块后缀缺省时, 会在extensions的列表里面, 按照顺序去寻找后缀的文件, 这个后缀列表需要遍历, 所以原则上越少越好,常用的类型放前面.
module.noParse
针对某些模块不使用loader进行解析.
这个属性是用来忽略特定的模块的, 一些模块不需要经过webpack的模块引入也可以运行,比如
jquery
, 这样子可以减少webpack的编译时间.module.externals
通过声明外部模块的别名, 在引入该模块的时候,webpack并不会去node_modules里面去寻找,而是去当前的全局变量中加载, 所以配合externals的属性使用, 需要在模板里面引入对应的script地址, 通常是使用cdn的地址.
Happypack 多进程打包
首先明确的是Happypack是对loader的处理, 由主进程分配loader, 打包完成之后合并到主进程进行处理.
所以, 打包的效果提升是有限的, 在充分使用了Dll和babel的cache情况下, 提升并没有说太明显, 但是, 如果系统设计到大量的图片资源base64的处理这种业务, loader处理耗费CPU, 那可能happypack的收益会很高,值得去尝试.
第一步安装:
第二步loader的加载资源指定happypack:
id是一个标识符,表示当前的资源使用指定的happypack实例,可以同时new 多个happypack进行打包,另外当前的haapypack不支持vue-loader, 如果想要使用happlypack编译vue文件,需要把vue文件里面的内容, 比如js部分, 单独使用happypack来打包.
像这样
ParallelUgligyPlugin 或者 terset-webpack-plugin
多入口的项目或者文件比较多的项目, 推荐使用
ParallelUgligyPlugin
或者terset-webpack-plugin
, 都是支持多进程打包的, 而ParallelUgligyPlugin
出现的时间比较早, 所以在webpack4.0之后推荐用terset-webpack-plugin
, 基本上ParallelUgligyPlugin
有的功能都有, 而且是官方的包, 比较稳定.ParallelUgligyPlugin的使用
test
, 可选参数, 默认是 /.js$/, 匹配压缩的对象include
,exclude
, 可选的参数,cacheDir
, 可选的缓存目录, 绝对路径workerCount
,开启的进程数, 默认cpu的数量-1sourceMap
, 默认不开启, 会降低打包的速度uglifyJS
, uglifyJs的配置uglifyES
, uglifyES的配置信息, 这是一个支持ES Module版本的uglifyJs, 但是也是因为这个库不再维护, 所以webpack默认用terser
来进行压,terser
也是uglifyJs
的一个fork,配置上大同小异.## 小结
以上是优化和提升打包速度的几个主要的方式
减低打包的文件体积
Scope Hoisting
这个特性, 会在webpack4.0 配置
mode:'production'
里面自动开启, 具体的作用是提升作用域, 简单的来说就是把内嵌的函数提升到根路径, 在模块化编程里面, 常见各种文件互相嵌套, 并且是深层次的嵌套, 提升作用域可以减少函数作用域的数量.更多的
scope hoising
信息请看这里webpack学习笔记(9)-scope Hoisting, 介绍怎么利用了ModuleConcatenationPlugin
插件进行堆栈的抽取和生成的.Tree Shaking
webpack2.0初步引入,旧版的
webapck2.0
对tree-shaking的dead code代码剔除支持不是很好, webpack4.0之后默认改用了terser-webpack-plugin
进行压缩代码,同时指定package.json#sideEffects
属性, 可以有效的剔除dead code.任何
import
的代码都有可能产生tree-shaking
,包括css,less,scss
比如import '@/less/a.less'
,如果不指定代码具有副作用, 会在production
的时候被剔除.生成gzip的压缩文件
在nginx的系统上配置
sendfile:on
, 开启linux上的系统调用, 可以非常快速的把磁盘的文件推给客户端,避免了读取磁盘, 写入buffer, 打包压缩gzip的过程.
总结
在最后,这篇文件林林总总参考和阅读了许多博客文章和笔记,官方文档,有的在实际项目中实践过,有切身感受, 有的也没有亲身实践,只草草的写了demo实践经验浅薄, 比如happypack, 所以侧漏之处各位不妨提醒,共同学习进步, 感谢!.
参考
The text was updated successfully, but these errors were encountered: