條件編譯,是指 用同一套代碼和同樣的編譯構建過程,根據設置的條件,選擇性地編譯指定的代碼,從而輸出不同程序的過程。一般用在C++、Java、C#這樣的編譯執行語言。對於javascript,我們也可以使用基於webpack
的js-conditional-compile-loader
插件實現類似的條件編譯功能。
我們經常會遇到類似這樣的需求:
- 代碼需要根據運行環境,運行不同的代碼。比如,測試環境可以控制檯輸出一些信息,生產環境則不提示;同時又不希望輸出的代碼中存在判斷環境的if-else代碼使程序包體積增大。
- 項目交付給多個客戶使用,而某些客戶會有一些定製模塊。這些定製模塊只給特定用戶使用,不希望也一起打包在不相干客戶的程序包中,但也不希望給定製客戶單獨維護一個特殊項目而增加維護成本。
使用條件編譯的方法,可以優雅地解決這樣的問題,同時代碼維護方便,發佈的程序包中也不會有多餘的代碼存在。
插件原理
js-conditional-compile-loader插件是一個webpack的loader插件,它會在webpack處理js代碼之前,將js代碼根據設置的條件進行修改,去掉當前條件下不需要的代碼,保留需要的代碼,從而實現條件編譯的功能。
使用步驟
可參考這裏的中文文檔。
1. 安裝
npm i -D js-conditional-compile-loader
2. 配置webpack
在rules中爲js文件添加loader,作爲第一步處理js文件,並配置編譯條件。
module: {
rules: [
{
test: /\.js$/,
include: [resolve('src'), resolve('test')],
use: [
//step-2
'babel-loader?cacheDirectory',
//step-1
{
loader: 'js-conditional-compile-loader',
options: {
isDebug: process.env.NODE_ENV === 'development', // optional, this is default
myFlag: process.env.ENV_COMPANY === 'ALI', // any name, used for /* IFTRUE_myFlag ...js code... FITRUE_myFlag */
}
},
]
},
//other rules
]
}
3. 項目代碼中使用
插件支持IFDEBUG和IFTRUE兩個條件編譯指令。用法是:在js代碼的任意地方以/*IFDEBUG
或/*IFTRUE_xxx
開頭,以FIDEBUG*/
或FITRUE_xxx*/
結尾,中間是被包裹的js代碼。xxx是在webpack中指定的條件屬性名,如上面的myFlag。
舉個例子,我們用這樣的源代碼:
/* IFTRUE_forAlibaba */
var aliCode = require('./ali/alibaba-business.js')
aliCode.doSomething()
/* FITRUE_forAlibaba */
$state.go('win', {dir: menu.winId /*IFDEBUG , reload: true FIDEBUG*/})
當webpack中插件的options配置爲{isDebug: true, forAlibaba: true}
時,構建後輸出的內容:
var aliCode = require('./ali/alibaba-business.js')
aliCode.doSomething()
$state.go('win', {dir: menu.winId, reload: true })
當webpack中插件的options配置爲{isDebug: false, forAlibaba: false}
時,構建後輸出的內容爲:
$state.go('win', {dir: menu.winId})
如此便實現了條件編譯。結合命令參數關聯到環境變量,可以用命令參數指定不同的編譯條件。實際項目中可以按照你的需要盡情發揮。
這裏是個完整項目的例子,可供參考。