写在前面
其实呢,这个东西也就那样,主要是我们得清楚webpack构建过程中的生命周期钩子,
就拿这个插件来说,我们想要把输出的js文件里面的内容中的console语句去掉,那么我们就需要找到webpack处理完文件时的钩子,然后通过正则表达式替换为空字符串即可
webpack hooks文档
我们就是要在这里找出来我们想要处理的时机,到底是哪个钩子做的事情。
插件的代码本质就是一个类,我们按照webpack的规定去实现内部的apply方法即可
它是node中执行的东西,所以按照CommonJS规范的模块化语法
// 就是实现一个apply方法
class CustomxxxxPLugin {
apply(compiler) {
....
}
}
module.exports = CustomxxxxPLugin;
铺垫的应该很直白,没什么难的东西,直接上代码
.custom-plugin/removeConsolePlugin.js
/*
* 去除代码中的console语句--plugin
*/
const pluginName = 'consoleRemovePlugin';
class RemoveConsolePlugin {
/**
* 参数types 为数组,传入*为所有类型
* ['log', 'info', 'warn', 'error'] === ['*']
* 也可以按需传入
*/
constructor(options) {
if (options.types) {
if (!Array.isArray(options.types)) {
throw new Error('【consoleRemovePlugin】error: types must be an array');
} else {
if (options.types.includes('*')) {
options.types = ['log', 'info', 'warn', 'error'];
}
options.types.forEach(type => {
if (!['log', 'info', 'warn', 'error'].includes(type)) {
throw new Error('【consoleRemovePlugin】error: types must be log, info, warn, error');
}
})
}
} else {
this.options.types = ['log', 'info', 'warn', 'error'];
}
this.options = options;
}
apply(compiler) {
let handler = (assets, compilation) => {
/** 处理正则表达式:用来匹配console.*()和console.*() */
let removedStr = this.options.types.reduce((a, b) => (a + '|' + b));
let reDict = {
1: [RegExp(`\\.console\\.(${removedStr})\\(\\)`, 'g'), ''],
2: [RegExp(`\\.console\\.(${removedStr})\\(`, 'g'), ';('],
3: [RegExp(`console\\.(${removedStr})\\(\\)`, 'g'), ''],
4: [RegExp(`console\\.(${removedStr})\\(`, 'g'), '(']
}
Object.entries(assets).forEach(([filename, source]) => {
let outputContent = source.source();
if (/\.(js|ts|jsx|tsx)/.test(filename)) {
Object.entries(reDict).forEach(([_, value]) => {
outputContent = outputContent.replace(value[0], value[1]);
})
compilation.assets[filename] = {
source: () => outputContent,
size: () => Buffer.byteLength(outputContent, 'utf8')
};
}
})
}
// https://webpack.docschina.org/api/compiler-hooks/#compilation
/**
* compilation钩子
* compilation 创建之后执行
*/
compiler.hooks.compilation.tap(pluginName, compilation => {
// https://webpack.docschina.org/api/compilation-hooks/#processassets
// webpack5的钩子,不使用webpack4
// afterProcessAssets钩子的使用而不是processAssets,
// 是因为webpack包中的sourceMapDevToolPlugin.js使用processAssets钩子,
// 我们的插件会更改source对象,导致sourceMapDevToolPlugin.js插件无法正确使用asset.source
// 具体体现在node_modules/webpack/lib/SourceMapDevToolPlugin.js中getTaskForFile方法
compilation.hooks.afterProcessAssets.tap({
name: pluginName,
}, assets => handler(assets, compilation))
})
}
}
module.exports = RemoveConsolePlugin;
webpack.config.js
中的使用
...
const RemoveConsolePlugin = require('./custom-plugin/consoleRemove');
module.exports = function (webpackEnv) {
...
return {
...
plugins: [
...,
!isEnvDevelopment && new RemoveConsolePlugin({
types: ['log'] // ["*"]
}),
]
}
}
写在最后
如果有帮到大家,就帮博主点个免费的赞,博主会特别开心能帮到大家嘞!