Webpack配置環境變量

在實際項目開發中,須要基於多種環境去設置不一樣的環境變量以便於在構建階段或是運行階段去使用,例如常見的經過process.env.NODE_ENV在構建時去判斷當前的構建環境是development仍是production,例如須要在開發環境測試環境生產環境去訪問不一樣的接口服務器。html

爲了模擬真實的項目,使用webpack搭建了一個最小化的項目結構:前端

├─package.json
├─src
|  └index.jsx
├─public
|   └index.html
├─config
|   └webpack.config.js

Node環境變量

Node環境變量就是指process.env這個屬性node

process.env 是什麼?

它是 Nodejs 應用程序中,process.env 屬性,返回包含用戶環境的對象,因此它不能夠在客戶端側代碼中使用,也就不能在瀏覽器環境上使用。webpack

// process.env(官方示例)
{
  TERM: 'xterm-256color',
  SHELL: '/usr/local/bin/bash',
  USER: 'nodejscn',
  PATH: '~/.bin/:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin',
  PWD: '/Users/nodejscn',
  EDITOR: 'vim',
  SHLVL: '1',
  HOME: '/Users/nodejscn',
  LOGNAME: 'nodejscn',
  _: '/usr/local/bin/node'
}

修改Node環境變量

1. 修改 package.json 文件

使用 cross-env依賴包,支持跨平臺配置環境變量。git

// package.json
{
  ...,
  "scripts": {
    "start": "npm run dev",
    "dev": "cross-env NODE_ENV=development AAA=123 webpack serve --config ./config/webpack.config.js",
    "build:test": "cross-env NODE_ENV=test  webpack --config ./config/webpack.config.js",
    "build:pro": "cross-env NODE_ENV=production  webpack --config ./config/webpack.config.js"
  },
  ...
}

經過在package.json腳本中設置變量的方式來注入環境變量,同時cross-env還支持去設置多個環境變量,只須要經過空格區分,例如在dev腳本中設置的NODE_ENV=developmentAAA=123github

這樣在執行npm start就可以經過process.env獲取到對應的環境變量。web

// webpack.config.js
console.log("【process.env】", process.env.AAA);

可以在構建時的終端中打印出npm

可是在index.jsx中也就是瀏覽器環境下的文件中打印process.env就會報錯json

緣由就是前文提到的peocess.env是Node環境的屬性,瀏覽器環境不可以獲取到。讓瀏覽器環境獲取到所需變量咱們後文再說。vim

2. 經過.env文件注入

直接經過在script腳本中注入環境變量的方式不利於集中管理環境變量,並且在環境變量較多時這種方式也十分不友好,因此須要一種方式來集中管理這些環境變量。

使用dotenv依賴包可將環境變量從 .env 文件加載到 process.env

dotenv會默認加載根目錄的.env文件去注入環境變量,經過require('dotenv').config()便可完成注入。

//webpack.config.js
dotenv.config();

//.env文件
AAA=123

一樣也可以在終端中看到

dotenv多環境配置

在多環境配置時須要經過規定不一樣環境對應的.env文件,例如如今規定.env.test是測試環境對應的環境變量,.env.production是生產環境,.env是開發環境。而後經過dotenv.config({ path: })去加載對應文件的環境變量。

//webpack.config.js
const PROJECT_PATH = resolve(__dirname, "../");

const dotenvFile = resolve(PROJECT_PATH, `./.env.${process.env.NODE_ENV}`);

// 加載.env*文件  默認加載.env文件
dotenv.config({
  path: fs.existsSync(dotenvFile)
    ? dotenvFile
    : resolve(PROJECT_PATH, `./.env`),
});

console.log("【process.env】", process.env.ENV);

這裏process.env.NODE_ENV是爲了判斷當前的運行環境來去加載對應的.env文件。

// package.json
"scripts": {
  "start": "npm run dev",
  "dev": "cross-env NODE_ENV=development webpack serve --config ./config/webpack.config.js",
  "build:test": "cross-env NODE_ENV=test  webpack --config ./config/webpack.config.js",
  "build:pro": "cross-env NODE_ENV=production  webpack --config ./config/webpack.config.js"
}

//.env.production
ENV=pro

//.env
ENV=dev

執行npm start

執行npm run build:pro

能夠看到不一樣環境的變量確實已經注入成功。

瀏覽器環境變量

瀏覽器環境下也須要根據不一樣的環境變量來處理一些邏輯,可是它不能獲取到process.env因此不能像注入Node環境變量的方式來實現。瀏覽器環境變量是基於webpack.DefinePlugin這個插件在項目構建時引入的,引入以後能夠在前端代碼中全局獲取到對應的變量。

基礎使用方式是將所需的變量按鍵值對的方式傳入DefinePlugin中,須要注意的是變量值須要經過JSON.stringify進行包裹。

module.exports = {
  plugins: [
    new DefinePlugin({
        aaa: JSON.stringify("!!!!")
    })
  ]
}

執行腳本後能夠在index.jsx中獲得對應的結果

//index.jsx
console.log("【app】", aaa);
const App = () => {
  return <div>app</div>;
};

配置多環境的瀏覽器變量

瀏覽器環境中也須要根據項目環境來引入不一樣的變量,以前在Node環境中已經獲取到不一樣的環境變量,咱們能夠創建一個基於此的映射表在項目構建時根據拿到的Node環境變量來引入對應的瀏覽器環境變量。

// webpack.config.js

// 瀏覽器環境注入的變量
const define = {
  dev: {
    baseURL: "/api/dev",
  },
  test: {
    baseURL: "/api/test",
  },
  pro: {
    baseURL: "/api/pro",
  },
};

module.exports = {
  new DefinePlugin({
    "process.env": Object.keys(define[process.env.ENV]).reduce((env, key) => {
      env[key] = JSON.stringify(define[process.env.ENV][key]);
      return env;
    }, {}),
  }),
}

執行npm start,能夠在瀏覽器控制檯看到結果

執行npm run build:pro,在dist目錄開啓一個服務器,能夠在瀏覽器控制檯看到結果

在實際項目中根據不一樣環境切換接口服務器地址的場景中,就能經過這樣的方式來獲取到不一樣環境中的接口地址。

在UMI中去配置多環境變量

在平時開發中較常使用umi做爲項目框架,umi經過環境變量UMI_ENV區分不一樣環境來指定不一樣配置。

具體來講是經過腳本中注入的UMI_ENV=xxx去匹配對應的config.xxx.js配置文件,而後在define屬性中去配置須要引入瀏覽器環境的變量。

具體相關內容能夠看官方文檔多環境配置
代碼中可用的變量

// webpack.config.js
module.exports = {
  ...,
  "scripts": {
    "start": "cross-env UMI_ENV=dev umi dev",
    "build:test": "cross-env UMI_ENV=test umi build",
    "build:pre": "cross-env UMI_ENV=pre umi build",
    "build:pro": "cross-env UMI_ENV=pro umi build",
  }
  ...,
}

//config.dev.js
import { defineConfig } from 'umi';

export default defineConfig({
  define: {
    'process.env': {
      BASE_API: '/api/dev',
    },
  },
});
相關文章
相關標籤/搜索