(window.webpackJsonp=window.webpackJsonp||[]).push([[30],{105:function(t,s,n){"use strict";n.r(s);var a=n(0),e=Object(a.a)({},function(){var t=this,s=t.$createElement,n=t._self._c||s;return n("div",{staticClass:"content"},[t._m(0),t._m(1),n("p",[t._v("在开发网页的时候，一般都会有多套运行环境，例如：")]),t._m(2),n("p",[t._v("这两套不同的环境虽然都是由同一套源代码编译而来，但是代码内容却不一样，差异包括：")]),n("ul",[n("li",[t._v("线上代码被通过 "),n("router-link",{attrs:{to:"./optimize-8.html"}},[t._v("压缩代码")]),t._v(" 中提到的方法压缩过。")],1),n("li",[t._v("开发用的代码包含一些用于提示开发者的提示日志，这些日志普通用户不可能去看它。")]),n("li",[t._v("开发用的代码所连接的后端数据接口地址也可能和线上环境不同，因为要避免开发过程中造成对线上数据的影响。")])]),n("p",[t._v("为了尽可能的复用代码，在构建的过程中需要根据目标代码要运行的环境而输出不同的代码，我们需要一套机制在源码中去区分环境。 幸运的是 Webpack 已经为我们实现了这点。")]),t._m(3),n("p",[t._v("具体区分方法很简单，在源码中通过如下方式：")]),t._m(4),n("p",[t._v("其大概原理是借助于环境变量的值去判断执行哪个分支。")]),t._m(5),t._m(6),t._m(7),t._m(8),n("p",[t._v("执行构建后，你会在输出的文件中发现如下代码：")]),t._m(9),t._m(10),t._m(11),t._m(12),t._m(13),t._m(14),t._m(15),n("p",[t._v("以上这句代码实际上等价于：")]),t._m(16),t._m(17),t._m(18),t._m(19),n("p",[t._v("Webpack 没有实现去除死代码功能，但是 UglifyJS 可以做这个事情，如何使用请阅读 "),n("router-link",{attrs:{to:"./optimize-8.html"}},[t._v("压缩代码")]),t._v(" 中的压缩 JavaScript。")],1),t._m(20),n("p",[t._v("除了在自己写的源码中可以有环境区分的代码外，很多第三方库也做了环境区分的优化。 以 React 为例，它做了两套环境区分，分别是：")]),t._m(21),n("p",[t._v("例如 React 源码中有大量类似下面这样的代码：")]),t._m(22),t._m(23),t._m(24)])},[function(){var t=this.$createElement,s=this._self._c||t;return s("h1",{attrs:{id:"_4-7-区分环境"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#_4-7-区分环境","aria-hidden":"true"}},[this._v("#")]),this._v(" 4-7 区分环境")])},function(){var t=this.$createElement,s=this._self._c||t;return s("h2",{attrs:{id:"为什么需要区分环境"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#为什么需要区分环境","aria-hidden":"true"}},[this._v("#")]),this._v(" 为什么需要区分环境")])},function(){var t=this.$createElement,s=this._self._c||t;return s("ol",[s("li",[this._v("在开发过程中方便开发调试的环境。")]),s("li",[this._v("发布到线上给用户使用的运行环境。")])])},function(){var t=this.$createElement,s=this._self._c||t;return s("h2",{attrs:{id:"如何区分环境"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#如何区分环境","aria-hidden":"true"}},[this._v("#")]),this._v(" 如何区分环境")])},function(){var t=this,s=t.$createElement,n=t._self._c||s;return n("div",{staticClass:"language-js extra-class"},[n("pre",{pre:!0,attrs:{class:"language-js"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("process"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("env"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token constant"}},[t._v("NODE_ENV")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("===")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"production"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n  console"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("log")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"你正在线上环境"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n  console"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("log")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"你正在使用开发环境"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])},function(){var t=this,s=t.$createElement,n=t._self._c||s;return n("p",[t._v("当你的代码中出现了使用 "),n("code",[t._v("process")]),t._v(" 模块的语句时，Webpack 就自动打包进 "),n("code",[t._v("process")]),t._v(" 模块的代码以支持非 Node.js 的运行环境。 当你的代码中没有使用 "),n("code",[t._v("process")]),t._v(" 时就不会打包进 "),n("code",[t._v("process")]),t._v(" 模块的代码。这个注入的 "),n("code",[t._v("process")]),t._v(" 模块作用是为了 "),n("strong",[t._v("模拟 Node.js 中的 process")]),t._v("，以支持上面使用的 "),n("code",[t._v("process.env.NODE_ENV === 'production'")]),t._v(" 语句。")])},function(){var t=this.$createElement,s=this._self._c||t;return s("p",[this._v("在构建线上环境代码时，需要给当前运行环境设置环境变量 "),s("code",[this._v("NODE_ENV = 'production'")]),this._v("，Webpack 相关配置如下：")])},function(){var t=this,s=t.$createElement,n=t._self._c||s;return n("div",{staticClass:"language-js extra-class"},[n("pre",{pre:!0,attrs:{class:"language-js"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" DefinePlugin "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("require")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"webpack/lib/DefinePlugin"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\nmodule"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("exports "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n  plugins"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("\n    "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DefinePlugin")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n      "),n("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// 定义 NODE_ENV 环境变量为 production")]),t._v("\n      "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"process.env"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n        "),n("span",{pre:!0,attrs:{class:"token constant"}},[t._v("NODE_ENV")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token constant"}},[t._v("JSON")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("stringify")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"production"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n      "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n    "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n  "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])},function(){var t=this,s=t.$createElement,n=t._self._c||s;return n("blockquote",[n("p",[t._v("注意在定义环境变量的值时用 "),n("code",[t._v("JSON.stringify")]),t._v(" 包裹字符串的原因是 "),n("strong",[t._v("环境变量的值需要是一个由双引号包裹的字符串")]),t._v("，而 "),n("code",[t._v("JSON.stringify('production')")]),t._v("的值正好等于"),n("code",[t._v("'\"production\"'")]),t._v("。")])])},function(){var t=this,s=t.$createElement,n=t._self._c||s;return n("div",{staticClass:"language-js extra-class"},[n("pre",{pre:!0,attrs:{class:"language-js"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n  console"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("log")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"你正在使用线上环境"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("else")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n  console"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("log")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"你正在使用开发环境"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])},function(){var t=this.$createElement,s=this._self._c||t;return s("p",[this._v("定义的环境变量的值被代入到了源码中，"),s("code",[this._v("process.env.NODE_ENV === 'production'")]),this._v(" 被直接替换成了 "),s("code",[this._v("true")]),this._v("。 并且由于此时访问 "),s("code",[this._v("process")]),this._v("的语句被替换了而没有了，Webpack 也不会打包进 process 模块了。")])},function(){var t=this.$createElement,s=this._self._c||t;return s("p",[s("code",[this._v("DefinePlugin")]),this._v(" 定义的环境变量 "),s("strong",[this._v("只对 Webpack 需要处理的代码有效")]),this._v("，而不会影响 Node.js 运行时的环境变量的值。")])},function(){var t=this.$createElement,s=this._self._c||t;return s("p",[this._v("通过 Shell 脚本的方式去定义的环境变量，例如 "),s("code",[this._v("NODE_ENV=production webpack")]),this._v("，Webpack 是不认识的，对 Webpack 需要处理的代码中的环境区分语句是没有作用的。")])},function(){var t=this.$createElement,s=this._self._c||t;return s("p",[this._v("也就是说只需要通过 "),s("code",[this._v("DefinePlugin")]),this._v(" 定义环境变量就能使上面介绍的环境区分语句正常工作，没必要又通过 Shell 脚本的方式去定义一遍。")])},function(){var t=this.$createElement,s=this._self._c||t;return s("p",[this._v("如果你想让 Webpack 使用通过 Shell 脚本的方式去定义的环境变量，你可以使用 "),s("code",[this._v("EnvironmentPlugin")]),this._v("，代码如下：")])},function(){var t=this,s=t.$createElement,n=t._self._c||s;return n("div",{staticClass:"language-js extra-class"},[n("pre",{pre:!0,attrs:{class:"language-js"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("webpack"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("EnvironmentPlugin")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"NODE_ENV"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])},function(){var t=this,s=t.$createElement,n=t._self._c||s;return n("div",{staticClass:"language-js extra-class"},[n("pre",{pre:!0,attrs:{class:"language-js"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("new")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("webpack"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("DefinePlugin")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n  "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"process.env.NODE_ENV"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token constant"}},[t._v("JSON")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("stringify")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("process"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("env"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token constant"}},[t._v("NODE_ENV")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])},function(){var t=this.$createElement,s=this._self._c||t;return s("h2",{attrs:{id:"结合-uglifyjs"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#结合-uglifyjs","aria-hidden":"true"}},[this._v("#")]),this._v(" 结合 UglifyJS")])},function(){var t=this.$createElement,s=this._self._c||t;return s("p",[this._v("其实以上输出的代码还可以进一步优化，因为 "),s("code",[this._v("if(true)")]),this._v(" 语句永远只会执行前一个分支中的代码，也就是说最佳的输出其实应该直接是：")])},function(){var t=this,s=t.$createElement,n=t._self._c||s;return n("div",{staticClass:"language-js extra-class"},[n("pre",{pre:!0,attrs:{class:"language-js"}},[n("code",[t._v("console"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("log")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"你正在线上环境"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])])},function(){var t=this.$createElement,s=this._self._c||t;return s("h2",{attrs:{id:"第三方库中的环境区分"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#第三方库中的环境区分","aria-hidden":"true"}},[this._v("#")]),this._v(" 第三方库中的环境区分")])},function(){var t=this.$createElement,s=this._self._c||t;return s("ol",[s("li",[this._v("开发环境：包含类型检查、HTML 元素检查等等针对开发者的警告日志代码。")]),s("li",[this._v("线上环境：去掉了所有针对开发者的代码，只保留让 React 能正常运行的部分，以优化大小和性能。")])])},function(){var t=this,s=t.$createElement,n=t._self._c||s;return n("div",{staticClass:"language-js extra-class"},[n("pre",{pre:!0,attrs:{class:"language-js"}},[n("code",[n("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("process"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("env"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),n("span",{pre:!0,attrs:{class:"token constant"}},[t._v("NODE_ENV")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!==")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"production"')]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n  "),n("span",{pre:!0,attrs:{class:"token function"}},[t._v("warning")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n    "),n("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n    "),n("span",{pre:!0,attrs:{class:"token string"}},[t._v('"%s(...): Can only update a mounted or mounting component.... "')]),t._v("\n  "),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),n("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])])},function(){var t=this.$createElement,s=this._self._c||t;return s("p",[this._v("如果你不定义 "),s("code",[this._v("NODE_ENV=production")]),this._v(" 那么这些警告日志就会被包含到输出的代码中，输出的文件将会非常大。")])},function(){var t=this.$createElement,s=this._self._c||t;return s("blockquote",[s("p",[s("code",[this._v("process.env.NODE_ENV !== 'production'")]),this._v(" 中的 "),s("code",[this._v("NODE_ENV")]),this._v(" 和 "),s("code",[this._v("'production'")]),this._v(" 两个值是社区的约定，通常使用这条判断语句在区分开发环境和线上环境。")])])}],!1,null,null,null);s.default=e.exports}}]);