點燈坊

失くすものさえない今が強くなるチャンスよ

Vue CLI 之 Mode 與 .env

Sam Xiao's Avatar 2023-01-14

實務上一定會遇到在不同 server ( developmentlabstagingproduction) ,且各有各的 環境變數,該如何設定這些環境變數並且自動切換呢 ?

Version

Vue 2.5.17
Vue CLI 3.0.3

Modes

Vue CLI 內建 3 種 mode:

  • development:執行 yarn serveyarn lint 時使用此模式
  • productionyarn buildyarn test:e2e 使用此模式
  • testyarn test:unit 使用此模式

我們也可以自行新增 mode,如 labstaging

.env

  • .env:所有 mode 都會載入
  • env.local:所有 mode 都會載入,但不會進 Git,適合每個人本機自行設定
  • **env.[mode]**:特定 mode 會載入
  • env.[mode].local:特定 mode 會載入,但不會進 Git,適合每個人本機自行設定

若 key 同時存在 .env.env.[mode]env.[mode].local 時,則其載入順序為:

.env => env.[mode] => env.[mode].local

也就是其優先權為:

env.[mode].local > env.[mode] > .env

.env.development.local

NODE_ENV=development
VUE_APP_API="https://jsonplaceholder.typicode.com"
  • NODE_ENV:指定使用 Vue CLI 內建的 3 個 mode 之一
  • VUE_APP_API:所有變數以 VUE_APP_ 為開頭
console.log(process.env.VUE_APP_API);

任何在 .env 所設定的變數,可以使用 process.env.VUE_APP_xxx 讀取。

Examples

  1. 前後端分離後,當 API spec 定義好,前後端就可以同時進行開發,此時後端的 API 還沒開發好,前端可根據 API spec 的 example 製造 假 API 先行開發
  2. 執行 e2e testing 時,由於實際打 真 API 的測試速度較慢,因此會希望只打 local 的 假 API,加快測試速度
  3. 希望開發時期的 假 API 能留下來進 Git,將來就能透過 CLI 切換使用 真 API假 API,不用修改 code
  • 使用 Node.js 建立假 API
  • 使用 .env 切換 API

Node.js for Fake API

Install Packages

$ yarn add express cors
  • 安裝 express framework。
  • 安裝 express 的解 CORS 套件。

Fake API

node/index.js

let express = require('express')
let cors = require('cors')

let data = require('./todos.json')

let app = express().use(cors())
let hostname = '127.0.0.1'
let port = 3000

app.get('/todos', (req, res) => res.send(data))

app.listen(port, () =>
  console.log(`Serving running at http://${hostname}:${port}/`))

Line 1

let express = require('express')

Import express module。

Line 2

let cors = require('cors')

Import cors module。

Line 4

let data = require('./todos.json')

Import 假 API 回傳的 JSON。

Line 6

let app = express().use(cors())

使用 express() 建立 app,並且 use cors() 所建立的物件。

Line 7

let hostname = '127.0.0.1'
let port = 3000

定義 hostname 位置與 port。

Line 10

app.get('/todos', (req, res) => res.send(data))

/todos 設定為 GET,其回傳資料由 JSON 所提供。

Line 12

app.listen(port, () =>
  console.log(`Serving running at http://${hostname}:${port}/`));

使用 app.listen() 啟動 Node.js 服務。

node/todos.json

{
  "todos": [
    {
      "userId": 1,
      "id": 1,
      "title": "delectus aut autem",
      "completed": false
    },
    {
      "userId": 1,
      "id": 2,
      "title": "quis ut nam facilis",
      "completed": false
    },
    {
      "userId": 1,
      "id": 3,
      "title": "fugiat veniam minus",
      "completed": false
    },
    {
      "userId": 1,
      "id": 4,
      "title": "et porro tempora",
      "completed": true
    },
    {
      "userId": 1,
      "id": 5,
      "title": "laboriosam mollitia et enim quasi",
      "completed": false
    },
    {
      "userId": 1,
      "id": 6,
      "title": "qui ullam ratione quibusda",
      "completed": false
    }
  ]
}

Switch API

Environment Variables

.env

NODE_ENV=production
  • 整個專案的 .env,會進 Git

  • NODE_ENV 預設為 Vue CLI 的 production mode

.env.development

NODE_ENV=development
VUE_APP_API="https://jsonplaceholder.typicode.com"
  • 設定 development mode 的 .env,會進 Git

  • NODE_ENV 設定為 Vue CLI 的 development mode

  • VUE_APP_API 變數為 真 API 位址

.env.development.local

NODE_ENV=development
VUE_APP_API="http://localhost:3000"
  • 設定 development mode 的 env不會 進 Git

  • NODE_ENV 設定為 Vue CLI 的 development mode

  • VUE_APP_API 變數為 假 API 位址

因為 .env.development.local 不會進 Git,自己開發用的環境變數可以設定在此

.env.lab

NODE_ENV=development
VUE_APP_API="https://jsonplaceholder.typicode.com"
  • 設定 lab mode,此為自訂的新 mode,會進 Git
  • NODE_ENV 設定為 Vue CLI 的 production mode
  • VUE_APP_API 變數為 真 API 位址

Read .env

api/todo.api.js

import axios from 'axios'

let API = process.env.VUE_APP_API

export let fetchTodos = () => axios.get(`${API}/todos`)

Line 3

let API = process.env.VUE_APP_API;

使用 process.env.VUE_APP_API 讀取 .envVUE_APP_API 變數。

Use Fake API

package.json

{
  "name": "vue-todo-lis-api",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint",
    "api": "node ./node/index.js"
  },
  "dependencies": {
    "axios": "^0.18.0",
    "cors": "^2.8.4",
    "express": "^4.16.4",
    "vue": "^2.5.17"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "^3.0.3",
    "@vue/cli-plugin-eslint": "^3.0.3",
    "@vue/cli-service": "^3.0.3",
    "@vue/eslint-config-airbnb": "^3.0.5",
    "vue-template-compiler": "^2.5.17"
  }
}

Line 9

"api": "node ./node/index.js"

輸入 yarn api 將執行 Node.js 的 假 API

$ yarn api
  • 執行 假 API
$ yarn serve
  • yarn serve 會使用 development mode,因為有提供 .env.development.local,所以 VUE_APP_API 應為 http://localhost:3000,也就是 假 API

Use Real API

$ yarn serve --mode lab
  • yarn serve 使用 lab mode,也就是 真 API

.env.development.local.sample

NODE_ENV=development
VUE_APP_API="http://localhost:3000"

由於 env.local.sample 沒有進 Git,其他人直接 git clone 下整個專案時,會因為不會設定 .env.development.local,導致無法執行 假 API 模式,可另外提供 .env.development.local.sample,此檔會進 Git,在自行由 .env.development.local.sample 命名為 .env.development.local 即可。

Conclusion

  • 透過 Node.js,就可解決 JSON Server 無法建立 POST 回傳資料的問題,因為 JSON Server 是純 RESTful
  • 靈活的運用 .env.development.local yarn serve --mode,就可靈活的切換 假 API真 API
  • 可將 .env.development.local.sample 也存進 Git,如此其他人 git clone 下來,可根據此檔建立 .env.development.local

Reference

Vue CLI, Environment Variables and Modes