本文首发于 Array_Huang的技术博客——实用至上
,非经做者赞成,请勿转载。
原文地址: http://www.javashuo.com/article/p-gfjsypje-kc.html
若是您对本系列文章感兴趣,欢迎关注订阅这里:https://segmentfault.com/blog/array_huang
开发环境与生产环境分离的缘由以下:javascript
若是硬是要在开发环境和生产环境用彻底同样的代码,那么必然会付出沉重的代价,这点想必也不用多说了。css
下面主要针对两点来介绍如何分离开发环境和生产环境:一是如何以不一样的方式进行编译,也即如何分别造成开发环境及生产环境的webpack配置文件;二是在业务代码中如何根据环境的不一样而作出不一样的处理。html
若是同时把一份完整的开发环境配置文件和一份完整的生产环境配置文件列在一块儿进行比较,那么会出现如下三种状况:前端
HotModuleReplacementPlugin
。UglifyJsPlugin
。output.publicPath
,又好比说css-loader
中的minimize
和autoprefixer
参数。更重要的是,实际上开发环境和生产环境的配置文件的绝大部分都是一致的,对于这一致的部分来讲,咱们坚定要消除冗余,不然后续维护起来不只麻烦,并且还容易出错。java
答案很简单:分拆webpack配置文件成N个小module。原先咱们是一个完整的配置文件,有好几百行,从头看到尾都头大了,更别说分离不分离的了。下面来看看我分离的结果:node
├─webpack.dev.config.js # 开发环境的webpack配置文件(无实质内容,仅为组织整理) ├─webpack.config.js # 生产环境的webpack配置文件(无实质内容,仅为组织整理) ├─webpack-config # 存放分拆后的webpack配置文件 ├─entry.config.js # webpack配置中的各个大项,这一级目录里的文件都是 ├─module.config.js ├─output.config.js ├─plugins.dev.config.js # 俩环境配置中不一致的部分,此文件由开发环境配置文件webpack.dev.config.js来加载 ├─plugins.product.config.js # 俩环境配置中不一致的部分,此文件由生产环境配置文件webpack.config.js来加载 ├─resolve.config.js │ ├─base # 主要是存放一些变量 │ ├─dir-vars.config.js │ ├─page-entries.config.js │ ├─inherit # 存放生产环境和开发环境相同的部分,以供继承 │ ├─plugins.config.js │ └─vendor # 存放webpack兼容第三方库所需的配置文件 ├─eslint.config.js ├─postcss.config.js
文件目录结构看过了,接下来看一下我是如何组织整理最后的配置文件的:webpack
/* 开发环境webpack配置文件webpack.dev.config.js */ module.exports = { entry: require('./webpack-config/entry.config.js'), output: require('./webpack-config/output.config.js'), module: require('./webpack-config/module.config.js'), resolve: require('./webpack-config/resolve.config.js'), plugins: require('./webpack-config/plugins.dev.config.js'), eslint: require('./webpack-config/vendor/eslint.config.js'), postcss: require('./webpack-config/vendor/postcss.config.js'), };
这样,你就能够很轻松地处理开发/生产环境配置文件中相同与不一样的部分了。git
还记得我在《webpack多页应用架构系列(二):webpack配置经常使用部分有哪些?》里讲过,咱们在控制台调用webpack命令来启动打包时,能够添加上--config
参数来指定webpack配置文件的路径吗?咱们能够配合上npm scripts
来使用,在package.json里定义:github
"scripts": { "build": "node build-script.js && webpack --progress --colors", "dev": "node build-script.js && webpack --progress --colors --config ./webpack.dev.config.js", "watch": "webpack --progress --colors --watch --config ./webpack.dev.config.js" },
这样一来,当咱们开发的时候就可使用npm run dev
或npm run watch
,而到要上线打包的时候就运行npm run build
。web
在业务代码里要判断生产/开发环境其实很简单,只需一个变量便可:
if (IS_PRODUCTION) { // 作生产环境该作的事情 } else { // 作开发环境该作的事情 }
这么一来,关键就在于这变量IS_PRODUCTION
是怎么来的了。
在我还没分离开发和生产环境时,我用的办法是,开发时在业务代码所使用的配置文件中把这变量设为false
,而在最后打包上线时就手动改成true
。这种方法我用过一段时间,很是繁琐,并且常常上线后发现,我嘞个去怎么ajax读的是我本地的mock服务器。
我参考了许多文章,先粗略讲讲我没有采用的方法:
EnvironmentPlugin
引入process.env,这样就能够在业务代码中靠process.env.NODE_ENV
来判断了。ProvidePlugin
来控制在不一样环境里加载不一样的配置文件(业务代码用的)。那我用的是什么方法呢?我最后选用的是DefinePlugin
。
举个官方例子,其大概用法是这样的:
new webpack.DefinePlugin({ PRODUCTION: JSON.stringify(true), VERSION: JSON.stringify("5fa3b9"), BROWSER_SUPPORTS_HTML5: true, TWO: "1+1", "typeof window": JSON.stringify("object") })
DefinePlugin
可能会被误认为其做用是在webpack配置文件中为编译后的代码上下文环境设置全局变量,但其实否则。它真正的机制是:DefinePlugin
的参数是一个object,那么其中会有一些key-value
对。在webpack编译的时候,会把业务代码中没有定义(使用var/const/let来预约义的)而变量名又与key
相同的变量(直接读代码的话的确像是全局变量)替换成value
。例如上面的官方例子,PRODUCTION
就会被替换为true
;VERSION
就会被替换为'5fa3b9'
(注意单引号);BROWSER_SUPPORTS_HTML5
也是会被替换为true
;TWO
会被替换为1+1
(至关因而一个数学表达式);typeof window
就被替换为'object'
了。
再举个例子,好比你在代码里是这么写的:
if (!PRODUCTION) console.log('Debug info') if (PRODUCTION) console.log('Production log')
那么在编译生成的代码里就会是这样了:
if (!true) console.log('Debug info') if (true) console.log('Production log')
而若是你用了UglifyJsPlugin
,则会变成这样:
console.log('Production log')
如此一来,只要在俩环境的配置文件里用DefinePlugin
分别定义好IS_PRODUCTION
的值,咱们就能够在业务代码里进行判断了:
/* global IS_PRODUCTION:true */ if (!IS_PRODUCTION) { console.log('若是你看到这个Log,那么这个版本其实是开发用的版本'); }
须要注意的是,若是你在webpack里整合了ESLint,那么,因为ESLint会检测没有定义的变量(ESLint要求使用全局变量时要用window.xxxxx
的写法),所以须要一个global
注释声明(/* global IS_PRODUCTION:true */
)IS_PRODUCTION是一个全局变量(固然在本例中并非)来规避warning。
诸位看本系列文章,搭配我在Github上的脚手架项目食用更佳哦(笑):Array-Huang/webpack-seed(https://github.com/Array-Huang/webpack-seed
)。
https://segmentfault.com/a/1190000006843916
https://segmentfault.com/a/1190000006863968
https://segmentfault.com/a/1190000006871991
https://segmentfault.com/a/1190000006887523
https://segmentfault.com/a/1190000006897458
https://segmentfault.com/a/1190000006907701
https://segmentfault.com/a/1190000006952432
https://segmentfault.com/a/1190000006992218
https://segmentfault.com/a/1190000007030775
https://segmentfault.com/a/1190000007043716
https://segmentfault.com/a/1190000007104372
https://segmentfault.com/a/1190000007126268
https://segmentfault.com/a/1190000007159115
本文首发于 Array_Huang的技术博客——实用至上
,非经做者赞成,请勿转载。
原文地址: http://www.javashuo.com/article/p-gfjsypje-kc.html
若是您对本系列文章感兴趣,欢迎关注订阅这里:https://segmentfault.com/blog/array_huang