Compiler 模块是 Webpack 最核心的模块。每次执行 Webpack 构建的时候,在 Webpack 内部,会首先实例化一个 Compiler 对象,然后调用它的 run 方法来开始一次完整的编译过程。直接使用 Webpack API webpack(options)
的方式得到的就是一个 Compiler 实例化的对象,这时候 Webpack 并不会立即开始构建,需要手动执行 comipler.run()
才可以。
const webpack = require('webpack')
const webpackConfig = require('./webpack.config.js')
// 只传入 config
const compiler = webpack(webpackConfig)
// 开始执行
compiler.run(callback)
// 上面两句等价于
webpack(webpackConfig, callback)
Tips:使用 webpack-dev-server API 方式时,只需要传入 compiler 对象给 dev server 即可,不需要手动执行 compiler.run()
。
如果要手动实例化一个 Compiler 对象,可以通过const Compiler = webpack.Compiler
来获取它的类,一般只有一个父 Compiler,而子 Compiler 可以用来处理一些特殊的事件。
在 Webpack Plugin 中,每个插件都有个 apply
方法。这个方法接收到的参数就是 Compiler 对象,可以通过在对应的钩子时机绑定处理函数来编写插件。
Compiler 钩子
上面的方式只是输出了 compiler.run()
之后的一部分钩子,Compiler 还有很多钩子。比如在 watch
模式下,还会有 watchRun
、watchClose
和 invalid
。
如果要绑定某个钩子,则可以使用下面的方法来绑定:
compiler.hooks.someHook.tap('MyPlugin', (params) => {
/* ... */
})
列举一下对应的关系
Tips:整个 Compiler 完整地展现了 Webpack 的构建流程:
- 准备阶段:make 之前做的事情都属于准备阶段,这阶段的 calback 入参以 compiler 为主
- 编译阶段:这阶段以 compilation 的钩子为主,calback 入参以 compilation 为主
- 产出阶段:这阶段从 compilation 开始,最后回到 Compiler 钩子上,calback 传入参数是跟结果相关的数据,包括 stats、error
Resolver
Compiler 的 Resolver 是指来自于 enhanced-resolve
模块,它主要功能是一个提供异步 require.resolve()
,即从哪里去查找文件的路径,可以通过 Webpack 的 resolve
和 resolveLoader
来配置。Compiler 类有三种类型的内置 Resolver:
- Normal:通过绝对路径或相对路径,解析一个模块
- Context:通过给定的上下文(context)解析一个模块
- Loader:解析一个 webpack loader
thisCompilation 和 compilation
有 thisCompilation
和 compilation
两个钩子其实是跟子编译(child compiler)有关, Compiler 实例通过 createChildCompiler
方法可以创建子编译实例 childCompiler
。创建 childCompiler
时,childCompiler
会复制 compiler
实例的任务点监听器。compilation
的钩子会被复制,而 thisCompilation
钩子则不会被复制。