基本搭建
1 | npm init -y |
一顿yes直接搭建好基本的node环境
1 | yarn install webpack webpack-cli --save-dev |
安装webpack, webpack-cli, 由于是开发环境需要,加上–save-dev
1 | module.exports = { |
新建index.js
, 新建webpack.config.js
, webpack
默认读取webpack.config.js
导出的对象.
1 | npx webpack |
webpack
默认读取根路径下的webpack.config.js
文件, npm
5.2之后提供了自动安装npx
,会自动查找当前依赖包中的可执行文件并执行
context
定义了打包的基础目录, 一旦设置, 那么接下来配置设置的根路径将会是配置的基础目录。
1 | const path = require('path'); |
entry
文件打包的起点
- 可以传入数组, 传入数组从前往后依次进行打包, 包名为main
- 可以传入对象, 每个键作为打包的包名, 值为打包的资源路径或者打包的描述符多入口可以设置打包依赖, 减少包体积, 避免重复使用相同的包
1
2
3
4
5
6
7
8
9
10
11
12
13
14module.exports = {
//...
entry: './index.js'
};
// 也可以自定义包名
module.exports = {
//...
entry: {
app: './app.js',
home: { import: './contact.js', filename: 'pages/[name][ext]' },
about: { import: './about.js', filename: 'pages/[name][ext]' }
}
};可以动态引入, 将在make事件中触发1
2
3
4
5
6
7module.exports = {
//...
entry: {
app: { import: ['./app.js', './app2.js'], dependOn: 'react-vendors' },
'react-vendors': ['react', 'react-dom', 'prop-types']
}
};1
2
3
4module.exports = {
//...
entry: () => './demo' // () => new Promise((resolve) => resolve(['./demo', './demo2']))
};
mode
打包模式分为development
和production
1 | module.exports = { |
可以在打包时决定
1 | npx webpack --mode=development |
如果我们需要在不同模式下进行定义不同的打包行为, 我们可以定义为函数, 使用方法如下。
开发环境打包文件webpack.base.js
1 | module.exports = (options) => ({ |
主打包文件webpack.dev.js
1 | module.exports = require('./webpack.base.js')({ |
通过配置进行打包, 选择对应的打包文件
1 | webpack --config webpack.dev.js |
output
打包的输出形态, 包括bundle和静态文件
filename
filename
是一个很常见的配置,就是对应于 entry
里面的输入文件。
这里可以使用可替换模板字符串的形式定义输出的打包文件名,浏览器存在缓存机制,如果名称相同,浏览器默认文件没有改变,这样打包文件名相同会使得获取文件出现问题,因此我们通过可替换模板字符串的形式定义输出的打包文件名。
- 编译层
- name: chunk文件名
- chunk层
- id: 内部chunk的id
- chunkhash:这个chunk的hash值
- 模块层
- contenthash: 根据内容生成的hash
- id:模块id
- hash:模块的hash值
- 文件层:
- file: 文件名称和路径
- query: 带前缀 ? 的 query
- url层:
- url
具体参照模板字符串替换
chunkFilename
chunkFilename
指未被列在 entry
中,却又需要被打包出来的 chunk
文件的名称。一般来说,这个 chunk
文件指的就是要懒加载的代码。
注意点: 默认文件输出为[id].js
或者遵循output.filename
的设置,如果output.filename
设置了name
, 则会被预先替换为id
可以参照这篇文章看到filename和chunkFilename的区别
path
打包文件路径
publicPath
外部资源路径,通常以/
结尾, 默认参照路径为HTML页面所在的路径为准
例如如下配置,请求一个chunk
就相当于请求/assets/1.chunk.js
1 | module.exports = { |
library
组织打包的模块,库开发使用
libraryTarget
库打包引入的方式
Module
module
对象用于模块的处理方式
rules
对应值为[Rule]
数组
rules
作用在于提供模块的创建规则,提供对应的loader
和解析器(parser
)
Rule
Rule
是一个对象,这个对象分为三部分
- 条件匹配: 条件匹配通过
test
、include
、exclude
和resource
对资源进行匹配(这个资源指的是请求的资源),并且属性issuer
对issuer
匹配, 这个issuer
指的是请求者的文件绝对路径。是导入时的位置。 - 应用规则: 对选中的文件使用
use
来应用loader
,按照从后往前的顺序应用, 并可以为loader传递参数。 - 嵌套规则:父规则(文档这里没怎么理解, 在我看来是指一般的规则)、
rule
、oneOf
的顺序,可以通过enforce
强制修改顺序。
1 | module.exports = { |
- 注意:
loader
顺序从右往左,从下往上执行,按照pitching
顺序执行1
2
3
4
5
6
7|- a-loader `pitch`
|- b-loader `pitch`
|- c-loader `pitch`
|- requested module is picked up as a dependency
|- c-loader normal execution
|- b-loader normal execution
|- a-loader normal execution
Rule.oneOf
一旦匹配,就使用
1 | module.exports = { |
Rule.use
提供一个 loader
数组, 从右往左进行匹配
1 | module.exports = { |
Rule.exclude/include
排除/包括 loader
加载某个模块
Rule.parse
文件被 loader
执行后会转成一段js字符串, parse
会将其转换为 AST
语法树,有了语法树就可以对代码为所欲为了,其中最重要的功能就是分析出这段代码依赖了哪些模块
Rule.sideEffect
模块是否包含副作用
Rule.type
设置匹配模块的类型,防止 webpack
自定义的行为发生,常用于自定义loader加载模块
Rule.resolve
模块解析可以在模块层被配置, Rule
层面的 resolve
会覆盖顶层的 resolve配置
UseEntry
Rule
传入的形式,通常可以是对象或者一个函数, 一个必选的字符串形式的 loader
和一个可选的 option
函数形式则会接受一个加载模块的对象参数
1 | // 对象形式 |
noParse
不解析所传递的正则表达式匹配到的文件,这里特别注意不匹配的文件不能存在require
和import
1 | module.exports = { |
unsafeCache
缓存模块是否需要解析, 首先得保证缓存开启。缓存未开启,默认为false
。缓存开启,默认会解析node_modules
的模块。
1 | module.exports = { |
Resolve
resolve
的作用在于如何正确的识别模块,找到需要引入bundle
的模块代码
alias
创建别名,使得引入方式更加简单
也可以在给定对象的键后的末尾添加 $
,以表示精准匹配
也可以使用 { '路径': false }
表示忽略路径的模块
resolve.alias 优先级高于其它模块解析方式。
1 | const path = require('path'); |
Optimization
优化,会根据打包模式自动切换配置,也可以手动配置
minimize
开启表示需要压缩,需要配合 TerserPlugin
或其它在 optimization.minimizer
定义的插件压缩 bundle
minimizer
使用自定义压缩工具,覆盖默认压缩工具,通常使用 TerserPlugin
1 | module.exports = { |
函数形式,形参为 compiler
1 | module.exports = { |
splitChunks
默认使用 webpack4
默认的分块策略,具体手动配置参考 splitChunkPlugin
runtimeChunk
runtimeChunk
作用在于将只含有runtime
的入口文件单独打包一个文件, 所谓runtime
就是指异步加载代码如import('./utils') => {}
emitOnErrors
编译时每当有错误时,会被 emit
, 关键错误会被 emit
到代码中
todo