目录
Webpack 2.2 中文文档
如何编写一个插件?
插件向第三方开发者提供了 webpack 引擎中完整的能力。使用阶段式的构建回调,开发者可以引入它们自己的行为到 webpack 构建流程中。创建插件比创建加载器更加高级,因为你将需要理解一些 webpack 底层的内部特性来做相应的勾子,所以做好阅读一些源码的准备!
编译器(Compiler)和编译(Compilation)
在插件开发中最重要的两个资源就是 compiler 和 compilation 对象。理解它们的角色是扩展 webpack 引擎重要的第一步。
- compiler 对象代表了完整的 webpack 环境配置。这个对象在启动 webpack 时被一次性建立,并在所有可操作的设置中被配置,包括原始配置,加载器和插件。当在 webpack 环境中应用一个插件时,插件将收到一个编译器对象的引用。可以使用它来访问 webpack 的主环境。
- compilation 对象代表了一次单一的版本构建和生成资源。当运行 webpack 开发环境中间件时,每当检测到一个文件变化,一次新的编译将被创建,从而生成一组新的编译资源。一个编译对象表现了当前的模块资源、编译生成资源、变化的文件、以及被跟踪依赖的状态信息。编译对象也提供了很多关键点回调供插件做自定义处理时选择使用。
这两个成员是任何 webpack 插件不可或缺的部分(特别是 compilation),如果开发者阅读它们的源码并进行熟悉,将获益匪浅:
基本插件架构
插件都是被实例化的带有 apply 原型方法的对象。这个 apply 方法在安装插件时将被 webpack 编译器调用一次。apply 方法提供了一个对应的编译器对象的引用,从而可以访问到相关的编译器回调。一个简单的插件结构如下:
function HelloWorldPlugin(options) { // 使用配置(options)设置插件实例 } HelloWorldPlugin.prototype.apply = function(compiler) { compiler.plugin('done', function() { console.log('Hello World!'); }); }; module.exports = HelloWorldPlugin;
然后要安装这个插件,只需要在你的 webpack 配置的 plugin 数组中加入一个实例:
var HelloWorldPlugin = require('hello-world'); var webpackConfig = { // ... 这里是其他配置 ... plugins: [ new HelloWorldPlugin({options: true}) ] };
访问编译
使用编译器对象时,你可以绑定提供了编译对象引用的回调拿到每次新的编译对象。这些编译对象提供了构建流程中很多步骤的回调来做勾子。
function HelloCompilationPlugin(options) {} HelloCompilationPlugin.prototype.apply = function(compiler) { // 设置回调来访问编译对象: compiler.plugin("compilation", function(compilation) { // 现在设置回调来访问编译中的步骤: compilation.plugin("optimize", function() { console.log("Assets are being optimized."); }); }); }; module.exports = HelloCompilationPlugin;
关于 compiler 和 compilation 的更多可用的回调和信息,以及其它重要的对象,请参考 插件 文档。
异步编译插件
有一些编译插件中的步骤是异步的,这样要传递一个回调函数,并且在插件运行结束时回调必须被调用。
function HelloAsyncPlugin(options) {} HelloAsyncPlugin.prototype.apply = function(compiler) { compiler.plugin("emit", function(compilation, callback) { // 做一些异步处理…… setTimeout(function() { console.log("Done with async work..."); callback(); }, 1000); }); }; module.exports = HelloAsyncPlugin;
示例
一旦能我们深入理解 webpack 编译器和每个独立的编译,我们依赖 webpack 引擎将有无限多的事可以做。我们可以重新格式化已有的文件,创建衍生的文件,或者制作全新的生成文件。
让我们来写一个简单的示例插件,生成一个叫做 filelist.md 的新文件;文件内容是所有构建生成的文件的列表。这个插件大概像下面这样:
function FileListPlugin(options) {} FileListPlugin.prototype.apply = function(compiler) { compiler.plugin('emit', function(compilation, callback) { // 创建一个头部字符串: var filelist = 'In this build:\n\n'; // 检查所有编译好的资源文件: // 为每个文件名新增一行 for (var filename in compilation.assets) { filelist += ('- '+ filename +'\n'); } // 把它作为一个新的文件资源插入到 webpack 构建中: compilation.assets['filelist.md'] = { source: function() { return filelist; }, size: function() { return filelist.length; } }; callback(); }); }; module.exports = FileListPlugin;
原文:https://webpack.js.org/development/how-to-write-a-plugin/
上一篇: 第三部分:文档-开发 下一篇: 有用的插件模式