摘要:開發(fā)環(huán)境和生產(chǎn)環(huán)境都擁有的配置,但在細(xì)節(jié)上有所不同,比如說,又比如說中的和參數(shù)。更重要的是,實(shí)際上開發(fā)環(huán)境和生產(chǎn)環(huán)境的配置文件的絕大部分都是一致的,對于這一致的部分來說,我們堅(jiān)決要消除冗余,否則后續(xù)維護(hù)起來不僅麻煩,而且還容易出錯(cuò)。
本文首發(fā)于Array_Huang的技術(shù)博客——實(shí)用至上,非經(jīng)作者同意,請勿轉(zhuǎn)載。前言
原文地址:https://segmentfault.com/a/1190000006952432
如果您對本系列文章感興趣,歡迎關(guān)注訂閱這里:https://segmentfault.com/blog/array_huang
開發(fā)環(huán)境與生產(chǎn)環(huán)境分離的原因如下:
在開發(fā)時(shí),不可避免會產(chǎn)生大量debug又或是測試的代碼,這些代碼不應(yīng)出現(xiàn)在生產(chǎn)環(huán)境中(也即不應(yīng)提供給用戶)。
在把頁面部署到服務(wù)器時(shí),為了追求極致的技術(shù)指標(biāo),我們會對代碼進(jìn)行各種各樣的優(yōu)化,比如說混淆、壓縮,這些手段往往會徹底破壞代碼本身的可讀性,不利于我們進(jìn)行debug等工作。
數(shù)據(jù)源的差異化,比如說在本地開發(fā)時(shí),讀取的往往是本地mock出來的數(shù)據(jù),而正式上線后讀取的自然是API提供的數(shù)據(jù)了。
如果硬是要在開發(fā)環(huán)境和生產(chǎn)環(huán)境用完全一樣的代碼,那么必然會付出沉重的代價(jià),這點(diǎn)想必也不用多說了。
下面主要針對兩點(diǎn)來介紹如何分離開發(fā)環(huán)境和生產(chǎn)環(huán)境:一是如何以不同的方式進(jìn)行編譯,也即如何分別形成開發(fā)環(huán)境及生產(chǎn)環(huán)境的webpack配置文件;二是在業(yè)務(wù)代碼中如何根據(jù)環(huán)境的不同而做出不同的處理。
如何分離開發(fā)環(huán)境和生產(chǎn)環(huán)境的webpack配置文件如果同時(shí)把一份完整的開發(fā)環(huán)境配置文件和一份完整的生產(chǎn)環(huán)境配置文件列在一起進(jìn)行比較,那么會出現(xiàn)以下三種情況:
開發(fā)環(huán)境有的配置,生產(chǎn)環(huán)境不一定有,比如說開發(fā)時(shí)需要生成sourcemap來幫助debug,又或是熱更新時(shí)使用到的HotModuleReplacementPlugin。
生產(chǎn)環(huán)境有的配置,開發(fā)環(huán)境不一定有,比如說用來混淆壓縮js用的UglifyJsPlugin。
開發(fā)環(huán)境和生產(chǎn)環(huán)境都擁有的配置,但在細(xì)節(jié)上有所不同,比如說output.publicPath,又比如說css-loader中的minimize和autoprefixer參數(shù)。
更重要的是,實(shí)際上開發(fā)環(huán)境和生產(chǎn)環(huán)境的配置文件的絕大部分都是一致的,對于這一致的部分來說,我們堅(jiān)決要消除冗余,否則后續(xù)維護(hù)起來不僅麻煩,而且還容易出錯(cuò)。
怎么做呢?答案很簡單:分拆webpack配置文件成N個(gè)小module。原先我們是一個(gè)完整的配置文件,有好幾百行,從頭看到尾都頭大了,更別說分離不分離的了。下面來看看我分離的結(jié)果:
├─webpack.dev.config.js # 開發(fā)環(huán)境的webpack配置文件(無實(shí)質(zhì)內(nèi)容,僅為組織整理) ├─webpack.config.js # 生產(chǎn)環(huán)境的webpack配置文件(無實(shí)質(zhì)內(nèi)容,僅為組織整理) ├─webpack-config # 存放分拆后的webpack配置文件 ├─entry.config.js # webpack配置中的各個(gè)大項(xiàng),這一級目錄里的文件都是 ├─module.config.js ├─output.config.js ├─plugins.dev.config.js # 倆環(huán)境配置中不一致的部分,此文件由開發(fā)環(huán)境配置文件webpack.dev.config.js來加載 ├─plugins.product.config.js # 倆環(huán)境配置中不一致的部分,此文件由生產(chǎn)環(huán)境配置文件webpack.config.js來加載 ├─resolve.config.js │ ├─base # 主要是存放一些變量 │ ├─dir-vars.config.js │ ├─page-entries.config.js │ ├─inherit # 存放生產(chǎn)環(huán)境和開發(fā)環(huán)境相同的部分,以供繼承 │ ├─plugins.config.js │ └─vendor # 存放webpack兼容第三方庫所需的配置文件 ├─eslint.config.js ├─postcss.config.js
文件目錄結(jié)構(gòu)看過了,接下來看一下我是如何組織整理最后的配置文件的:
/* 開發(fā)環(huán)境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"), };
這樣,你就可以很輕松地處理開發(fā)/生產(chǎn)環(huán)境配置文件中相同與不同的部分了。
如何分別調(diào)用開發(fā)/生產(chǎn)環(huán)境的配置文件呢?還記得我在《webpack多頁應(yīng)用架構(gòu)系列(二):webpack配置常用部分有哪些?》里講過,我們在控制臺調(diào)用webpack命令來啟動(dòng)打包時(shí),可以添加上--config參數(shù)來指定webpack配置文件的路徑嗎?我們可以配合上npm scripts來使用,在package.json里定義:
"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" },
這樣一來,當(dāng)我們開發(fā)的時(shí)候就可以使用npm run dev或npm run watch,而到要上線打包的時(shí)候就運(yùn)行npm run build。
業(yè)務(wù)代碼如何判斷生產(chǎn)/開發(fā)環(huán)境在業(yè)務(wù)代碼里要判斷生產(chǎn)/開發(fā)環(huán)境其實(shí)很簡單,只需一個(gè)變量即可:
if (IS_PRODUCTION) { // 做生產(chǎn)環(huán)境該做的事情 } else { // 做開發(fā)環(huán)境該做的事情 }
這么一來,關(guān)鍵就在于這變量IS_PRODUCTION是怎么來的了。
在我還沒分離開發(fā)和生產(chǎn)環(huán)境時(shí),我用的辦法是,開發(fā)時(shí)在業(yè)務(wù)代碼所使用的配置文件中把這變量設(shè)為false,而在最后打包上線時(shí)就手動(dòng)改為true。這種方法我用過一段時(shí)間,非常繁瑣,而且經(jīng)常上線后發(fā)現(xiàn),我嘞個(gè)去怎么ajax讀的是我本地的mock服務(wù)器。
怎么做呢?我參考了許多文章,先粗略講講我沒有采用的方法:
用EnvironmentPlugin引入process.env,這樣就可以在業(yè)務(wù)代碼中靠process.env.NODE_ENV來判斷了。
用ProvidePlugin來控制在不同環(huán)境里加載不同的配置文件(業(yè)務(wù)代碼用的)。
那我用的是什么方法呢?我最后選用的是DefinePlugin。
舉個(gè)官方例子,其大概用法是這樣的:
new webpack.DefinePlugin({ PRODUCTION: JSON.stringify(true), VERSION: JSON.stringify("5fa3b9"), BROWSER_SUPPORTS_HTML5: true, TWO: "1+1", "typeof window": JSON.stringify("object") })
DefinePlugin可能會被誤認(rèn)為其作用是在webpack配置文件中為編譯后的代碼上下文環(huán)境設(shè)置全局變量,但其實(shí)不然。它真正的機(jī)制是:DefinePlugin的參數(shù)是一個(gè)object,那么其中會有一些key-value對。在webpack編譯的時(shí)候,會把業(yè)務(wù)代碼中沒有定義(使用var/const/let來預(yù)定義的)而變量名又與key相同的變量(直接讀代碼的話的確像是全局變量)替換成value。例如上面的官方例子,PRODUCTION就會被替換為true;VERSION就會被替換為"5fa3b9"(注意單引號);BROWSER_SUPPORTS_HTML5也是會被替換為true;TWO會被替換為1+1(相當(dāng)于是一個(gè)數(shù)學(xué)表達(dá)式);typeof window就被替換為"object"了。
再舉個(gè)例子,比如你在代碼里是這么寫的:
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")
如此一來,只要在倆環(huán)境的配置文件里用DefinePlugin分別定義好IS_PRODUCTION的值,我們就可以在業(yè)務(wù)代碼里進(jìn)行判斷了:
/* global IS_PRODUCTION:true */ if (!IS_PRODUCTION) { console.log("如果你看到這個(gè)Log,那么這個(gè)版本實(shí)際上是開發(fā)用的版本"); }
需要注意的是,如果你在webpack里整合了ESLint,那么,由于ESLint會檢測沒有定義的變量(ESLint要求使用全局變量時(shí)要用window.xxxxx的寫法),因此需要一個(gè)global注釋聲明(/* global IS_PRODUCTION:true */)IS_PRODUCTION是一個(gè)全局變量(當(dāng)然在本例中并不是)來規(guī)避warning。
示例代碼諸位看本系列文章,搭配我在Github上的腳手架項(xiàng)目食用更佳哦(笑):Array-Huang/webpack-seed(https://github.com/Array-Huang/webpack-seed)。
附系列文章目錄(同步更新)webpack多頁應(yīng)用架構(gòu)系列(一):一步一步解決架構(gòu)痛點(diǎn):https://segmentfault.com/a/1190000006843916
webpack多頁應(yīng)用架構(gòu)系列(二):webpack配置常用部分有哪些?:https://segmentfault.com/a/1190000006863968
webpack多頁應(yīng)用架構(gòu)系列(三):怎么打包公共代碼才能避免重復(fù)?:https://segmentfault.com/a/1190000006871991
webpack多頁應(yīng)用架構(gòu)系列(四):老式j(luò)Query插件還不能丟,怎么兼容?:https://segmentfault.com/a/1190000006887523
webpack多頁應(yīng)用架構(gòu)系列(五):聽說webpack連less/css也能打包?:https://segmentfault.com/a/1190000006897458
webpack多頁應(yīng)用架構(gòu)系列(六):聽說webpack連圖片和字體也能打包?:https://segmentfault.com/a/1190000006907701
webpack多頁應(yīng)用架構(gòu)系列(七):開發(fā)環(huán)境、生產(chǎn)環(huán)境傻傻分不清楚?:https://segmentfault.com/a/1190000006952432
webpack多頁應(yīng)用架構(gòu)系列(八):教練我要寫ES6!webpack怎么整合Babel?:https://segmentfault.com/a/1190000006992218
webpack多頁應(yīng)用架構(gòu)系列(九):總有刁民想害朕!ESLint為你阻擊垃圾代碼:https://segmentfault.com/a/1190000007030775
webpack多頁應(yīng)用架構(gòu)系列(十):如何打造一個(gè)自定義的bootstrap:https://segmentfault.com/a/1190000007043716
webpack多頁應(yīng)用架構(gòu)系列(十一):預(yù)打包Dll,實(shí)現(xiàn)webpack音速編譯:https://segmentfault.com/a/1190000007104372
webpack多頁應(yīng)用架構(gòu)系列(十二):利用webpack生成HTML普通網(wǎng)頁&頁面模板:https://segmentfault.com/a/1190000007126268
webpack多頁應(yīng)用架構(gòu)系列(十三):構(gòu)建一個(gè)簡單的模板布局系統(tǒng):https://segmentfault.com/a/1190000007159115
webpack多頁應(yīng)用架構(gòu)系列(十四):No復(fù)制粘貼!多項(xiàng)目共用基礎(chǔ)設(shè)施
webpack多頁應(yīng)用架構(gòu)系列(十五):論前端如何在后端渲染開發(fā)模式下夾縫生存
webpack多頁應(yīng)用架構(gòu)系列(十六):善用瀏覽器緩存,該去則去,該留則留
本文首發(fā)于Array_Huang的技術(shù)博客——實(shí)用至上,非經(jīng)作者同意,請勿轉(zhuǎn)載。
原文地址:https://segmentfault.com/a/1190000006952432
如果您對本系列文章感興趣,歡迎關(guān)注訂閱這里:https://segmentfault.com/blog/array_huang
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/80419.html
摘要:本文首發(fā)于的技術(shù)博客實(shí)用至上,非經(jīng)作者同意,請勿轉(zhuǎn)載。原文地址如果您對本系列文章感興趣,歡迎關(guān)注訂閱這里這系列文章講什么本系列文章主要介紹如何用這一當(dāng)前流行的構(gòu)建工具來設(shè)計(jì)一個(gè)多頁應(yīng)用的架構(gòu)。 本文首發(fā)于Array_Huang的技術(shù)博客——實(shí)用至上,非經(jīng)作者同意,請勿轉(zhuǎn)載。原文地址:https://segmentfault.com/a/1190000006843916如果您對本系列文章...
摘要:在上一篇文章多頁應(yīng)用架構(gòu)系列二配置常用部分有哪些中,我介紹了如何配置多頁應(yīng)用的入口,然而,如果僅僅如此操作,帶來的后果就是,打包生成出來的每一個(gè)入口文件都會完整包含所有代碼。的初始化常用參數(shù)有哪些,給這個(gè)包含公共代碼的命個(gè)名唯一標(biāo)識。 本文首發(fā)于Array_Huang的技術(shù)博客——實(shí)用至上,非經(jīng)作者同意,請勿轉(zhuǎn)載。原文地址:https://segmentfault.com/a/1190...
摘要:本文首發(fā)于的技術(shù)博客實(shí)用至上,非經(jīng)作者同意,請勿轉(zhuǎn)載。只是最近學(xué)習(xí)生態(tài),用起來轉(zhuǎn)換之余,也不免碰到諸多用上的教程案例,因此便稍作學(xué)習(xí)。在當(dāng)前的瀏覽器市場下,想在生產(chǎn)環(huán)境用上,是必不可少的。 本文首發(fā)于Array_Huang的技術(shù)博客——實(shí)用至上,非經(jīng)作者同意,請勿轉(zhuǎn)載。原文地址:https://segmentfault.com/a/1190000006992218如果您對本系列文章感興...
摘要:本文首發(fā)于的技術(shù)博客實(shí)用至上,非經(jīng)作者同意,請勿轉(zhuǎn)載。如果你使用了,或類似的,那么,通過編譯前后的代碼相差就很大了,這會造成兩個(gè)問題以為例把你的代碼轉(zhuǎn)成什么樣你自己是無法控制的,這往往導(dǎo)致無法通過的審查。 本文首發(fā)于Array_Huang的技術(shù)博客——實(shí)用至上,非經(jīng)作者同意,請勿轉(zhuǎn)載。原文地址:https://segmentfault.com/a/1190000007030775如果您...
摘要:本文首發(fā)于的技術(shù)博客實(shí)用至上,非經(jīng)作者同意,請勿轉(zhuǎn)載。原文地址如果您對本系列文章感興趣,歡迎關(guān)注訂閱這里前言書承上文多頁應(yīng)用架構(gòu)系列十如何打造一個(gè)自定義的。終于,發(fā)現(xiàn)了這一大殺器,打包時(shí)間過長的問題得到完美解決。 本文首發(fā)于Array_Huang的技術(shù)博客——實(shí)用至上,非經(jīng)作者同意,請勿轉(zhuǎn)載。原文地址:https://segmentfault.com/a/119000000710437...
閱讀 2342·2021-09-30 09:47
閱讀 2963·2019-08-30 11:05
閱讀 2536·2019-08-29 17:20
閱讀 1923·2019-08-29 13:01
閱讀 1731·2019-08-26 13:39
閱讀 1258·2019-08-26 13:26
閱讀 3214·2019-08-23 18:40
閱讀 1833·2019-08-23 17:09