webpack 是个很强大的构建工具,其丰富灵活的配置决定了使用也不简单。在面试中经常能遇到 webpack 相关的问题,如果平常只是使用脚手架如 vue-cli 而没有好好深入学习研究 webpack 的话,估计答不上什么。我相信,如果没有深入了解,部分面试官也问不出什么。可能也就变成了两个人侃侃如何配置出入口,常见的 loader,plugin 有哪些。
作为一名多年油条前端,一直没有正视 webpack 相关知识,面对 webpack 相关的面试题更是一问三不知。这次准备好好学习研究 webpack相关内容,并且将学习内容记录成 webpack 系列,希望可以让不了解 webpack 的小白能对其有所掌握。
编写一个插件
插件向第三方开发者提供了 webpack 引擎中完整的能力。专注处理 webpack 在编译过程中的某个特定任务的功能模块,可以称为插件。
创建插件
webpack 插件由以下组成:
-
一个 Javascript 命名函数
-
在插件函数的 prototype 上定义一个 apply 方法
-
指定一个绑定到 webpack 自身的事件钩子
-
处理 webpack 内部实例的特定数据
-
功能完成之后调用 webpack 提供的回调
// 一个 JavaScript 命名函数。
function MyExampleWebpackPlugin() {
};
// 在插件函数的 prototype 上定义一个 `apply` 方法。
MyExampleWebpackPlugin.prototype.apply = function(compiler) {
// 指定一个挂载到 webpack 自身的事件钩子。
compiler.plugin('webpacksEventHook', function(compilation /* 处理 webpack 内部实例的特定数据。*/, callback) {
console.log("This is an example plugin!!!");
// 功能完成后调用 webpack 提供的回调。
callback();
});
};
Compiler 和 Compilation
在插件开发中最重要的两个资源就是 compiler 和 compilation 对象。插件的主要功能就是根据 compiler 和 compilation 得到当前配置项及编辑状态,再通过 compiler 及 compilation 给出的钩子参与编译过程。
-
compiler 对象代表了完整的 webpack 环境配置。这个对象在启动 webpack 时被一次性建立,并配置好所有可操作的设置,包括 options,loader 和 plugin。当在 webpack 环境中应用一个插件时,插件将收到此 compiler 对象的引用。可以使用它来访问 webpack 的主环境。
-
compilation 对象代表了一次资源版本构建。当运行 webpack 开发环境中间件时,每当检测到一个文件变化,就会创建一个新的 compilation,从而生成一组新的编译资源。一个 compilation 对象表现了当前的模块资源、编译生成资源、变化的文件、以及被跟踪依赖的状态信息。compilation 对象也提供了很多关键时机的回调,以供插件做自定义处理时选择使用。
开发插件的核心就在于运用这个两个对象,其源码在
-
Compiler Source
-
Compilation Source
基本插件架构
插件是由「具有 apply 方法的 prototype 对象」所实例化出来的。这个 apply 方法在安装插件时,会被 webpack compiler 调用一次。apply 方法可以接收一个 webpack compiler 对象的引用,从而可以在回调函数中访问到 compiler 对象。一个简单的插件结构如下:
function HelloWorldPlugin(options) {
// 使用 options 设置插件实例……
}
HelloWorldPlugin.prototype.apply = function(compiler) {
// 相当于在Done钩子中注册函数
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})
]
};
访问 compilation 对象
使用 compiler 对象时,你可以绑定提供了编译 compilation 引用的回调函数,然后拿到每次新的 compilation 对象。这些 compilation 对象提供了一些钩子函数,来钩入到构建流程的很多步骤中。
function HelloCompilationPlugin(options) {}
HelloCompilationPlugin.prototype.apply = function(compiler) {
// 设置回调来访问 compilation 对象:
compiler.plugin("compilation", function(compilation) {
// 现在,设置回调来访问 compilation 中的步骤:
compilation.plugin("optimize", function() {
console.log("Assets are being optimized.");
});
});
};
module.exports = HelloCompilationPlugin;
异步编译插件
一些异步钩子需要额外使用 callBack 回调函数
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;
示例
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;
欢迎到前端菜鸟群一起学习交流~516913974
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!