生产环境中部署js代码一般会去掉console.log()
,一来大量console.log
会影响性能,二来有可能引起安全问题。我们一般在webpack.prod.conf.js
文件配置:
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: true,
drop_debugger: true,
drop_console: true
}
},
sourceMap: config.build.productionSourceMap,
parallel: os.cpus().length - 1
}),
通过以上配置,我们的代码上生产环境后确实不会再控制台打印任何东西了。但是,如果我们想保留一些确定的打印呢,类似于百度:
在网上查得方法如下:
Node
环境下:
global.console.log("UglifyJs won't remove me")
Browser
环境下:
window.console.log("UglifyJs won't remove me")
console.log
清除原理浅析
// node_modules/uglify-js/lib/compress.js
// 传 drop_console: true
if (compressor.option("drop_console")) {
if (exp instanceof AST_PropAccess) {
var name = exp.expression;
while (name.expression) {
name = name.expression;
}
// 通过Babel生成AST语法树判断节点是否为 console
if (is_undeclared_ref(name) && name.name == "console") { // 没有对 X.console 这种AST节点进行判断,所以我们可以 window.console.log(1) 这么来打印内容
return make_node(AST_Undefined, self).optimize(compressor); // 用 AST_Undefined 节点替换当前 console节点(AST节点), AST_Undefined 定义在 node_modules/uglify-js/lib/ast.js 文件中
}
}
}
...
// 生成AST节点
function make_node(ctor, orig, props) {
if (!props) props = {};
if (orig) {
// 将原始console节点(AST节点)start end值赋值给一个空对象(props)
if (!props.start) props.start = orig.start;
if (!props.end) props.end = orig.end;
}
return new ctor(props);
}
总结
明白了uglify-js
对console.log
的处理方法后,我们想要保留console.log
就很简单了,只要不是这么调用console.log(xxx)
就行,写法其实有很多,原理都是用变量保留对console.log
的引用
window.log = console.log
log('hahaha')
const {log} = console
log('wawawa')