出处:掘金
原作者:海石
console.log 的弊端
导致内存泄露
在控制台可以展开对象,本应该需要回收的对象无法被回收
即使不打开控制台,浏览器仍需保留对其的引用,因为我们任何时刻打开控制台,都能看到之前的 console,并且可操作(展开对象)
影响性能
会占用内存和 CPU 资源,尤其是在循环或高频触发的地方(如 mousemove
事件)。虽然现代浏览器优化了 console
,但大量日志仍可能导致轻微性能下降
暴露敏感信息
可能会泄露 API 接口、Token、用户数据等敏感信息,容易被恶意利用
干扰调试
生产环境日志过多,可能会掩盖真正的错误信息,增加调试难度。 开发者可能会误以为某些 console.log
是预期行为,而忽略真正的 Bug
增加代码体积
即使 console.log
本身很小,但大量日志会增加打包后的文件体积,影响加载速度
解决方案
删除
手动删除
- Ctrl + Shift + F ,全局搜索启动
- Alt + R,使用正则表达式
- 正则表达式
console\.log\(.*?\)
输入 - 然后全局替换,启动
插件删除
在 VSCode 插件商店中搜索 remove-console
编码规范化
ESLint
是一个插件化的 JavaScript
代码检查工具,它能够帮助我们识别代码中的问题,并提供修复建议
我们可以配置 .eslintrc.json
文件,通过添加相应的规则,来软性地禁止 console
的使用:
{
"rules": {
"no-console": "warn"
}
}
当这样配置后,代码中使用了 console
的地方会划上黄色波浪色,进行警示:
这样虽然不能实现删除 console.log
,但是能一定程度上削减代码中会出现的 console.log
的数量
ESLint
的能力有限,无法真正的拦截用户的代码提交
那么就双管齐下,既在代码编写的时候提醒删除 console.log
,也在代码提交的时候不允许没删干净 console.log
的代码提交
当我们每次提交代码时,Git
都会运行 pre-commit
这个 hook,因此我们就可以在这个 hook 内写一些处理逻辑
找到项目中的 .git/hooks/pre-commit.sample
文件,复制后重命名文件为 pre-commit
:
# 检查当前暂存区的文件是否包含 console.log
if git diff --cached --name-only | xargs grep -E 'console\.log';
then
echo "Error: console.log is not allowed in commits."
exit 1
fi
exit 0
git diff --cached
:列出暂存区(即将被提交的文件)与最后一次提交之间的差异--name-only
:这个选项告诉 Git 只输出有差异的文件名,而不输出差异内容|
:管道操作符,它将前一个命令的输出作为下一个命令的输入,这样就能拿到这次提交的全部代码了xargs
:这个命令从标准输入(也就是上一个命令的输出)中读取数据,并将其作为参数传递给后面的命令grep -E 'console.log'
:grep
是用于搜索文本的工具,-E
选项启用扩展的正则表达式。在我们的这种业务场景下,它就是负责搜索包含console.log
的字符串。注意,.
在正则表达式中是一个特殊字符,表示任意字符,因此需要用反斜杠\
进行转义if
语句:如果grep
命令找到了匹配的文件,则它的退出状态为 0(表示成功)exit 1
:这将终止脚本,并返回退出状态 1,通常表示一个错误或非正常退出fi
:表示if
语句结束exit 0
:以退出状态 0 结束,表示成功
也可以使用 husky 拦截 git commit
命令
这样在 git commit
时,就会检查新加的代码中有 console.log
就禁止提交,但是可以绕过这个检查:
git commit --no-verify
hack 方法
复写 console.log
if (_IS_DEV_) {
console.log = () => {}
}
自定义 console
包装函数
// utils/logger.js
const logger = {
log: (...args) => {
if (process.env.NODE_ENV !== "production") {
console.log("[LOG]", ...args);
}
},
warn: (...args) => {
console.warn("[WARN]", ...args);
},
error: (...args) => {
console.error("[ERROR]", ...args);
},
};
export default logger;
使用:
import logger from "./utils/logger";
logger.log("Debug info"); // 生产环境自动不打印
logger.error("Critical error"); // 始终打印
特点:
- 可以精细控制日志,可控性强,可以自定义日志级别
- 不影响
console.warn
和console.error
- 需要手动替换
console.log
构建工具
使用 Babel 插件
在 babel.config.js
中配置:
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset',
],
plugins: [
['@babel/plugin-proposal-optional-chaining'],
...process.env.NODE_ENV === 'production' ? [['transform-remove-console', { exclude: ['info', 'error', 'warn'] }]] : []
]
}
特点:
- 不影响源码,仅在生产环境生效,开发环境保留完整
console
- 配置简单直接,适合快速实现基本需求
- 依赖 Babel 插件
使用 Terser 压缩时移除
Webpack/Vite 默认都支持
在 vite.config.js
或 webpack.config.js
中配置:
module.exports = {
chainWebpack: (config) => {
config.optimization.minimizer("terser").tap((args) => {
args[0].terserOptions.compress = {
...args[0].terserOptions.compress,
drop_console: true, // 移除所有 console
pure_funcs: ["console.log"], // 只移除 console.log,保留其他
};
return args;
});
},
};
特点:
- 不影响源码,仅在生产环境生效,开发环境保留完整
console
- 避免 Babel 插件兼容性问题
- 需要额外配置
其他插件
Webpack 可以使用 terser-webpack-plugin
这个插件,它能够压缩 JavaScript 代码。在使用它的地方进行相应的配置即可:
将 drop_console
的值设置为 true
,就能在打包后去除全部的 console.log
vite 插件:vite-plugin-remove-console