资讯专栏INFORMATION COLUMN

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

王军 / 1632人阅读

摘要:选择性编译是指根据打包是环境的不同,选择性地让特定的语句有效,让特定的语句无效。选择性编译是笔者自己瞎想出来的名词,不知道用的对不对。检测时,还没有被替换掉。

背景

程序在开发的过程中,少不了打印调试用的日志,测试流程时伪造的数据。这些代码是不能出现在生产环境上的。
这意味着在程序打包前,需要把相关代码剔除掉。
这些事情用人手去做很麻烦,很容易疏漏。而且打包出来测试时遇到了bug,又得重新把测试代码添加回去。重复整个繁琐的过程。

既然人工做这么麻烦而且容易出错,那能不能用程序帮我们完成这些事情呢?
当然可以,用选择性编译技术就行,本文就介绍在webpack下解决这一问题的方法。
其实这个方法在webpack官网就有提到,本文只是提供相关示例及做一些延伸。

选择性编译是指根据打包是环境的不同,选择性地让特定的语句有效,让特定的语句无效。
最简单的例子,在开发环境中,我们打印日志,但在生产环境中,我们让所有打印日志的语句无效(让程序不运行打印的语句,甚至让打包出来的文件根本就不包含打印日志的语句)。
选择性编译是笔者自己瞎想出来的名词,不知道用的对不对。
实践过程 首先,先让我们看一个选择性打印日志的示例。

新建一个vue项目

打开build/webpack.dev.conf.js文件(项目处于开发环境时使用到的webpack打包配置,运行npm run dev,这个文件就会被执行)

添加如下代码

new webpack.DefinePlugin({
    "process.env": config.dev.env,
    IS_DEV: JSON.stringify(true),
}),

打开build/webpack.prod.conf.js文件(项目打包生产环境时使用到的webpack打包配置,运行npm run build,这个文件就会被执行)

添加如下代码

new webpack.DefinePlugin({
    "process.env": config.dev.env,
    IS_DEV: JSON.stringify(false),
}),

打开src/main.js文件(项目入口文件,运行项目时被执行)

添加如下代码

if (IS_DEV) {
    console.log("this is dev env");
} else {
    console.log("this is prod env");
}

分别在开发环境和生产环境运行程序,查看控制台。我们发现,在开发环境下,打印了this is dev env。在生产环境下运行打印了this is prod env

打开打包出来的文件/dist/static/js/app.xxx.js.map,搜索this is prod env。我们发现IS_DEV变成了false。

同理,我们在开发环境下,查看chrome开发者工具,找到相应的app.xxx.js文件。我们发现IS_DEV变成了true。

由此我们可以知道

选择性编译本质上是字符串的替换,先经过DefinePlugin对代码中的特定字符串进行替换。再对替换后的代码进行编译打包。

需要替换的变量需要分别在webpack.dev.conf.jswebpack.prod.conf.js中指定其转换后的意义。

为什么在mian.js中使用IS_DEV,程序不会报"IS_DEV is not defined"的错误?

因为浏览器在运行代码时,拿到的文件里面IS_DEV已经被替换成了true或者false,已经不存在IS_DEV这个变量。所以不会报错。

DefinePlugin的使用说明

除了替换成简单的布尔值,还可以替换成字符串,数值,数组,对象等。

如TEST_DATA: JSON.stringify({name:"momo",age:18}),

为什么需要进行JSON.stringify替换?

另外还可以替换成某个段代码的值(代码内容直接使用""包裹即可)。

如:TWO: "1+1",TOW将被替换成这段代码的结果,即2。

ESLint冲突处理
ESLint是一个用来识别 ECMAScript 并且按照规则给出报告的代码检测工具,使用它可以避免低级错误和统一代码的风格。
配置了eslint的项目在使用选择性编译功能时,可能会报出这样的错误。
http://exlint.org/docs/rules/no-undef "IS_DEV" is not defined
正如报错信息所说的,这是由于eslint检测代码时,发现IS_DEV没有定义(这侧面说明了eslint是先于条件编译执行的。ESLint检测时,IS_DEV还没有被替换掉)。解决这个问题有以下三种方法:

简单粗暴的方法,修改eslint的配置,将error改为warn呗,先打包了再说。具体操作为修改eslintrc.js文件,如果配置文件里面已有第一条语句"eslint":"recommended"(这是引用默认配置)。则往rules里面添加一条规则"no_undef":"warn",以覆盖掉默认配置。

如果已经存在"no-undef"的配置,则直接改为"warn"就行。

上面的方法影响太大,直接修改了规则。能不能局部修改规则,只在特定语句中忽略掉该规则呢?可以的,使用备注包裹需要忽略的语句就行。

但是上面的方法需要在每个用到的地方都多写两条语句,略麻。,有没有更简单的,一劳永逸的方法呢?有有有~~ 修改eslintrc.js,将IS_DEV配置成一个全局变量,之后eslint就不会认为IS_DEV是未定义的变量了。

选择性编辑技术的应用场景

API接口的环境替换

账号信息的模拟,数据模拟

日志打印等

彩蛋 更优的去除log的方法

用if逻辑判断来输出log可能略显繁琐。其实对于控制台输出的日志,我们可以通过UglifyJs在打包时来剔除。
具体操作:

打开build/webpack.prod.conf.js文件,添加如下语句

compress: {
    warnings: false, // 去除warning警告
    drop_debugger: true, // 发布时去除debugger语句
    drop_console: true // 发布时去除console语句
},

如果想只去除console.log,同时保留console.error等错误提示。可以指定去除特定的函数

compress: {
    warnings: false, // 去除warning警告
    pure_funcs: ["console.log"], // 配置发布时,不被打包的函数
    // drop_debugger: true, // 发布时去除debugger
    // drop_console: true // 发布时去除console
}

注意,添加了这个配置以后,console.log在打包出来的文件就不存在了。所以前面测试用的this is dev env也会消失不见

去除条件编译中不可达代码

什么叫不可达代码?就是无论什么情况下都不会被运行的代码。

例如我们在条件编译打包出来的代码中

if (false) {
    console.log("this is dev env");
} else {
    console.log("this is prod env");
}
```console.log("this is dev env");```就是不可达代码。
我们同样可以使用UglifyJs的功能把这部分无用代码去除掉。让条件编译不留痕迹。
具体配置如下:
```
compress: {
    warnings: false, // 去除warning警告
    dead_code: true, // 去除不可达代码
}, sourceMap: true
```
![dead_code](http://upyun.luckly-mjw.cn/Assets/selective-compilation/dead_code.png)
UglifyJs的更多功能

UglifyJs还用很多强大的功能,如代码混淆,压缩,重拍版等。这里附上UglifyJs官方网址。
英文不好的同学还可以查看对应的中文文档(其实这才是重点#机智脸)

完结,撒花花

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/89020.html

相关文章

  • webpack优化

    摘要:使用要给项目构建接入动态链接库的思想,需要完成以下事情把网页依赖的基础模块抽离出来,打包到一个个单独的动态链接库中去。接入已经内置了对动态链接库的支持,需要通过个内置的插件接入,它们分别是插件用于打包出一个个单独的动态链接库文件。 webpack优化 查看所有文档页面:全栈开发,获取更多信息。原文链接:webpack优化,原文广告模态框遮挡,阅读体验不好,所以整理成本文,方便查找。 ...

    ChanceWong 评论0 收藏0
  • 从零开始搭建React同构应用(三):配置SSR

    摘要:从零开始搭建同构应用三配置这篇文章来讲解来配置,我们先从最简单的方法开始,用的方式模拟实现。影响生产环境下执行效率。最后权衡下,还是决定使用现在多一套编译配置的方案。新建,写入以下内容以为例,注意不能少。 从零开始搭建React同构应用(三):配置SSR 这篇文章来讲解来配置server side render,我们先从最简单的方法开始,用cli的方式模拟实现SSR。 demo在这里 ...

    jzzlee 评论0 收藏0
  • webpack学习笔记

    摘要:配置完成后就可以使用来打包代码了。值得注意的是会删除所有无作用代码也就是说那些包裹在这些全局变量下的代码块都会被删除这样就能保证这些代码不会因发布上线而泄露。默认会从项目的根目录下引入这些文件。 命令使用 npm install webpack -g 作为全局安装, 在任意目录使用 npm install webpack --save-dev 作为项目依赖安装 np...

    mylxsw 评论0 收藏0
  • webpack4.0优化那些事儿

    摘要:配置以何种方式导出库。当检测文件不再发生变化,会先缓存起来,等等待一段时间后之后再通知监听者,这个等待时间通过配置。发布到线上给用户使用的运行环境。 一 缩小文件搜索范围 1 include & exclude 1) action 限制编译范围 2) useage module: { rules: [ { test...

    levy9527 评论0 收藏0
  • [Webpack并不难]使用教程(三)--- plugins

    摘要:使用教程一,,,使用教程二版本官方的文档上一篇讲到的是被用来转换某些类型的模块,它则可以用来做更广泛的任务。可看作绑定事件,打包时会触发事件。它的作用是定义全局常量,是常量。为,启用两步之间的延迟。请注意,规范建议始终使用引号。 使用教程(一)--- entry,devtool,output,resolve使用教程(二)--- module.loadersWebpack版本 3.10...

    Youngs 评论0 收藏0

发表评论

0条评论

王军

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<