为什么需要区分环境

在开发网页的时候,一般都会有多套运行环境,例如:

  1. 在开发过程中方便开发调试的环境。
  2. 发布到线上给用户使用的运行环境。

这两套不同的环境虽然都是由同一套源代码编译而来,但是代码内容却不一样,差异包括:

  • 线上代码被通过 4-8 压缩代码 中提到的方法压缩过。
  • 开发用的代码包含一些用于提示开发者的提示日志,这些日志普通用户不可能去看它。
  • 开发用的代码所连接的后端数据接口地址也可能和线上环境不同,因为要避免开发过程中造成对线上数据的影响。

为了尽可能的复用代码,在构建的过程中需要根据目标代码要运行的环境而输出不同的代码,我们需要一套机制在源码中去区分环境。 幸运的是 Webpack 已经为我们实现了这点。

如何区分环境

具体区分方法很简单,在源码中通过如下方式:

if (process.env.NODE_ENV === 'production') {
console.log('你正在线上环境');
} else {
console.log('你正在使用开发环境');
}

其大概原理是借助于环境变量的值去判断执行哪个分支。

当你的代码中出现了使用 process 模块的语句时,Webpack 就自动打包进 process 模块的代码以支持非 Node.js 的运行环境。 当你的代码中没有使用 process 时就不会打包进 process 模块的代码。这个注入的 process 模块作用是为了模拟 Node.js 中的 process,以支持上面使用的  process.env.NODE_ENV === 'production'  语句。

在构建线上环境代码时,需要给当前运行环境设置环境变量  NODE_ENV = 'production' ,Webpack 相关配置如下:

const DefinePlugin = require('webpack/lib/DefinePlugin');
module.exports = {
plugins: [
new DefinePlugin({
// 定义 NODE_ENV 环境变量为 production
'process.env': {
NODE_ENV: JSON.stringify('production')
}
}),
],
};

注意在定义环境变量的值时用  JSON.stringify  包裹字符串的原因是环境变量的值需要是一个由双引号包裹的字符串,而  JSON.stringify('production') 的值正好等于 "production" 。

执行构建后,你会在输出的文件中发现如下代码:

if (true) {
console.log('你正在使用线上环境');
} else {
console.log('你正在使用开发环境');
}

定义的环境变量的值被代入到了源码中, process.env.NODE_ENV === 'production'  被直接替换成了 true。 并且由于此时访问 process 的语句被替换了而没有了,Webpack 也不会打包进 process 模块了。

DefinePlugin 定义的环境变量只对 Webpack 需要处理的代码有效,而不会影响 Node.js 运行时的环境变量的值。

通过 Shell 脚本的方式去定义的环境变量,例如  NODE_ENV=production webpack ,Webpack 是不认识的,对 Webpack 需要处理的代码中的环境区分语句是没有作用的。

也就是说只需要通过 DefinePlugin 定义环境变量就能使上面介绍的环境区分语句正常工作,没必要又通过 Shell 脚本的方式去定义一遍。

如果你想让 Webpack 使用通过 Shell 脚本的方式去定义的环境变量,你可以使用 EnvironmentPlugin,代码如下:

new webpack.EnvironmentPlugin(['NODE_ENV'])

以上这句代码实际上等价于:

new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
})

结合 UglifyJS

其实以上输出的代码还可以进一步优化,因为  if(true)  语句永远只会执行前一个分支中的代码,也就是说最佳的输出其实应该直接是:

  console.log('你正在线上环境');

Webpack 没有实现去除死代码功能,但是 UglifyJS 可以做这个事情,如何使用请阅读 4-8 压缩代码 中的压缩 JavaScript。

第三方库中的环境区分

除了在自己写的源码中可以有环境区分的代码外,很多第三方库也做了环境区分的优化。 以 React 为例,它做了两套环境区分,分别是:

  1. 开发环境:包含类型检查、HTML 元素检查等等针对开发者的警告日志代码。
  2. 线上环境:去掉了所有针对开发者的代码,只保留让 React 能正常运行的部分,以优化大小和性能。

例如 React 源码中有大量类似下面这样的代码:

if (process.env.NODE_ENV !== 'production') {
warning(false, '%s(...): Can only update a mounted or mounting component.... ')
}

如果你不定义  NODE_ENV=production  那么这些警告日志就会被包含到输出的代码中,输出的文件将会非常大。

process.env.NODE_ENV !== 'production'  中的  NODE_ENV  和 ' production ' 两个值是社区的约定,通常使用这条判断语句在区分开发环境和线上环境。本实例 提供项目完整代码

webpack学习笔记--区分环境的更多相关文章

  1. Android Studio 学习笔记(一)环境搭建、文件目录等相关说明

    Android Studio 学习笔记(一)环境搭建.文件目录等相关说明 引入 对APP开发而言,Android和iOS是两大主流开发平台,其中区别在于 Android用java语言,用Android ...

  2. Qt5学习笔记(1)-环境配置(win+64bit+VS2013)

    Qt5学习笔记(1)-环境配置 工欲善其事必先-不装-所以装软件 久不露面,赶紧打下酱油. 下载 地址:http://download.qt.io/ 这个小网页就可以下载到跟Qt有关的几乎所有大部分东 ...

  3. openresty 学习笔记一:环境安装

    openresty 学习笔记一:环境安装 openresty 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库.第三方模块以及大多数的依赖项.用于方便地搭 ...

  4. 更博不能忘——webpack学习笔记

    webpack是前端构建系统就像grunt和gulp(之前有学习过grunt所以也就大概明白webpack是个什么东西),所以说前端技术大部分还真是相通的,现在觉得当时多看的东西并不白费,虽然长时间不 ...

  5. 【原】webpack学习笔记

    之前在react的项目中有用过webpack,不过没有认真的去研究,这段时间又重新好好的学习一下webpack,发觉 webpack是一个很强大的东西.而且很好用,方便,接下来主要是做一下学习的笔记 ...

  6. webpack学习笔记—webpack安装、基本配置

    文章结构: 什么是webpack? 安装webpack 'webpack基本配置 一.什么是webpack? 在学习react时发现大部分文章都是react和webpack结合使用的,所以在学reac ...

  7. Python3学习笔记 - 准备环境

    前言 最近乘着项目不忙想赶一波时髦学习一下Python3.由于正好学习了Docker,并深深迷上了Docker,所以必须趁热打铁的用它来创建我们的Python3的开发测试环境.Python3的中文教程 ...

  8. webpack学习笔记一:安装webpack、webpack-dev-server、内存加载js和html文件、loader处理非js文件

    一 .webpack学习环境准备: 1:window系统 2:安装node.js  官方网址 下载好后下一步下一步安装即可 安装步骤略过....... 3:nrm的安装 打开cmd命令控制台 输入:n ...

  9. oracle学习笔记——配置环境

    题记:最近再学oracle,于是按照这本经典的书<Oracle Database 9i/10g/11g编程艺术>来学习. 配置环境 如何正确建立SCOTT/TIGER演示模式 需要建立和运 ...

随机推荐

  1. rocketmq的name server启动时的jvm参数配置

    -Xms2g -Xmx2g -Xmn1g //设置年轻代大小 -XX:MetaspaceSize=128m //持久代的初始大小 -XX:MaxMetaspaceSize=320m //持久代的上限 ...

  2. 利用binlogserver恢复单表实验【转】

    使用场景 每次开启binlogserver 指定了mysql-bin.0000XX 后都会从该点从头进行传输一次 创建binlogserver [root@mysql-zst3 binlogserve ...

  3. 设计模式C++学习笔记之四(Multition多例模式)

      多例模式,这个在GOF的模式设计里没有提到,但在实际工作中确实会用到.更详细的内容及说明可以参考原作者博客:cbf4life.cnblogs.com. 4.1.解释 main(),客户 略 说明: ...

  4. 在PHP中使用AES加密算法加密数据及解密数据

    这个算法可以将数据加密后,储存起来,到需要用的时候,用之前加密的秘钥将之还原. 除了这个之外,还有AES这个算法能够将数据很好的加密起来,在传输过程中不容易被破解. 在PHP中,我们必须先安装好mcr ...

  5. aix装python

    网址是:http://www-03.ibm.com/systems/power/software/aix/linux/toolbox/alpha.html 在AIX下安装python Python是个 ...

  6. zabbix3.2监控vcenter和exsi信息

    简介 为了解 ESXI虚拟主机的运行状况,通过zabbix进行监控,图形展示ESXI虚拟主机当前的状态,避免因为esxi服务器因为资源利用率过高导致 概述 从 Zabbix 2.2.0 开始支持对 V ...

  7. Mac 上卸载 Java

    如何在 Mac 上卸载 Java? 本文适用于: 平台: Macintosh OS X Java 版本: 7.0, 8.0 使用终端卸载 Oracle Java 注:要卸载 Java,必须具有管理员权 ...

  8. Springboot:开发时工程启动慢

    个人的解决办法是删除workspace中的histor 然后重启Eclipse,发现一切正常.

  9. awk-for循环简单用法

    文本: [root@VM_0_84_centos ~]# cat sshd.txt 1 2 3 4 5 6 7 8 9 循环打印上述文本 for 循环的固定格式   i=1设置i的初始变量  i< ...

  10. Oracle11g 体系结构

    一:Oracle11g 体系结构 二:逻辑储存结构 二.1:数据块(data blocks) ----通过 v$parameter数据字典来查询oracle标准数据块的大小. SYS@orcl> ...