webpack 的基础用法之核心概念
entry 入口文件
单入口文件
entry是一个字符串1
2
3module.exports = {
entry: 'xxx.js'
}
多入口文件
entry是一个对象1
2
3
4
5
6module.exports = {
entry: {
index: 'index.js',
search: 'search.js'
}
}
output
output 用来告诉webpack如何将编译后的文件,输出到磁盘
单入口文件
只需指定output 的filename及path两个参数即可
1 | const path = require(''path) |
多入口文件
在output中没有多入口文件说法,而是通过占位符来确保输出的文件名称唯一1
2
3
4
5
6
7
8
9
10
11
12const path = require(''path)
module.exports = {
entry: {
index: 'index.js',
search: 'search.js'
},
output: {
filename: '[name].js',
path: path.join(__dirname, dist)
},
mode: 'production'
}
loaders
webpack 开箱即用只支持JS和JSON两种文件类型。需要通过loaders去支持其他文件类型并将它们转化成有效的模块,并且可以添加到依赖图中。
loader本身是一个函数,接受源文件作为参数,返回转换的结果。
常见的loader
名称 | 描述 |
---|---|
babel-loader | 转换es6、es7等新特性语法 |
css-loader | 支持.css文件的加载和解析 |
less-loader | 将less文件转换为css |
ts-loader | 将TS转换为JS |
file-loader | 进行图片、字体等的打包 |
raw-loader | 将文件以字符串的形式导入 |
thread-loader | 多进程打包js和css |
loader 的用法
1 | module.exports = { |
例1: 解析ES6
需要使用babel-loader 去解析,babel-loader又依赖于babel,所以项目中需要使用.babelrc文件
1 | // 安装解析ES6依赖 |
项目中新增.babelrc文件1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24// .babelrc
{
"presets" : [ // 一系列plugins的集合
"@babel/preset-env"
]
}
// 修改webpack.config.js
module.exports = {
... // 省略entry output
mode: 'production',
module: {
rules: [
{
test: /\.js$/,
use: 'babel-loader'
}
]
}
}
$ rm -rf dist // 清理当前dist目录
$ npm run build // 打包编译查看效果
例2: 解析React JSX
1 | $ npm i react react-dom @bebel/preset-react -D |
例3 : 解析css 、less
1 | // 解析 css |
需注意,loader是链式调用,执行方式是从右到左,所以在css应先css-loader解析css,然后传递给style-loader
plugins 插件
插件用于bundle文件的优化,资源管理和环境变量注入。
作用于整个构建过程。
可以理解为 loaders没办法做的事情,通过plugins来完成,如在打包前,手动删除打包目录,可用plugins来完成。
常见的plugins
名称 | 描述 |
---|---|
CommonChunkPlugin | 讲chunks相同的模块代码,提取成公共js |
CleanWebpackPlugin | 清理构建目录 |
CopyWebpackPlugin | 将文件或文件夹拷贝到构建的输出目录 |
ExtractTextWebpackPlugin | 将css从bundle文件里提取成一个独立的css文件 |
HtmlWebpackPlugin | 创建html文件去承载输出的bundle |
UglifyjsWebpackPlugin | 压缩JS |
ZipWebpackPlugin | 将打包出的资源生成一个zip包 |
mode 环境
mode用来指定当前当前的构建环境是 production、development、none。
webpack 4之前没有这个概念,使用mode的好处是可以使用webpack的内置函数。如设置成development,将在开发阶段启动用于开发时使用的参数配置。
mode函数的内置功能
选项 | 描述 |
---|---|
development | 设置process.env.NODE_ENV 的值为 development,开启NameChunksPlugin和NameModulesPlugin. |
production | 开启FlagDependenUsagePlugin , FlagIncludedChunksPlugin , ModuleConcatenationPlugin等 |
none | 不开启任何优化选项 |
文件监听
文件监听,是在源码发生变化时,自动重新构建出新的输出文件
webpack的两种监听方式
- 轮询判断文件的最后编辑时间是否发生变化
- 某个文件发生了变化,并不会立刻告诉监听者,而是先缓存起来,等待一段时间(aggregateTimeout),若其它文件也有发生变化,则会将变化的文件列表一起去构建,生成到bundle中。
1
2
3
4
5
6
7
8module.export = {
watch: true // 默认为false 不开启
watchOptions: { // 只有开启了监听模式,watchOptions 才有意义
ignored: /node_modules/, // 默认为空,不监听的文件或文件夹,支持正则匹配
aggregateTimeout: 300, // 监听到变化后,会等300ms再去执行,默认为300ms
poll: 1000, // 判断文件是否发生变化是通过不停询问系统指定文件有没有变化实现的,默认每秒询问1000次
}
}
webpack-dev-server 热更新
1 | // pageage.json |
webpack原理分析
首先了解几个概念:
- webpack Compile: 将Js编译成Bundle
- HMR Server: 将热更新的文件传输给 HMR Runtime
- Bundle Server : 提供文件在浏览器端的访问
- HMR Runtime: 会被更新到浏览器,更新文件的变化
- bundle.js : 构建输出的文件
热更新的过程
热更新有两个过程。
- 文件的启动阶段
将初始代码经文件系统进行编译, 使用webpack Compile进行打包,打包好的bundle.js传输给bundle Server(服务器) ,bundle Server以server的方式让浏览器访问到。 - 代码更新阶段
文件系统(代码)更新后,使用webpack Compile 打包,传输给HMR Server, HMR Server(服务端)将发生变化的文件告知HMR Runtime(浏览器端),通常以JSON数据的形式进行传输,HMR Runtime 更新代码,实现不刷新更新。
文件指纹
打包后输出的文件名后缀。
文件指纹的生成
- Hash 和整个项目的构建有关,只要项目文件有更改,整个构建项目的hash值就会更改。
- Chunkhash 和webpack打包的chunk有关,不同的entry会生成不同的Chunkhash
- Contenthash 根据文件内容更新hash,文件内容不变,Contenthash不变。注:js 没有contenthash。
js文件指纹设置
设置output的filename,使用chunkhash1
2
3
4
5// webpack.config.js
module.export = {
// ...
output: '[filename][chunkhash:8].js'
}
css文件指纹设置
一般情况下,若项目中配置使用了style-loader和css-loader,会将编译好的css,使用style-loader插入到head中,没有独立的css文件,所以需要借用MiniCssExtractPlugin将style-loader 中的css提取为一个独立的文件,使用contenthash
1 | // webpack.config.js |
图片文件指纹设置
设置file-loader的name使用[hash]
1 | ``` |
占位符名称 | 含义 |
---|---|
ext | 资源后缀名 |
name | 文件名称 |
path | 文件相对路径 |
folder | 文件所在的文件夹 |
contenthash | 文件内容的hash, 默认md5生成 |
hash | 文件内容的hash, 默认md5生成 |
emoji | 一个随机的指代文件内容的emoji |
代码压缩
JS代码压缩
webpack4中内置了 uglifyjs-webpack-plugin 不需要再做处理了。
css代码压缩
使用optimize-css-assets-webpack-plugin,同时使用 cssnano(css预处理器)
1 | $ npm i optimize-css-assets-webpack-plugin cssnano -D |
html代码压缩
使用html-webpack-plugin设置压缩参数
1 | $ npm i html-webpack-plugin -D |