webpack.DefinePlugin與cross-env區別

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)
    })
  ]
} // 這樣就可以使用不同的結果
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章