生產環境中部署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')