本文目的,实现一个可以移除项目中 console.log
的 webpack 插件。
本来以为比较简单,但还是花了我一个上午的时间。
首先,我们需要初始化环境
yarn init -y
yarn add webpack webpack-cli -D
webpack.config.js 配置如下:
module.exports = {
entry: './index.js',
plugins: []
}
根目录下新建一个 index.js
,内容如下:
console.log('hello world');
在 package.json 添加 build
命令
"scripts": {
"build": "yarn webpack"
}
此时我们运行 yarn build
就会在 dist 目录打包出一个 main.js。我们使用 node 执行这个文件就会输出 hello world
node dist/main.js
如果成功输出,就说明环境已经配置好了。
切换到 webpack.config.js 我们新建一个类,作为我们的自定义 Plugin。
class RemoveLogs {
constructor(options) {
this.options = options
}
apply(compiler) {
console.log("Hello from the custom plugin")
};
}
module.exports = {
entry: './index.js',
plugins: [ new RemoveLogs()]
}
此时再运行 yarn build
,你会在控制台看到 Hello from the custom plugin
这句话。这说明我们的自定义 Plugin 已经添加成功了。
我们接下来要做的,就是把我们代码里的 console.log
语句去掉,我们可以选择很多时机来做这件事。比如在即将开始编译的时候,而我们这里选择放在编译结束之后。
class RemoveLogs {
constructor(options) {
this.options = options
}
apply(compiler) {
compiler.hooks.done.tap("RemoveLogs", stats => {
console.log('我将要移除所有的 console')
removeAllLogs(stats)
});
};
}
compiler.hooks.done
类似于我们 DOM 操作中的 document.addEventListener('click', ()=>{})
。也就是说我们想在编译结束后要做什么事。这个函数的第一个参数是字符串,这里是 RemoveLogs
。它在调试的时候比较有用,你可以随便起名,并不需要一定要对应 class 名。
接下来我们完善 removeAllLogs
这个函数就好了
removeAllLogs(stats) {
const { path, filename } = stats.compilation.options.output;
let filePath = path + "/" + filename;
fs.readFile(filePath, "utf8", (err, data) => {
const rgx = /console.log\(['|"](.*?)['|"]\)/;
const newData = data.replace(rgx, "");
if (err) console.log(err);
fs.writeFile(filePath, newData, function (err) {
if (err) {
return console.log(err)
}
console.log("Logs Removed");
});
});
}
但是此时运行会报错,因为这个时候的 filename 获取到的是一个替代值,具体来说,是字符串 '[name]',我们还需要加一个来获取此时真实的 filename。
compiler.hooks.compilation.tap('GetFileNamePlugin', compilation => {
compilation.hooks.chunkIds.tap('GetFileNamePlugin', (c) => {
this.filename = Array.from(c)[0].name
});
});
此时我们的 removeAllLogs
也相应改变获取 filePath 的方式:
let filePath = (path + "/" + filename).replace(/\[name\]/g, this.filename);
这样,我们就实现完毕了。试着运行 node dist/main.js
。会发现我们已经没有任何输出了。
全部代码如下:
const fs = require('fs')
class RemoveLogs {
constructor(options) {
this.options = options
}
apply(compiler) {
console.log(compiler.options.output);
compiler.hooks.done.tap("RemoveLogs", stats => {
try {
this.removeAllLogs(stats);
} catch (e) {
console.log(e);
}
});
compiler.hooks.compilation.tap('HelloCompilationPlugin', compilation => {
compilation.hooks.chunkIds.tap('HelloCompilationPlugin', (c) => {
this.filename = Array.from(c)[0].name
});
});
};
removeAllLogs(stats) {
const { path, filename } = stats.compilation.options.output;
let filePath = (path + "/" + filename).replace(/\[name\]/g, this.filename);
try {
fs.readFile(filePath, "utf8", (err, data) => {
const rgx = /console.log\(['|"](.*?)['|"]\)/;
const newData = data.replace(rgx, "");
if (err) console.log(err);
fs.writeFile(filePath, newData, function (err) {
if (err) {
console.log(err)
}
console.log("all logs Removed");
});
});
} catch (e) {
console.error(e)
}
}
}
module.exports = {
entry: './index.js',
plugins: [new RemoveLogs()]
}
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!