手写清除console的loader

588 阅读4分钟

前言

作为一个前端,对于console.log的调试可谓是相当熟悉,话不多说就是好用!帮助我们解决了很多bug^_^
但是!有因必有果(虽然不知道为什么说这句但是很顺口),如果把console发到生产环境也是很头疼的,尤其是如果打印的信息很私密的话,可能要凉凉TT

删除console方式介绍

对于在生产环境必须要清除的console语句,如果手动一个个删除,听上去就很辛苦,因此这篇文章本着看到了就要学,学到了就要用的精神我打算介绍一下手写loader的方式清除代码中的console语句,在此之前也介绍一下其他可以清除console语句的方式吧哈哈

image.png

1. 方式一:暴力清除

通过编辑器查找所有console,或者eslint编译时的报错提示定位语句,然后清除,就是有点费手,不够优雅
因此下面需要介绍几种优雅的清除方式

2. 方式二 :uglifyjs-webpack-plugin

该插件可用于压缩我们的js代码,同时可以通过配置去掉console语句,安装后配置在webpack的optimization下,即可使用,需要注意的是:此配置只在production环境下生效

安装
npm i uglifyjs-webpack-plugin

image.png 其中drop_console和pure_funcs的区别是:

  • drop_console的配置值为boolean,也就是说如果为true,那么代码中所有带console前缀的调试方式都会被清除,包括console.log,console.warn等
  • pure_funcs的配置值是一个数组,也就是可以配置清除那些带console前缀的语句,截图中配的是['console.log'] ,因此生产环境上只会清除console.log,如果代码中包含其他带console的前缀,如console.warn则保留

但是需要注意的是,该方法只对ES5语法有效,如果你的代码中涉及ES6就会报错

3. 方式三:terser-webpack-plugin

webpack v5 开箱即带有最新版本的 terser-webpack-plugin。如果你使用的是 webpack v5 或更高版本,同时希望自定义配置,那么仍需要安装 terser-webpack-plugin。如果使用 webpack v4,则必须安装 terser-webpack-plugin v4 的版本。

安装
npm i terser-webpack-plugin@4

image.png terser-webpack-plugin对于清楚console的配置可谓是跟uglifyjs-webpack-plugin一点没差,但是他们最大的差别就是TerserWebpackPlugin支持ES6的语法

4. 方式四:手写loader删除console

终于进入了主题了,朋友们

  1. 什么是loader 众所周知,webpack只能理解js,json等文件,那么除了js,json之外的文件就需要通过loader去顺利加载,因此loader在其中担任的就是翻译工作。loader可以看作一个node模块,实际上就是一个函数,但他不能是一个箭头函数,因为它需要继承webpack的this,可以在loader中使用webpack的方法。
  • 单一原则,一个loader只做一件事
  • 调用方式,loader是从右向左调用,遵循链式调用
  • 统一原则,输入输出都是字符串或者二进制数据

根据第三点,下面的代码就会报错,因为输出的是数字而不是字符串或二进制数据

module.exports = function(source) {
    return 111
}

image.png

  1. 新建清除console语句的loader

首先新建一个dropConsole.js文件

// source:表示当前要处理的内容
const reg = /(console.log\()(.*)(\))/g;
module.exports = function(source) {
    // 通过正则表达式将当前处理内容中的console替换为空字符串
    source = source.replace(reg, "")
    // 再把处理好的内容return出去,坚守输入输出都是字符串的原则,并可达到链式调用的目的供下一个loader处理
    return source
}
  1. 在webpack的配置文件中引入
module: {
    rules:[
        {
            test: /\.js/,
            use: [
               {
                loader: path.resolve(__dirname, "./dropConsole.js"),
                options: {
                 name: "前端"
                }
               }
            ]
        },
      {
   ]
}

在webpack的配置中,loader的导入需要绝对路径,否则导入失效,如果想要像第三方loader一样引入,就需要配置resolveLoader 中的modules属性,告诉webpack,当node_modules中找不到时,去别的目录下找

module: {
    rules:[
        {
            test: /\.js/,
            use: [
               {
                loader: 'dropConsole',
                options: {
                 name: "前端"
                }
               }
            ]
        },
      {
   ]
}
resolveLoader:{
    modules:["./node_modules","./build"] //此时我的loader写在build目录下
},

正常运行后,调试台将不会打印console信息

image.png

  1. 最后介绍几种在loader中常用的webpack api
  • this.query:返回webpack的参数即options的对象

image.png

  • this.callback:同步模式,可以把自定义处理好的数据传递给webpack
const reg = /(console.log\()(.*)(\))/g;
module.exports = function(source) {
    source = source.replace(reg, "");
    this.callback(null,source);
    // return的作用是让webpack知道loader返回的结果应该在this.callback当中,而不是return中
    return     
}
  • this.async():异步模式,可以大致的认为是this.callback的异步版本,因为最终返回的也是this.callback
const  path = require('path')
const util  = require('util')
const babel = require('@babel/core')


const transform = util.promisify(babel.transform)

module.exports = function(source,map,meta) {
  var callback = this.async();

  transform(source).then(({code,map})=> {
      callback(null, code,map)
  }).catch(err=> {
      callback(err)
  })
};

最后的最后,webpack博大精深,值得我们好好学习,深入研究!