webpack生产环境保留某些console.log

生产环境中部署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-jsconsole.log的处理方法后,我们想要保留console.log就很简单了,只要不是这么调用console.log(xxx)就行,写法其实有很多,原理都是用变量保留对console.log的引用

window.log = console.log
log('hahaha')
const {log} = console
log('wawawa')

参考

Webpack Uglify: Keep Certain console.logs

posted @ 2020-08-20 21:41  韩帅  阅读(2381)  评论(0编辑  收藏  举报