现在制作一个插件,它会在打包的时候将LICENSE放到目的文件夹中。
准备工作
假设node环境已经到位。
现在从零开始,一步一步实现我的小目标。
-
搭建空白项目
# 下面我们的一切都将在这个目录下进行 mkdir diy-plugins-loaders cd diy-plugins-loaders # 初始化工程 npm init # 安装webpack依赖 npm i -D webpack webpack-cli # 新建目录 mkdir src && mkdir build && mkdir plugins && mkdir loaders echo console.log('hello') >> src/index.js echo "this is a license" > LICENSE
-
配置webpack.config.js
再也没有比这个更简单的配置了const { resolve } = require('path') module.exports = { entry: resolve(__dirname, "./src/index.js"), output: { path: resolve(__dirname, "./build"), filename: "bundle.js" }, plugins: [], module: { rules: [] }, mode: 'development' }
- 添加快捷指令
修改 package.json
"scripts": { "dev": "webpack --mode development", "build": "webpack --mode production" }
- 好了,现在我们可以使用以下命令进行打包了
- 开发模式: npm run dev
- 生产模式: npm run build
-
这个简单的工程目录如下:
- build - node_modules - package.json - plugins - loaders - src - index.js - LICENSE
简单的分析
我们的插件要做的事情是,将传入的license文件,打包到打包目录中。
简单点说,就是用nodejs复制一个文件。
- 现在我们关注几个事情:
- 该如何让webpack调用我们的plugin
- 插件该如何获取传入的文件路径
- 插件该如何获取输出的打包路径
如何让webpack调用plugin
首先,以html-webpack-plugin为例,我们来看看是怎样使用其它的插件的
-
下载插件
npm i -D html-webpack-plugin -
在webpack.config.js中导入插件
const HtmlWebpackPlugin = require(‘html-webpack-plugin’) -
在webpack.config.js中使用插件
module.exports = { ... plugins: [ new HtmlWebpackPlugin() ], ... }
再参考官方文档
所谓插件显然就是一个类,这个类拥有一个apply方法,大部分功能实现都在这里面进行。
现在,我们来做一个插件,这个插件什么都不做,只输出一个打印语句。
我们约定,把所有的插件代码放到plugins
文件夹下。
- 新建0.createLicense.js,内容如下:
class CreateLicensePlugin { constructor(options = {}) { } apply(compiler) { console.log('这是一个自定义插件'); } } module.exports = CreateLicensePlugin;
-
在webpack.config.js中导入我们自己写的插件
const CreateLicensePlugin = require(‘./plugins/0.createLicense’) -
在webpack.config.js中配置使用我们的插件
module.exports = { ... plugins: [ new CreateLicensePlugin() ], ... }
接下来,npm run build,你会发现会有插件的log输出。
如何获取传入的文件路径
这个问题其实比较简单。
配置的时候不是先new一个实例化插件对象吗,我们在插件类的构造函数中接收参数即可。
如何获取输出的打包路径
在官网的示例中,我们可以看到插件的apply是传递了一个compiler参数的,这个compiler有两个重要属性。
const { hooks, options } = compiler;
顾名思义,
- hooks是编译过程中各个状态的钩子集合,这个官网有详细解释compiler-hooks。
这里我们选done这一状态hook。
如果你需要详细了解hook的状态和时机,官方是建议看源码:To learn this, search for hooks.< hook name>.call across the webpack source
- options,也就是配置的意思。要配置当然从这里面拿。
最终实现
/*
该插件用于将licensePath的文件输出到输出目录下License.txt, 用法如下:
plugins: [
...,
new CreateLicensePlugin({
licensePath: './LICENSE'
}),
],
*/
const pluginName = 'CreateLicensePlugin';
const fs = require("fs");
const { resolve } = require("path");
class CreateLicensePlugin {
//在构造函数里面接收配置参数
constructor(options = {}) {
this.licensePath = options.licensePath || './LICENSE'
}
apply(compiler) {
const { hooks, options } = compiler;
const outputPath = options.output.path
// 当全部完毕后执行
hooks.done.tap(pluginName, () => {
// 将LICENSE复制到目标文件夹
if (fs.existsSync(this.licensePath)) {
const output = resolve(outputPath, 'LICENSE.txt')
console.log(outputPath);
console.log(output);
const data = fs.readFileSync(this.licensePath);
fs.writeFileSync(output, data)
} else {
console.error(`${this.licensePath} is not exist!`)
}
});
}
}
module.exports = CreateLicensePlugin;
源代码
https://github.com/nicennnnnnnlee/webpack-plugin-loader-examples