当前位置: 首页 > 后端技术 > Node.js

webpack选择性编译DefinePlugin(打包并自动排除测试数据)

时间:2023-04-04 00:01:13 Node.js

后台程序在开发过程中,测试过程中打印调试日志和伪造数据是必不可少的。这些代码不能出现在生产环境中。这意味着在程序打包之前,需要去掉相关代码。手工做这些事情很麻烦,而且很容易被忽视。而且打包出去测试的时候遇到了bug,又得重新把测试代码加回去。重复整个繁琐的过程。既然手动工作如此繁琐且容易出错,那么我们是否可以使用程序来帮助我们做这些事情呢?当然,你可以使用选择性编译技术。本文介绍webpack下解决该问题的方法。其实webpack官网上有提到这个方法。本文仅提供相关示例和一些扩展。选择性编译是指根据不同的打包环境,有选择地启用特定的语句,使特定的语句失效。最简单的例子,在开发环境中,我们打印日志,但是在生产环境中,我们将所有打印日志的语句都作废(以至于程序不运行打印的语句,甚至打包后的文件不包含打印日志的语句。语句)。selectivecompilation是作者想出来的一个名词,不知道用得对不对。实践过程首先我们来看一个选择性打印日志的例子。新建一个vue项目,打开build/webpack.dev.conf.js文件(项目在开发环境时使用的webpack打包配置,运行npmrundev,会执行这个文件)添加如下代码newwebpack.DefinePlugin({'process.env':config.dev.env,IS_DEV:JSON.stringify(true),}),打开build/webpack.prod.conf.js文件(项目时使用的webpack打包配置生产环境打包,运行npmrunbuild,会执行这个文件)添加如下代码newwebpack.DefinePlugin({'process.env':config.dev.env,IS_DEV:JSON.stringify(false),}),打开src/main.js文件(项目入口文件,运行项目时执行)添加如下代码if(IS_DEV){console.log('thisisdevenv');}else{console.log('this是prodenv');}分别在开发环境和生产环境运行程序,查看控制台。我们发现在开发环境中,打印的是thisisdevenv。在生产环境中运行打印出thisisprodenv。打开打包好的文件/dist/static/js/app.xxx.js.map,搜索thisisprodenv。我们发现IS_DEV变成了false。同样,我们查看开发环境中的chrome开发者工具,找到对应的app.xxx.js文件。我们发现IS_DEV变成了true。由此我们可以知道,选择性编译本质上是对字符串的替换,首先通过DefinePlugin对代码中的特定字符串进行替换。然后对替换后的代码进行编译打包。需要替换的变量需要分别在webpack.dev.conf.js和webpack.prod.conf.js中指定其转换后的含义。为什么在mian.js中使用IS_DEV时程序不报错“IS_DEVisnotdefined”?因为当浏览器运行代码时,获取到的文件中的IS_DEV已经被true或者false替换,变量IS_DEV已经不存在了。所以不会报错。DefinePlugin的使用说明除了可以替换简单的布尔值外,还可以替换成字符串、数字、数组、对象等。比如TEST_DATA:JSON.stringify({name:'momo',age:18}),why你需要替换JSON.stringify吗?另外可以用某段代码的值来代替(代码内容可以直接用“”包起来)。例如:TWO:“1+1”,TOW会被替换成这段代码的结果,也就是2。ESLint冲突处理ESLint是一个代码检测工具,用于识别ECMAScript并按规则上报。使用它可以避免低级错误,统一代码风格。配置了eslint的项目在使用选择性编译功能时,可能会报这样的错误。http://exlint.org/docs/rules/no-undef'IS_DEV'isnotdefined如错误信息所说,这是因为eslint检测代码时,发现IS_DEV未定义(这边说明eslint是在conditionCompileandexecute之前。ESLint检测到IS_DEV还没有被替换)。解决这个问题的方法有3种:简单粗暴的方法,修改eslint的配置,把error改成warn,先打包。具体操作是修改eslintrc.js文件,如果配置文件中已经有第一条语句'eslint':'recommended'(这里指的是默认配置)。然后在规则中添加一条规则'no_undef':'warn'来覆盖默认配置。如果'no-undef'的配置已经存在,直接改成'warn'即可。上面的方法影响太大,直接修改规则。是否可以在本地修改规则,使其仅在某些语句中被忽略?是的,只是用备注把需要忽略的语句包裹起来。但是上面的方法需要在每个用到的地方多写两条语句,有点麻木。,有没有一种更简单、一劳永逸的方法来做到这一点?是的~~修改eslintrc.js,将IS_DEV配置为全局变量,这样eslint就不会认为IS_DEV是未定义变量了。SelectiveEditing技术应用场景API接口环境替代账户信息模拟、数据模拟日志打印等彩蛋效果更好。使用if逻辑判断输出日志的移除日志的方法可能有点繁琐。其实对于控制台输出的日志,我们可以在打包的时候使用UglifyJs来剔除。具体操作:打开build/webpack.prod.conf.js文件,添加如下语句compress:{warnings:false,//去掉warning警告drop_debugger:true,//去掉发布时的debugger语句drop_console:true//removetheconsolewhenpublishingStatement},如果只想去掉console.log,同时保留console.error等错误提示。可以指定移除特定函数compress:{warnings:false,//移除警告警告pure_funcs:['console.log'],//配置发布时不打包的函数//drop_debugger:true,//发布时移除debugger//drop_console:true//发布时去掉console}注意,添加这个配置后,console.log不会再存在于打包文件中。所以之前测试用的thisisdevenv也会消失。去除条件编译中不可达的代码。无法访问的代码是什么?是任何情况下都不会执行的代码。例如,if(false){console.log('这是开发环境');}else{console.log('这是生产环境');}```console.log('这是开发环境');```是无法访问的代码。我们也可以使用UglifyJs的功能来去除这部分无用代码。让条件编译不留痕迹。具体配置如下:```compress:{warnings:false,//移除警告warningdead_code:true,//移除不可达代码},sourceMap:true```![dead_code](http://upyun.luckly-mjw.cn/Assets/selective-compilation/dead_code.png)UglifyJs的更多功能UglifyJs还使用了很多强大的功能,比如代码混淆、压缩、重制等,这里是UglifyJs的官网。英文不好的同学也可以查看对应的中文文档(其实这才是重点#滑智脸)。结束了,撒花