功能概览
- 代码转换 (各种loader)
- 文件优化、压缩 (terser)
- 代码分割、首屏优化()
- 模块合并()
- 自动刷新(HMR)
- 代码校验
- 自动发布
优点
- 专注于模块化项目
-
缺点
-
概念
entry 项目入口文件
chunk 多个模块组成的块
module 一个文件
loader
plugin流程
从项目入口文件(entry)开始,递归解析依赖的module,每个module通过loader进行转换,转换后解析出module依赖的module,生成一个chunk,将chunk输出为文件
优化
优化构建速度
让尽可能少的文件被loader处理
- 明确第三方模块的入口文件,减少搜索(缩小文件搜索范围)
- resolve.modules配置三方模块的查找路径
- resolve.alias 通过别名映射到三方库线上使用的文件(压缩的去模块化的文件)react =》 dist/react.min.js
- resolve.extensions配置后缀匹配 、频率出现高的后缀优先进行匹配
- resolve.modules.noParse忽略某些没有模块化的文件的递归解析处理
- 重复模块只编译一次(编译后的模块暴露在全局,下次编译直接通过变量获取)
- 多进程减少文件读写、压缩与其他计算密集型操作时间 happypack?
- 动态链接库 dllPlugin 与代码分割的关系?
-
优化开发体验
-
优化输出质量
CDN加速
- 静态资源文件带上hash值,防止被缓存
- 将不同类型的资源放到不同域名cdn服务上,防止资源并行加载被阻塞、入口html文件放到业务服务器上,防止被缓存
- 资源域名预解析?
- 压缩
- css压缩(cssnano)
#ffoooo =》red10px 20px 10px 20px =》 10px 20px - js压缩(Terser)内嵌已定义但是只用到一次的变量 提取出现多次但是没有定义成变量去引用的静态值 删除console 是否保留注释
- 尽量使用ES6代码,代码量小,const申明读取速度快,去掉babel-preset-env插件配置
- css压缩(cssnano)
- sourceMap
- Tree Shaking、按需加载
- 异步加载chunk
- 提取公共chunk
DefinePlugin
CommonsChunkPlugin=>optimization.splitChunks
模块
webpack生成的代码是一个IIFE
模块会被结构化,勒石于
module={id:@id,load:bool,exports:{}}
模块数据会以字典的形式保存在文件中
{‘path1’:代码,’path2’:代码}
这里的path可以看作moduleid值,生产模式会经过算法简化
webpack对于不同模块的实现,是基于自己实现的__webpack_require__ 和__webpack_exports__ ,装换成类似于commonjs的形式。对于es6模块通过__webpack_require__.r方法添加标识符
异步加载模块原理
import().then()
import 会被编译为webpack_require.e
该方法会返回一个决议后的promise,promise的resolve, reject被封装在loadingEnded函数内,同时通过document.createElement script加载异步脚本,
这个函数在script脚本加载执行之后触发onLoad事件执行,这个时候脚本已经执行,会在全局挂载新加载的moudle,manifest?
promi决议之后webpack_require通过模块标识符执行module,获取exports值返回给业务代码
类似于jsonp
长效缓存
runtime 提取optimization.runtimeChunk
