webpack5-手撸RemoveConsolePlugin插件

写在前面

其实呢,这个东西也就那样,主要是我们得清楚webpack构建过程中的生命周期钩子,

就拿这个插件来说,我们想要把输出的js文件里面的内容中的console语句去掉,那么我们就需要找到webpack处理完文件时的钩子,然后通过正则表达式替换为空字符串即可

webpack hooks文档

我们就是要在这里找出来我们想要处理的时机,到底是哪个钩子做的事情。

插件的代码本质就是一个类,我们按照webpack的规定去实现内部的apply方法即可

它是node中执行的东西,所以按照CommonJS规范的模块化语法

javascript 复制代码
// 就是实现一个apply方法
class CustomxxxxPLugin {
  apply(compiler) {
  ....
  }
}

module.exports = CustomxxxxPLugin;

铺垫的应该很直白,没什么难的东西,直接上代码

.custom-plugin/removeConsolePlugin.js

javascript 复制代码
/*
 * 去除代码中的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中的使用

javascript 复制代码
...
const RemoveConsolePlugin = require('./custom-plugin/consoleRemove');
module.exports = function (webpackEnv) {
  ...
  return {
    ...
    plugins: [
		...,
		!isEnvDevelopment && new RemoveConsolePlugin({
	        types: ['log'] // ["*"]
	    }),
    ]
  }
}

写在最后

如果有帮到大家,就帮博主点个免费的赞,博主会特别开心能帮到大家嘞!

相关推荐
萧行之1 小时前
可视化技术复盘:从图形语法看 D3、Vega-Lite、ECharts、Observable Plot
前端·学习·数据可视化
尾善爱看海9 小时前
Vue 面试收官篇:SSR、性能优化落地、30 道高频面试题精讲(附标准答案)
前端·javascript·vue.js·面试·vue
驳是9 小时前
一个组件,提升 react-router 开发的幸福感
前端·preact
GreenTea9 小时前
OpenAI Agents API 上手实测:一次调用把整个 agent loop 甩给 OpenAI
前端·后端·算法
星云API技术支持9 小时前
企业微信二次开发:群权限设置、成员管理与群资料维护的接口组合实践
java·前端·企业微信
京东云开发者10 小时前
81.8 秒的视频,我们改了 15 个版本:一次纯 Codex 驱动的 AI-native 视频实践
前端·aigc
Csvn10 小时前
TypeScript 大型项目架构:从单体 tsconfig 到分层可扩展的工程
前端
计算机魔术师12 小时前
Dario Amodei 发文呼吁为前沿 AI 降速并提出三点计划
前端
计算机魔术师12 小时前
OpenAI的AI代理偷偷给RubyGems下毒,我们却毫无察觉
前端
甲维斯12 小时前
0代码,0建模,3句话开发一个3D游戏!
前端·游戏·游戏开发