前端 Vue 和后端 Node,TypeScript 实现三种环境下,使用不同的 API,如 开发环境下使用 “/dev-api”,线上测试环境下,使用“/test-api”。

前言

在开发中,可能会被要求在不同的环境中使用不同的配置,如端口号,请求地址,请求的API接口。
你可能知道 development、test、production 三种环境,分别对应开发环境、线上测试环境和生产环境。

三种环境对应的API可以为:

  • 开发模式 => /dev-api/...,例如:/dev-api/login
  • 生产模式 => /prod-api/...,例如:/prod-api/login
  • 演示模式 => /stage-api/...,例如:/stage-api/login

一、Vue 前端【Gitee 仓库

(一)Vue 默认指令与模式

在使用 Vue-cli 创建工程后,package.json 中默认指令如下:

"scripts": {
  "serve": "vue-cli-service serve",
  "build": "vue-cli-service build"
},

其中

  • serve 指令,即当你运行 npm run serve 时,默认的模式development
  • build 指令,即当你运行 npm run build 时,默认的模式production

类似于这样配置

"scripts": {
  "serve": "vue-cli-service serve --mode development",
  "build": "vue-cli-service build --mode production"
},

所以可以通过添加 --mode env 来指定环境变量。如下,添加test模式:

"scripts": {
  "build:test": "vue-cli-service serve --mode test"
},
npm run build:test

(二)环境变量

环境变量是什么?就是一个配置文件,里面提供了一些键值对的数据。

可以解决在不同环境中使用不同的配置,比如项目在开发环境、生产环境、线上测试环境时的请求API,请求 网址 不一样,这时候就可以通过使用环境变量文件来申明指定环境使用的配置。

更多说明看【Vue-cli 环境变量】文档

在 【vue-admin-template】Github文档中,就是用了三种不同模式下使用不同的API。如下:

  • 开发模式 => /dev-api/...,例如:/dev-api/login
  • 生产模式 => /prod-api/...,例如:/prod-api/login
  • 演示模式 => /stage-api/...,例如:/stage-api/login

在 Vue-cli 搭建的工程中,可以创建 .env.mode 的文件,配置不同模式下使用的环境变量。

比如,测试模式

// package.json 部分代码
"scripts": {
  "build:test": "vue-cli-service build --mode test"
}
// .env.test
ENV = 'test'
VUE_APP_BASE_API = '/test-api'

使用了上述代码后,你在工程中可以使用 process.env.key 来访问你环境变量。

console.log("环境:" + process.env.NODE_ENV);
console.log("base_api:" + process.env.VUE_APP_BASE_API);

--mode mode 指令和 .env.mode文件名中的 mode 名称一致,在编译时,Vue-cli 就会使用相对应的环境变量文件。

  • --mode development => .env.development
  • --mode production => .env.production
  • --mode test => .env.test

(三)项目查看

你可以分别使用

  • npm run dev
  • npm run build
  • npm run build:test

三个指令来运行工程,之后打开控制台,你会看到,使用三个不同的指令运行,login的请求地址将都会不一样。


二、NodeJS 后端【Gitee 仓库

说明:

  • 使用 NodeJS + Express 开发服务器,封装请求 API
  • 使用 cross-env 添加全局变量,区分模式
  • 使用 dotenv 加载 .env.mode文件。

依赖包:cross-env、dotenv、express、nodemon

(一)工程目录

|-- src
|   |-- env.js					// dotenv 加载 `.env.mode` 文件,并配置到 `process.env` 对象上。
|   |-- index.js				// 入口文件
|-- .env.development
|-- .env.production
|-- .env.test
|-- package.json

(二)具体实现

1. 代码

// env.js
const path = require("path")
const dotenv = require('dotenv')

const envFileName = path.resolve(__dirname, '../.env.' + process.env.NODE_ENV)

//  dotenv 加载指定 .env.{mode} 文件
dotenv.config({ path: envFileName })

// 这里可以删除
console.log(`模式:${process.env.NODE_ENV}`, `BASE_API:${process.env.BASE_API}`);
// index.js
const express = require("express")
// 运行 .env文件
require('./env')
const app = express();
const port = 3000;

// 处理根路径的 GET 请求
app.get('/', (req, res) => {
  res.send('Hello, World!');
});

// 处理自定义路由的 GET 请求
const BASE_API = process.env.BASE_API
app.get(`${BASE_API}/user`, (req, res) => {
  const user = { id: 1, name: 'John Doe', };
  res.json(user);
});

// 启动服务器
app.listen(port, () => {
  console.log(`访问: http://localhost:3000${BASE_API}/user`);
});
// .env.development
BASE_API = "/dev-api"

// .env.production
BASE_API = "/prod-api"

//  .env.test
BASE_API = "/test-api"

// package.json 部分代码
"scripts": {
  "dev": "cross-env NODE_ENV=development nodemon ./src/index.js",
  "start:prod": "cross-env NODE_ENV=production node ./src/index.js",
  "start:test": "cross-env NODE_ENV=test node ./src/index.js"
}

2. 语言描述

start:test指令为例

  1. 运行 npm run start:test 指令,值得关注的是 cross-env NODE_ENV=test,这时候会在全局对象process.env中添加NODE_ENV属性,值为 test,既 process.env.NODE_ENV = "test"
  2. 当执行到 node ./src/index.js时,会执行到 require('./env') ,这样会执行一遍 .env.js文件。
  3. .env.js 文件中,首先是根据 process.env.NODE_ENV 确认 .env.{mode}的文件路径,然后使用 dotenv.config({ path: envFileName }) 方法让 dotenv 加载文件,并解析环境变量
  4. 最后将解析的数据注入到全局 process.env对象上。这里注入了 process.env.BASE_API = "/test-api"。这意味着,你可以在工程中任何地方使用 process.env.BASE_API

三、TypeScript 后端

由于 TypeScript 需要有一个 tsc 编译阶段,而 tsc 只能将 .ts 文件编译至目标文件夹。这就意味着如果使用 dotenv 模块,加载 .env 环境变量方式时,在使用 tsc 编译原码.ts 文件时,.env文件将不会直接拷贝到dist目录。

为此使用,我提供了

  • 使用 .ts 环境配置文件的方式,区分不同环境下的不同配置。【Gitee 仓库 master
  • 使用 copyfiles 模块,在 tsc 编译完成后,将 .env 模块拷贝到 dist 目录。【Gitee 仓库 use-env-file

两种方式,适应不同的环境,提供不同的 API

两种方式的源码都在同一个仓库中,只是放在不同的分支中。


下面是使用 .ts 文件配置环境变量的方式。【Gitee 仓库 master

(一)工程目录

|-- dist							// 编译后,文件目录
|-- src								// TS 工程源码目录
|   |-- config
|   |   |-- dev.config.ts			// 开发环境 配置文件
|   |   |-- prod.config.ts		// 生产环境 配置文件
|   |   |-- test.config.ts		// 线上测试环境 配置文件
|   |   |-- index.ts
|   |-- index.js				// 入口文件
|-- package.json
|-- tsconfig.json

(二)具体实现

// dev.config.ts
const ENV = 'development'  	// 其他两个文件对应:production、test
const BASE_API = '/dev-api'  // 其他两个文件对应:'/prod-api'、'/test-api'

export {
  ENV,
  BASE_API
}

export default {
  ENV,
  BASE_API
}
// config/index.ts
import devConfig from './dev.config';
import testConfig from './test.config';
import prodConfig from './prod.config';

let config: any;

switch (process.env.NODE_ENV) {
  case 'development':
    config = devConfig;
    break;
  case 'test':
    config = testConfig;
    break;
  case 'production':
    config = prodConfig;
    break;
  default:
    throw new Error('Invalid NODE_ENV');
}

mountToEnv(config)

/**
 * 挂载到全局 process.env 对象上,这意味着,你在项目任何地方都可以使用 process.env.{key} 来访问你声明的环境变量。
 * @param config 
 */
function mountToEnv(config: object) {
  const values = Object.values(config)
  Object.keys(config).forEach((item: string, index: number) => {
    process.env[item] = values[index]
  })
}

export default config;

// index.ts
import express from 'express';
import config from "./config/index"
const app = express();
const port = 3000;

const BASE_API = config['BASE_API']

app.get('/', (req, res) => {
  res.send('Hello,113');
});

app.get(`${BASE_API}/user`, (req, res) => {
  res.send('user');
});

// this can delete
console.log(`env: ${config.ENV}, base-api:${config.BASE_API}`);

app.listen(port, () => {
  console.log(`访问: http://localhost:3000${BASE_API}/user`);
});

// package.json
"scripts": {
  "dev": "cross-env NODE_ENV=development nodemon --watch ./src/**/*.ts --exec ts-node ./src/index.ts",
  "build": "rd /s /q dist & tsc",
  "start:prod": "cross-env NODE_ENV=production node dist/index.js",
  "start:test": "cross-env NODE_ENV=test node dist/index.js"
},
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值