为什么需要区分环境

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

  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. python骚操作之...

    python中的Ellipsis对象.写作:- 中文解释:省略 该对象bool测试是为真 用途: 1.用来省略代码,作用类似于pass的一种替代方案. from collections.abc imp ...

  2. .NET之美 第一部分C#语言基础

    第一章 类型基础 1 值类型与引用类型 CLR 支持两种类型:值类型和引用类型, C#的所有值类型均隐式派生自System.ValueType: 结构体:struct(直接派生于System.Valu ...

  3. SharePoint 2016: 数据库正在兼容性范围内运行,建议进行升级

    问题描述: SharePoint 运行状况分析器提示: 中文:数据库正在兼容性范围内运行,建议进行升级. 英文:Database running in compatibility range and ...

  4. 020_iPhone救命稻草

    一.如何对iPhone强制恢复出厂设置 1.在"通用"->"设置"->"还原全部设置",但是我的不知道为啥除了设置完开机密码后, ...

  5. $Django 数据库图片渲染设计 站点设计 截断函数

    1.数据库图片渲染设计 1.模型层 class User_info (AbstractUser): head_img = models.FileField (upload_to='test', def ...

  6. 缓存系列之一:buffer、cache与浏览器缓存

    缓存系列之一:buffer.cache与浏览器缓存 一:缓存是为了调节速度不一致的两个或多个不同的物质的速度,在中间对速度较快的一方起到一个加速访问速度较慢的一方的作用,比如CPU的一级.二级缓存是保 ...

  7. 1.ROS启动小乌龟

        启动turtlesim 在三个不同的终端中分别执行如下三个指令 roscore rosrun turtlesim turtlesim_node rosrun turtlesim turtle_ ...

  8. Codeforces 1045G AI robots [CDQ分治]

    洛谷 Codeforces 简单的CDQ分治题. 由于对话要求互相看见,无法简单地用树套树切掉,考虑CDQ分治. 按视野从大到小排序,这样只要右边能看见左边就可以保证互相看见. 发现\(K\)固定,那 ...

  9. Mybatis调用PostgreSQL存储过程实现数组入参传递

    注:本文来源于 < Mybatis调用PostgreSQL存储过程实现数组入参传递  > 前言 项目中用到了Mybatis调用PostgreSQL存储过程(自定义函数)相关操作,由于Pos ...

  10. Confluence 6 审查日志的对象

    审查日志记录一下事件的信息,这个记录不是详细的信息列表.但是这些信息能够让你了解你能够在日志中看到些什么内容. 空间 创建和删除一个空间. 编辑空间细节,主题,配色方案或者样式表. 修改空间权限,包括 ...