/**
* webpack插件开发采用'动态原型模式'
* 插件开发,最重要的两个对象:compiler、compilation
* @param options
* @constructor
*/
function MyPlugin(options) {
// 根据 options 配置你的插件
}
// 我们可以在原型上添加一些方法
MyPlugin.prototype.someFunc = function() {
/*something*/
};
// apply方法是必须要有的,因为当我们使用一个插件时(new somePlugins({})),webpack会去寻找插件的apply方法并执行
MyPlugin.prototype.apply = function(compiler) {
// compiler是什么?compiler是webpack的'编译器'引用
// compiler.plugin('***')和compilation.plugin('***')代表什么?
// document.addEventListener熟悉吧?其实是类似的
// compiler.plugin('***')就相当于给compiler设置了事件监听
// 所以compiler.plugin('compile')就代表:当编译器监听到compile事件时,我们应该做些什么
// compile('编译器'对'开始编译'这个事件的监听)
compiler.plugin('compile', function(params) {
console.log('The compiler is starting to compile...');
});
// compilation('编译器'对'编译ing'这个事件的监听)
compiler.plugin('compilation', function(compilation) {
console.log('The compiler is starting a new compilation...');
// 在compilation事件监听中,我们可以访问compilation引用,它是一个代表编译过程的对象引用
// 我们一定要区分compiler和compilation,一个代表编译器实体,另一个代表编译过程
// optimize('编译过程'对'优化文件'这个事件的监听)
compilation.plugin('optimize', function() {
console.log('The compilation is starting to optimize files...');
});
});
// emit('编译器'对'生成最终资源'这个事件的监听)
compiler.plugin('emit', function(compilation, callback) {
console.log('The compilation is going to emit files...');
// compilation.chunks是块的集合(构建后将要输出的文件,即编译之后得到的结果)
compilation.chunks.forEach(function(chunk) {
// chunk.modules是模块的集合(构建时webpack梳理出的依赖,即import、require的module)
// 形象一点说:chunk.modules是原材料,下面的chunk.files才是最终的成品
chunk.modules.forEach(function(module) {
// module.fileDependencies就是具体的文件,最真实的资源【举例,在css中@import("reset.css"),这里的reset.css就是fileDependencie】
module.fileDependencies.forEach(function(filepath) {
// 到这一步,就可以操作源文件了
});
});
// 最终生成的文件的集合
chunk.files.forEach(function(filename) {
// source()可以得到每个文件的源码
var source = compilation.assets[filename].source();
});
});
// callback在最后必须调用
callback();
});
};
// 以上compiler和compilation的事件监听只是一小部分,详细API可见该链接http://www.css88.com/doc/webpack2/api/plugins/
module.exports = MyPlugin;
Webpack 核心的两个模块即是 Loaders 与 Plugins,Loaders 负责载入各种各样的资源、样式与脚本文件,而 Plugins 负责对载入的文件进行处理并且最终输出到编译后的文件中。加载器可以串联。可以通过管道来处理资源,最后一个加载器需要输出为 JavaScript,中间别的加载器可以输出任意的格式到下一个加载器。
加载器是把一个资源文件作为入参转换为另一个资源文件的 node.js 函数。例如,可以通过加载器来让 webpack 来加载 CoffeeScript 或 JSX 文件。加载器的基本使用如下所示:
module.exports = {
entry: "./entry.js",
output: {
path: __dirname,
filename: "bundle.js"
},
module: {
loaders: [
{test: /\.css$/, loader: "style!css" },
{test: /\.js$/, exclude: /node_modules/, loader: 'babel?stage=0'}
]
}
};
安装加载器一般直接可以通过npm
进行安装:
$ npm install xxx-loader --save
$ npm install xxx-loader --save-dev
虽然不是强制要求,但惯例把加载器命名为 XXX-loader,其中 XXX 就是加载器的名字,如:json-loader。可以通过全称(实际的名称)来引用加载器(如 json-loader),也可以通过简略名来引用(如 json)。加载器的命名惯例和搜索优先级是通过 webpack 的配置 api resolveLoader.moduleTemplate 来指定的。
可以通过 require 语句(或 define、require.ensure 等)来指定加载器,只需要用 ! 来分隔资源即可,每部分都是相对当前目录。
require("./loader!./dir/file.txt");
// => 使用当前目录下的 "loader.js" 来转换 "dir" 目录下的 "file.txt" 文件
require("jade!./template.jade");
// => 使用 "jade-loader" (通过 npm 安装在 "node_modules" 目录)来转换 "template.jade" 文件
require("style!css!less!bootstrap/less/bootstrap.less");
// => 通过 github 来安装在 "node_modules" 目录下的 "bootstrap" 模块里的 "less" 目录里的 "bootstrap.less"
// 文件会先被 "less-loader" 转换,然后再被 "css-loader" 转换,最后被 "style-loader" 转换
可以通过正则来在配置文件中绑定加载器:
{
module: {
loaders: [
{ test: /\.jade$/, loader: "jade" },
// => "jade" loader is used for ".jade" files
{ test: /\.css$/, loader: "style!css" },
// => "style" and "css" loader is used for ".css" files
// Alternative syntax:
{ test: /\.css$/, loaders: ["style", "css"] }
]
}
}
通过 CLI 扩展参数来绑定加载器
$ webpack --module-bind jade --module-bind 'css=style!css'
上述命令给 .jade
文件绑定了 jade
加载器,给 .css
文件班定了 style
和 css
加载器。
在使用 Loader 时可以通过查询 web 风格的字符串来指定查询参数,如:url-loader?mimetype=image/png
。查询字符串的格式要看加载器,具体格式参考加载器文档。大多数的加载器支持普通的查询格式(?key=value&key2=value2)和 JSON 对象(?{"key":"value","key2":"value2"})。
require
require("url-loader?mimetype=image/png!./file.png");
{ test: /\.png$/, loader: "url-loader?mimetype=image/png" }
或
{
test: /\.png$/,
loader: "url-loader"
query: { mimetype: "image/png" }
}
webpack --module-bind "png=url-loader?mimetype=image/png"
npm install babel-loader --save-dev
在配置文件中:
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel'
}
]
}
直接使用 npm 命令安装即可:
$ npm install eslint-loader
在 Webpack 的配置文件中,需要进行以下修正:
module.exports = {
// ...
module: {
loaders: [
{ test: /\.js$/, loader: 'eslint-loader', exclude: /node_modules/ }
]
} // ...
};
如果使用了其他的编译器,譬如 babel-loader
时候,务必要注意 loaders 中的顺序,否则文件可能会在经过 Babel 处理之后再进行格式检查。
module.exports = {
// ...
module: {
loaders: [
{
test: /\.js$/,
loaders: ['babel-loader', 'eslint-loader'],
exclude: /node_modules/
}
]
} // ...
};
安全起见,你可以考虑在preLoaders
部分来进行源文件的检查,而不会影响其他的加载器:
module.exports = {
// ...
module: {
preLoaders: [
{ test: /\.js$/, loader: 'eslint-loader', exclude: /node_modules/ }
]
} // ...
};