# Webpack
# webpack作用
# 模块打包
可以将不同模块的文件打包整合在一起,并且保证它们之间的引用正确,执行有序。
# 编译兼容
通过webpack的Loader机制,不仅仅可以帮助我们对代码做polyfill,还可以编译转换诸如.less, .vue, .jsx这类在浏览器无法识别的格式文件,让我们在开发的时候可以使用新特性和新语法做开发,提高开发效率。
# 能力扩展
通过webpack的Plugin机制,我们在实现模块化打包和编译兼容的基础上,可以进一步实现诸如按需加载,代码压缩等一系列功能,帮助我们进一步提高自动化程度。
# 基本使用
# 拆分配置和merge
# 处理ES6
# 处理样式
# 处理图片
# 高级配置
# 多入口
在entry配置多个入口文件。

output配置文件名

针对每个入口都创建一个HtmlWebpackPlugin

# 抽离并压缩css文件
配置css后缀文件的loader,使用MiniCssExtractPlugin

配置相关插件

# 抽离公共代码
在optimization中配置分割代码块

在HtmlWebpackPlugin中配置需要加载的chunks

# 异步加载JS(懒加载)
直接使用import语法即可(使用import语法引入,会为其单独生成一个chunk)

# webpack打包原理
# 运行流程
- 读取
webpack的配置参数 - 启动
webpack,创建Compiler对象并开始解析项目 - 从入口文件(
entry)开始解析,并且找到其导入的依赖模块,递归遍历分析,形成依赖关系树 - 对不同文件类型的依赖模块文件使用对应的
Loader进行编译,最终转为Javascript文件 - 整个过程中
webpack会通过发布订阅模式,向外抛出一些hooks,而webpack的插件即可通过监听这些关键的事件节点,执行插件任务进而达到干预输出结果的目的
# 具体原理
webpack主要依赖于compiler和compilation两个核心对象实现文件的解析和构建。
compiler对象是一个全局单例,他负责把控整个webpack打包的构建流程。 compilation对象是每一次构建的上下文对象,它包含了当次构建所需要的所有信息,每次热更新和重新构建,compiler都会重新生成一个新的compilation对象,负责此次更新的构建过程。
而每个模块间的依赖关系,则依赖于AST语法树。每个模块文件在通过Loader解析完成之后,会通过acorn库生成模块代码的AST语法树,通过语法树就可以分析这个模块是否还有依赖的模块,进而继续循环执行下一个模块的编译解析。
# Babel
core-js 是除了处理「生成器」相关语法的兼容性集合
regenerator是处理「生成器」相关语法的兼容性集合
babel-polyfill是core-js和regenerator的集合
# loader和plugin区别
# Loader
- Loader本质就是JS一个函数,在该函数中对接收到的内容进行转换,返回转换后的结果。
- Loader在module.rules中配置,类型为数组,里面每一项都是一个对象。对象里面包括test(类型文件)、loader、option(参数)等属性
{
test: /\.css$/,
use: ['style-loader','css-loader']
},
# Plugin
- plugin就是一个webpack插件,它主要用来扩展webpack的功能的。在wepack运行的生命周期过程中会广播出很多事情,plugin可以监听这些事件从而调用webpack的api改变输出的结果。
- 在 plugins 中单独配置,类型为数组,每一项是一个 Plugin 的实例,参数都通过构造函数传入。
//webpack.config.js
module.exports = {
mode: "development",
module: {
rules: [
{
test: /\.jsx?$/,
use: ['babel-loader'],
exclude: /node_modules/ //排除 node_modules 目录
}
]
},
plugins: [
//数组 放着所有的webpack插件
new HtmlWebpackPlugin({
template: './public/index.html',
filename: 'index.html', //打包后的文件名
minify: {
removeAttributeQuotes: false, //是否删除属性的双引号
collapseWhitespace: false, //是否折叠空白
},
// hash: true //是否加上hash,默认是 false
})
]
};
# 常用loader
- image-loader:加载并且压缩图片文件
- babel-loader:把ES6转换成ES5
- ts-loader:将TypeScript转成JavaScript
- sass-loader:将将SCSS/SASS代码转换成CSS
- css-loader:加载 CSS,支持模块化、压缩、文件导入等特性
- style-loader:把 CSS 代码注入到 JavaScript 中,通过 DOM 操作去加载 CSS
- postcss-loader: 浏览器兼容性
- eslint-loader:通过ESLint检查JavaScript代码
- vue-loader:加载Vue单文件组件
# 常用的plugin
- mini-css-extract-plugin:分离样式文件,CSS 提取为独立文件,可以按需加载
- terser-webpack-plugin:压缩ES6代码
- web-webpack-plugin:可方便地为单页应用输出 HTML
- clean-webpack-plugin:目录清理
- webpack-dashboard:更好的展示相关打包信息
- webpack-merge:提取公共配置,减少重复配置代码
- size-plugin:监控资源体积变化,尽早发现问题
- webpack-bundle-analyzer:生成bundle的模块组成图,可以显示所占的体积
- html-webpack-plugin:创建入口html文件,并且把打包的内容引入HTML中。
# 各种区别
# module、chunk、bundle
# module
可以理解为各个源码文件,在Webpack中一切皆模块
# chunk
由多个模块合并而成的,如import() splitChunk
# bundle
最终输出的文件
# 热更新和自动刷新
# 热更新
只更新配置的部分,状态会保留。
# 自动刷新
整个网页都会刷新,状态会丢失,配置简单。
# file-loader和url-loader区别
# file-loader
file-loader将文件(图片、音频、字体等)解析为url,并将该文件复制到输出目录中。
# url-loader
url-loader可以识别图片的大小,然后把图片转换成base64,从而减少请求的次数,如果图片超过设定的范围,就还是用file-loader来处理。
# babel-runtime和babel-polyfill
# webpack如何实现懒加载
# 性能优化
# 优化构建速度
# 优化babel-loader

# IgnorePlugin
忽略第三方包指定目录,让这些指定目录不要被打包进去
# noParse
该引入还是会引入,只是不参与loader或webpack的解析及打包
# happyPack多线程打包
在loader那里配置happypack

在plugin中配置HappyPack

# 使用ParallelUglifyPlugin多线程压缩优化JS
虽然Webpack内置了Uglify工具压缩JS,但是JS是单线程的,开启多线程压缩会更快。

# 热更新
配置HotModuleReplacementPlugin

在plugins中配置插件

在devServer设置hot: true
配置需要热更新的模块

# DllPlugin动态链接库
webpack已内置DllPlugin支持
# 先使用DllPlugin打包出dll文件
# 然后使用DllReferencePlugin使用dll文件
- 先使用webpack-bundle-analyzer进行体积分析,然后再根据实际的情况进行相应的优化
- 多进程/多实例构建:使用thread-loader
- 缓存
- babel缓存。cacheDirectory:true
- 文件资源缓存。hash名
- babel-loader 开启缓存
- terser-webpack-plugin 开启缓存
- 使用高版本的webpack
# 优化产出代码
# 小图片使用base64编码
使用base64编码,减少请求的次数
# bundle加hash
通过文件内容计算出hash,合理使用缓存
# 懒加载
# 提取公共代码
# IngorePlugin
# CDN加速
# Scope Hosting
# 优点
- 代码体积更小
- 创建函数作用域更少
- 代码可读性更好
# 配置方式

# webpack热更新原理
服务端与浏览器之间维持着一个websocket。当资源发生变化的时候,服务端会向浏览器推送更新信息,并且带上更新的hash。浏览器根据这个hash与旧的资源对比,如果发现有差异就发起Ajax去获取更新的内容。
# Tree-Shaking
# 开启方式
webpack中,mode设置为“Production”就会自动开启。