DefinePlugin 用來做定義,這就類似於我們項目開發中的config文件一樣,在config文件中一般放的是系統代碼中的一些服務器地址之類的公共信息,我們將這些信息提取出來單獨放在配置文件中,方便於後期的維護和管理。
那 DefinePlugin 的功能和 config 這個文件類似,我們可以在它裏面定義一些公有信息,然後在代碼裏直接使用。
一、DefinePlugin
先來看看在Webpack的官方定義:
DefinePlugin 允許創建一個在編譯時可以配置的全局常量。這可能會對開發模式和生產模式的構建允許不同的行爲非常有用。如果在開發構建中,而不在發佈構建中執行日誌記錄,則可以使用全局常量來決定是否記錄日誌。這就是 DefinePlugin 的用處,設置它,就可以忘記開發環境和生產環境構建的規則。
1、用法
每個傳進 DefinePlugin 的鍵值都是一個標誌符或者多個用 . 連接起來的標誌符。
(1)如果這個值是一個字符串,它會被當作一個代碼片段來使用。
(2)如果這個值不是字符串,它會被轉化爲字符串(包括函數)。
(3)如果這個值是一個對象,它所有的 key 會被同樣的方式定義。
(4)如果在一個 key 前面加了 typeof,它會被定義爲 typeof 調用。
這些值會被內聯進那些允許傳一個代碼壓縮參數的代碼中,從而減少冗餘的條件判斷。
new webpack.DefinePlugin({
PRODUCTION: JSON.stringify(true),
VERSION: JSON.stringify('5fa3b9'),
BROWSER_SUPPORTS_HTML5: true,
TWO: '1+1', 'typeof window': JSON.stringify('object'), 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
});
console.log('Running App version ' + VERSION); if(!BROWSER_SUPPORTS_HTML5) require('html5shiv');
注意,因爲這個插件直接執行文本替換,給定的值必須包含字符串本身內的實際引號。通常,有兩種方式來達到這個效果,使用 '"production"'
, 或者使用 JSON.stringify('production')
。
2、官網中說的:“可以使用這個插件定義一些編譯時的全局常量”
編譯時這幾個字很重要,webpack會根據配置文件將將入口文件解析、打包、轉譯爲瀏覽器可識別的js文件最後輸出到出口,而他轉譯的過程其實就是webpack編譯過程,也就是官網說的編譯時。
3、官網中說的:“插件會直接替換文本”
在編譯過程中(轉譯爲瀏覽器可識別的js文件時),會將源文件中所有用到DefinePlugin中定義的常量的地方直接替換爲對應的值文本,注意,是文本無論語義上是對象還是字符串還是函數,都直接作爲文本替換過去。
4、示例使用
//1、假設在配置文件中定義編譯時全局常量 process.env.firstName
new webpack.DefinePlugin({ 'process.env.firstName': JSON.stringify("Test")
}); //源文件index.js內容如下
console.log(process.env.firstName) //最終轉譯後的js文件
console.log('Test')
可以看到,在編譯生成新js文件時,將process.env.firstName常量直接替換成了他對應的值文本
//2、假設在配置文件中定義編譯時全局常量 process.env.info
new webpack.DefinePlugin({ 'process.env.info': JSON.stringify({
ame:'Test',
age:23 })
}); //源文件index.js內容如下
console.log(process.env);
console.log(process.env.info) //最終轉譯後的js文件
console.log(process.env);
console.log({
name:'Test',
age:23 })
可以看到,在編譯生成新js文件時,將process.env.info常量直接替換成了他對應的值文本,而process.env沒有被替換,因爲沒有在DefinePlugin中定義process.env
運行最終轉譯後的js文件時,process.env指向的是Node中的process,在process.env中找不到info屬性,足以證明在DefinePlugin定義的process.env.info和Node的process沒有任何關係,他只是一個在插件中定義的編譯時的常量,編譯後就已經被替換了。
因此理解清楚概念,他只是個編譯時的常量,轉譯後就會被替換,只是恰好常量的名字是process.env.info。
二、webpack.DefinePlugin與cross-env區別詳解
webpack.DefinePlugin與cross-env常用於在項目工程化中定義環境變量:
1、webpack.DefinePlugin 用於在編譯期定義環境變量,意味着在代碼中寫上 process.env.NODE_ENV 不會在編譯期出現錯誤提醒;
2、cross-env 庫用於在運行時定義環境變量
3、問題場景:爲什麼要使用 cross-env 庫?
在進行“NODE_ENV=development webpack”配置時候,在大多數Windows命令行中在使用NODE_ENV = production設置環境變量時會報錯。同樣Windows和Linux命令如何設置環境變量也有所不同。所以需要使用 cross-env 庫來支持跨平臺設置和使用環境變量的腳本,這樣可以設置在不同的平臺上有相同的NODE_ENV參數。
4、DefinePlugin 用途:
根據不同的環境進行不同的配置,如不同環境的域名不同,我們就可以利用 DefinePlugin(https://www.webpackjs.com/plugins/define-plugin/)進行配置
// config/env.js 配置文件
const env = process.env.NODE_ENV; const config = {
development: {
loginApi: 'www.abc-login-test.com',
orderApi: 'www.abc-order-test.com' },
production: {
loginApi: 'www.abc-login.com',
orderApi: 'www.abc-order.com' }
};
module.exports = config[env]; // webpack.config.js
const envConfig= require('./config/env');
module.exports = {
plugins: [ new webpack.DefinePlugin({
envConfig: JSON.stringify(envConfig)
})
]
} // 這樣就可以使用不同的結果