CopyWebpackPlugin 将已经存在的单个文件或整个目录复制到构建目录。
准备工作
npm i webpack webpack-cli
创建如下项目目录
├── plugins # 编译打包后的输出目录
├── public # 静态资源
│ │── index.css
│ │── index.html
│ └── reset.css
├── src
│ └── reset.js
├── .gitignore
├── package.json
├── package-lock.json
└── webpack.config.js
代码实现
webpack.config.js
const CopyWebpackPlugin = require('./plugin/CopyWebpackPlugin');
module.exports = {
mode: 'production',
output: {
clean: true,
},
plugins: [
new CopyWebpackPlugin({
form: 'public',
to: 'css',
ignore: ['**/index.html'],
}),
],
};
plugin/CopyWebpackPlugin.js
const { validate } = require('schema-utils');
const globby = require('globby');
const path = require('path');
const schema = {
type: 'object',
properties: {
form: {
type: 'string',
},
to: {
type: 'string',
},
ignore: {
type: 'array',
},
},
additionalProperties: false, // 是否允许不存在的选项传入
};
class CopyWebpackPlugin {
constructor(options = {}) {
// 校验插件options
validate(options, schema, {
name: 'CopyWebpackPlugin',
});
this.options = options;
}
apply(compiler) {
// 获取操作文件的对象
const fs = compiler.outputFileSystem;
// 绑定到 “thisCompilation” 钩子,
// 以便进一步绑定到 compilation 过程更早期的阶段
compiler.hooks.thisCompilation.tap('CopyWebpackPlugin', (compilation) => {
// 绑定到 “additionalAssets” 钩子,为 compilation 创建额外 asset
compilation.hooks.additionalAssets.tapAsync('CopyWebpackPlugin', async (callback) => {
// 1. 获取ignore后的文件 paths
const { form, ignore } = this.options;
// to 默认打包目的根目录
const to = this.options.to ? this.options.to : '.';
// 运行指令的上下文
const { context } = compiler.options;
// 获取 form 的绝对地址
const absoluteForm = path.isAbsolute(form) ? form : path.resolve(context, form);
// 获取 ignore 后的匹配目录文件路径
const paths = await globby(absoluteForm, { ignore });
// 2. 读取 paths 文件内容
const files = paths.map((absolutePath) => {
// 读取文件
const data = fs.readFileSync(absolutePath);
// 获取文件名
const filename = path.basename(absolutePath);
// filename 和 to 结合,获取文件path
const filePath = path.join(to, filename);
return {
data,
filename: filePath,
};
});
// 3. 创建webpack格式的资源,并输入
// webpack 模块实例,可以通过 compiler 对象访问,
// 这样确保使用的是模块的正确版本
// (不要直接 require/import webpack)
const { webpack } = compiler;
// RawSource 是其中一种 “源码”("sources") 类型,
// 用来在 compilation 中表示资源的源码
const { RawSource } = webpack.sources;
// 向 compilation 添加新的资源,
// 这样 webpack 就会自动生成并输出到 output 目录
files.forEach((file) => compilation.emitAsset(file.filename, new RawSource(file.data)));
callback();
});
});
}
}
module.exports = CopyWebpackPlugin;
验证测试
执行 npx webpack
,可以看到打包结果如下,符合期待。
源码:https://gitee.com/yanhuakang/webpack-demos/tree/master/proficient/step_5-CopyWebpackPlugin