「这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战」。
前言
接上一篇章《webpack plugin从入门都入门》,带大家从4个常用Class(SyncHook
、SyncBailHook
、AsyncParallelHook
、 AsyncSeriesHook
)去了解tapable的常规用法。本文将会从webpack plugin的基本架构开展,介绍compiler与compilation。
写一个 webpack plugin 的基本架构
插件需要封装成class,当webpack安装插件时,会对class进行实例化,并调用实例下的apply
方法。调用apply
方法时候,会把compiler
对象作为参数的形式传入,compiler
是webpack底层编译对象的引用,开发者可以在apply
方法实现中使用compiler
。
引用官方的代码片段如下:
class HelloCompilationPlugin {
apply(compiler) {
// 指定一个挂载到 compilation 的钩子,回调函数的参数为 compilation 。
compiler.hooks.compilation.tap('HelloCompilationPlugin', (compilation) => {
// 现在可以通过 compilation 对象绑定各种钩子
console.log('现在可以通过 compilation 对象绑定各种钩子')
compilation.hooks.optimize.tap('HelloCompilationPlugin', () => {
console.log('资源已经优化完毕。');
});
});
}
}
module.exports = HelloCompilationPlugin;
复制代码
tips: 代码片段中的tap
方法,是不是让你回想起tapable的注册同步消费者。
让HelloCompilationPlugin
运行起来
|- plugins
|- HelloCompilationPlugin.js
|- src
|- index.js
|- webpack.config.js
复制代码
其中HelloCompilationPlugin.js
内容如上文,index.js
如下:
console.log('hello webpack plugin');
复制代码
webpack.config.js
内容如下:
const HelloCompilationPlugin = require('./plugins/HelloCompilationPlugin')
module.exports = {
mode: 'development',
plugins: [
new HelloCompilationPlugin({})
]
}
复制代码
安装webpack
与webpack-cli
依赖:
yarn add -D webpack webpack-cli
或
npm i -D webpack webpack-cli
复制代码
安装完成后执行:
./node_modules/webpack/bin/webpack.js
复制代码
在不指定配置文件路径的情况下,webpack cli
会默认使用执行目录根目录webpack.config.js
作为执行配置。在不配置entry
的情况下,默认用src/index.js
作为编译打包入口,在不配置output的情况下默认使用dist
目录作为打包产物的输出目录。
执行结果如下:
现在可以通过 compilation 对象绑定各种钩子
资源已经优化完毕。
asset main.js 1.21 KiB [compared for emit] (name: main)
./src/index.js 36 bytes [built] [code generated]
webpack 5.69.1 compiled successfully in 85 ms
复制代码
从控制台输出可得:
调用compiler.hooks.compilation.tap
注册的同步钩子消费者被执行了。
调用compilation.hooks.optimize.tap
注册的同步钩子消费者被执行了。
注册异步消费者
与上一篇章《webpack plugin从入门都入门》的tapable
模块类似,因为Compiler
和 Compilation
类都继承了 Tapable
类。也是使用tapAsync
与tapPromise
。这里不展开描述,详情可以见官方文档。
compiler 和 compilation 具体是什么
compiler 和 compilation 是 webpack 打包构建过程中的核心对象,记录着打包的关键信息,并提供打包流程中对应的钩子供开发者在plugin中使用。
compiler
Compiler
类的实例,webpack 从开始执行到结束,Compiler
只会实例化一次。compiler 对象记录了 webpack 运行环境的所有的信息,插件可以通过它获取到 webpack 的配置信息,如entry、output、module
等配置。
compilation
Compilation
类实例,提供了 webpack 大部分生命周期Hook API供自定义处理时做拓展使用。一个 compilation 对象记录了一次构建到生成资源过程中的信息,它储存了当前的模块资源、编译生成的资源、变化的文件、以及被跟踪依赖的状态信息。
简单来说,Compilation
的职责就是对所有 require 图(graph)中对象的字面上的编译,编译构建 module 和 chunk,并调用插件构建过程,同时把本次构建编译的内容全存到内存里。compilation 编译可以多次执行,如在watch模式下启动 webpack,每次监测到源文件发生变化,都会重新实例化一个compilation对象,从而生成一组新的编译资源对象。这个对象可以访问所有的模块和它们的依赖。
总结
这篇文章在读者对tapable有一定印象的前提下。重点解释compiler
与compilation
的概念与实践架构。
compiler
对象记录着构建过程中 webpack
环境与配置信息,整个 webpack
从开始到结束的生命周期。针对的是webpack。
compilation
对象记录编译模块的信息,只要项目文件有改动,compilation
就会被重新创建。针对的是随时可变的项目文件。
下一篇最终篇将会介绍 plugin 的其他 API,并用添加 plugin 开发的示例来深入阐述webpack plugin。