如何开发webpack plugin
继上回介绍了如何开发webpack loader 之后。趁热打铁,来继续看下webpack另一个核心组成:plugin。
下面也和loader一样,让我们一起从基本的官方文档着手看起。
loader和plugin的差别
- loader : 顾名思义,某种类型资源文件的加载器,作用于某种类型的文件上。webpack本身也是不能直接打包这些非js文件的,需要一个转化器即loader。 loader本身是单一,简单的,不能将多个功能放在一个loader里。
- plugin比loaders更加先进一点,你可以扩展webpack的功能来满足自己的需要,换句话说,loader不能满足的时候,就需要plugin了。
如何开发一个plugin
插件将webpack引擎所有的能力暴露给第三方开发者。通过阶梯式的build回调,开发者可以在webpack编译过程中加入自己的行为。开发插件比loaders更加先进一点,因为你需要理解webpack一些底层构成来添加钩子回调。准备好读一些源码吧。
开发一个插件
一个webpack的插件由以下几方面组成:
- 一个非匿名的js函数
- 在它的原型对象上定义apply方法
- 指明挂载自身的webpack钩子事件
- 操作webpack内部情况的特定数据
- 方法完成时唤起webpack提供的回调
// A named JavaScript function.
function MyExampleWebpackPlugin() {
//
};
// Defines `apply` method in it's prototype.
MyExampleWebpackPlugin.prototype.apply = function(compiler) {
// Specifies webpack's event hook to attach itself.
compiler.plugin('webpacksEventHook', function(compilation /* Manipulates webpack internal instance specific data. */, callback) {
console.log("This is an example plugin!!!");
// Invokes webpack provided callback after functionality is complete.
callback();
});
};
编译器和编译
开发插件过程中最重要的两个对象就是compiler 和compilation。理解他们的职责是扩展webpack功能最重要的第一步
编译器对象就是webpack完整的配置环境。该对象一经webpack开始执行就创建,并且通过所有可操作的设置项来设置,例如options,loaders,和plugins。当在webpack环境中应用一个插件时,该插件将会接受到一个指向该编译器的引用。使用该编译器来访问主要的webpack环境。
compilation对象是一个单独的关于版本资源的创建。当执行webpack 开发中间件时,当一个文件的更改被检测到就会创建一个新的compilation对象,因此产生了一些可被编译的资源。一个compilation展现了一些信息关于当前模块资源状态、编译资源、改变的文件、监视的依赖等信息。同样提供了很多关键的回调,当插件扩展自定义行为时
这两个组件是webpack 插件必需的组成部分(特别是compilation),所以开发者如果熟悉下面这些源文件将会获益不小。
插件的基本结构
插件是在原型中带有一个apply方法的实例化对象,当安装插件的时候,这个apply方法就会被webpack调用一次。apply方法提供一个指向当前活动的webpack compiler的引用,该引用允许访问compiler的回调。一个简单的插件结构如下:
function HelloWorldPlugin(options) {
// Setup the plugin instance with options...
}
HelloWorldPlugin.prototype.apply = function(compiler) {
compiler.plugin('done', function() {
console.log('Hello World!');
});
};
module.exports = HelloWorldPlugin;
然后安装一个插件,仅仅需要在你的 webpack config 中plugins对应的数组中,增加一个插件的实例即可
var HelloWorldPlugin = require('hello-world');
var webpackConfig = {
// ... config settings here ...
plugins: [
new HelloWorldPlugin({options: true})
]
};
访问编译
通过使用编译器对象,你可能会绑定提供指向每个新的compilation应用的回调。这些compilations提供了编译过程中很多步骤的回调函数。
function HelloCompilationPlugin(options) {}
HelloCompilationPlugin.prototype.apply = function(compiler) {
// Setup callback for accessing a compilation:
compiler.plugin("compilation", function(compilation) {
// Now setup callbacks for accessing compilation steps:
compilation.plugin("optimize", function() {
console.log("Assets are being optimized.");
});
});
};
module.exports = HelloCompilationPlugin;
如果想了解更多关于在编译器、编译中哪些回调是可用的和其他一些更重要的对象,轻戳plugin文档
异步插件
一些编译插件步骤是异步的并且提供了一个当你的插件结束编译时必须调用的回调方法
function HelloAsyncPlugin(options) {}
HelloAsyncPlugin.prototype.apply = function(compiler) {
compiler.plugin("emit", function(compilation, callback) {
// Do something async...
setTimeout(function() {
console.log("Done with async work...");
callback();
}, 1000);
});
};
module.exports = HelloAsyncPlugin;
示例
一旦我们打开了webpack编译器和每个单独编译的大门,我们可以使用引擎做的事情是无限可能的。我们可以重新格式化存在的文件、创建派生文件、完全伪造一个新文件
让我们写个简单的示例插件,目的是生成一个新的名字为filelist.md的文件。内容如下:列出构建过程中所有的生成文件。这个插件大概如下:
function FileListPlugin(options) {}
FileListPlugin.prototype.apply = function(compiler) {
compiler.plugin('emit', function(compilation, callback) {
// Create a header string for the generated file:
var filelist = 'In this build:\n\n';
// Loop through all compiled assets,
// adding a new line item for each filename.
for (var filename in compilation.assets) {
filelist += ('- '+ filename +'\n');
}
// Insert this list into the webpack build as a new file asset:
compilation.assets['filelist.md'] = {
source: function() {
return filelist;
},
size: function() {
return filelist.length;
}
};
callback();
});
};
module.exports = FileListPlugin;
不同类型的插件
插件可以依据其注册的事件来分成不同的类型,每个事件钩子决定了在触发时如何调用该插件。
同步类型
这种类型的实例使用如下方式来调用插件
applyPlugins(name: string, args: any...)
applyPluginsBailResult(name: string, args: any...)
这意味着每一个插件的回调将伴随特定参数args依次被调用。对插件而言这是最简单的格式。很多有用的事件例如"compile", "this-compilation",是期望插件同步执行的。
流式类型
waterfall Plugins 通过下面的方式调用
applyPluginsWaterfall(name: string, init: any, args: any...)
异步类型
当所有的插件被使用下面的方法异步调用的时候,即为异步插件
applyPluginsAsync(name: string, args: any..., callback: (err?: Error) -> void)
插件控制方法被调用,参数是所有的args和带有这种标志(err?: Error) -> void的回调。handler方法按照注册回调在所有handlers被调用之后的顺序来调用。对于"emit", "run"事件来说这是很常用的模式。
异步流
这种插件将按照流失方式来被异步使用
applyPluginsAsyncWaterfall(name: string, init: any, callback: (err: Error, result: any) -> void)
这种插件的handler被调用时,参数是当前value和带有这种标志(err?: Error) -> void的回调。当被调用时,nextValue是下一个handler的当前值。第一个handler的当前值是init。所有的handler被调用之后,最后一个值将会被赋给回调。如果有的handler传递了一个err的值,回调将会接受err,并且不会有其他handler被第阿勇。这种插件模式使用与于"before-resolve" and "after-resolve"之类的事件。
异步系列
这种和异步插件很相似,不同在于如果有点插件注册失败,将不会调用任何插件
applyPluginsAsyncSeries(name: string, args: any..., callback: (err: Error, result: any) -> void)
结束语
至此,如何开发一个基本的webpack plugin 我相信大家已经知道了,如果还不太清楚的话,可以移步w-loader查看。
另外,对于我这种英语渣渣来说,翻译起来确实难度蛮大的。此处抛砖引玉,希望大家共同探讨学习。
此文为原创文章,转载请注明出处!
如何开发webpack plugin的更多相关文章
- 简单webpack plugin 开发
重要是学习下怎么开发webpack plugin,同时记录下 插件模型 webpack 是一个插件,可以是javascript class ,或者具名 class 定义apply 方法 指定一个绑定到 ...
- YYDS: Webpack Plugin开发
目录 导读 一.cdn常规使用 二.开发一个webpack plugin 三.cdn优化插件实现 1.创建一个具名 JavaScript 函数(使用ES6的class实现) 2.在它的原型上定义 ap ...
- 揭秘webpack plugin
前言 Plugin(插件) 是 webpack 生态的的一个关键部分.它为社区提供了一种强大的方法来扩展 webpack 和开发 webpack 的编译过程.这篇文章将尝试探索 webpack plu ...
- vue(9)—— 组件化开发 - webpack(3)
前面两个终于把webpack相关配置解析完了.现在终于进入vue的开发了 vue组件化开发预热 前期准备 创建如下项目: app.js: footer.js: main.js: webpack.con ...
- vue(8)—— 组件化开发 - webpack(2)
webpack的常用loder和插件 loder和插件是什么,现在暂且不表,看到后面你就懂了 引入css问题 直接用link标签导入css 在前面的 vue(7)—— 组件化开发 — webpack( ...
- Webpack Plugin
[Webpack Plugin] Since Loaders only execute transforms on a per-file basis, plugins are most commonl ...
- 案例实战之如何写一个webpack plugin
案例实战之如何写一个webpack plugin 1.写一个生成打包文件目录的file.md文件 // 生成一个目录项目目录的文件夹 class FileListPlugin { constructo ...
- 开发 IDEA Plugin 引入探针,基于字节码插桩获取执行SQL
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 片面了! 一月三舟,托尔斯泰说:"多么伟大的作家,也不过就是在书写自己的片 ...
- 如何开发webpack loader
关于webpack 作为近段时间风头正盛的打包工具,webpack基本占领了前端圈.相信你都不好意思说不知道webpack. 有兴趣的同学可以参考下我很早之前的webpack简介 . 确实webpac ...
随机推荐
- Java单元测试之覆盖率统计eclemma
安装 有两种安装方法 下载安装(推荐) 地址: http://sourceforge.net/projects/eclemma/ 将解压后的features和plugins目录下的文件分别拷贝到Ecl ...
- 【Alpha】Daily Scrum Meeting——Day5
站立式会议照片 1.本次会议为第五次Meeting会议: 2.本次会议在上午大课间09:40,在陆大楼召开,本次会议为30分钟讨论昨天的任务完成情况以及接下来的任务安排. 燃尽图 每个人的工作分配 成 ...
- Python[小甲鱼003小插曲之变量和字符串]
>>>teacher = 3 >>>teacher 3 #在定义了一个变量后可以之间输入整个变量即可访问这个变量. >>> teache ...
- python实例编写(4)--js,滚动条,cookie,验证码,获取特定属性的元素,实现原理
一.调用js 执行方法:execute_script(script,*args) 场景一:在页面上直接执行调用js 场景二:在定位的某个元素上执行调用js 如:掩藏文字(提示插件 tooltip设置淡 ...
- getOutputStream() has already been called for this response
错误日志里偶尔会有getOutputStream() has already been called for this response这个错误 最近发现了高概率复现条件,所以顺手解决了一下: 首先根 ...
- PHP垃圾回收机制理解
使用的是"引用计数"方式进行回收.简单地理解的话,就是每个分配的内存区域都有一个计数器,记录有多少个变量指针指向这片内存.当指向该片内存的指针数量为0,那么该片内存区域就可以被回收 ...
- MX4拍摄视频转码方法
问题 使用魅族4手机拍摄的视频,其视频编码是H.265 目前大多数设备不支持解码,表现为常用播放器无法正常播放视频,剪辑软件无法剪辑视频. 解决方案 使用软件进行转码,期间尝试软件如下: 爱剪辑 部分 ...
- zookeeper环境搭建及使用
本文只讲解搭建步骤,先不讲原理相关知识 一.zookeeper下载地址 本文使用版本为zookeeper-3.4.10.tar.gz 地址:http://mirrors.shuosc.org/apac ...
- 云计算之openstack ocata 项目搭建详细方法
之前写过一篇<openstack mitaka 配置详解>然而最近使用发现阿里不再提供m版本的源,所以最近又开始学习ocata版本,并进行总结,写下如下文档 OpenStack ocata ...
- Maven在Windows中的配置以及IDE中的项目创建
Maven在Windows下的配置 1.Maven下载地址:http://maven.apache.org/download.cgi,下载红框里的版本即可. 2.解压到D盘: 3.修改配置文件sett ...