1. 概述

现代 Web 应用通常需要在不修改代码的前提下灵活适应不同环境。对于许多 Vue.js 开发者来说,在运行时修改 API 密钥或基础 URL 等设置非常关键。因为默认情况下,环境变量是打包进构建产物中的,这限制了灵活性。

本文将探讨如何在 Vue 应用中运行时传递环境变量。我们会演示一个实用方案,动态注入这些变量,并配置应用读取它们。

2. 前置条件

开始之前,需准备好以下组件:

  • 已安装 Node.js 和 npm 或 yarn
  • 已安装 Docker 和 Docker Compose
  • 已注册 ExchangeRate API Key 用于运行货币转换项目

准备好后,我们就可以开始了。

3. 理解 Vue.js 中的运行时环境变量

Vue.js 与大多数前端框架一样,在构建时处理环境变量。应用构建时,*.env* 文件或 process.env 中的值会被直接嵌入到 JavaScript 打包文件中。这意味着在不重新构建应用的前提下,这些值无法更改。

这种机制在需要动态配置时会成为限制。例如,API 的基础 URL 或密钥可能在不同环境(开发、测试、生产)之间变化。如果这些变量是在构建时固定的,每次更改都需要重新构建和部署,效率低下且耗时。

此外,这种做法在多环境部署时也缺乏灵活性。设想将同一个应用部署到多个服务器上,每个服务器配置不同,若不能在运行时调整变量,会增加部署流程的复杂性。

4. 构建运行时环境配置

为了让 Vue.js 应用支持动态配置,我们需要一种机制,在运行时注入环境变量,而不是在构建时嵌入。我们可以通过生成、提供和集成运行时变量的设置来实现这一点。

这个方案主要涉及三个文件:config.jsentrypoint.shnginx.conf。在深入这些文件之前,我们先搭建一个基础项目,包含实现所需的基础文件和配置。

4.1. 克隆基础项目

首先,克隆基础项目仓库,它包含一个简单的 Vue.js 项目——一个货币转换器应用:

$ git clone https://github.com/Baeldung/ops-tutorials.git

进入项目目录:

$ cd ops-tutorials/docker-modules/passing-env-vars-to-vue-app-at-runtime/vue-env-vars-starter

安装依赖:

$ npm install

$ yarn install

运行 npm run dev,在浏览器中访问 http://localhost:5173 验证本地环境是否正常工作。

Starter project

4.2. 创建 config.js 文件

config.js 是运行时变量的来源。与构建时注入不同,这个文件在运行时动态生成,以反映当前环境。

在项目 public 目录下创建该文件:

$ touch public/config.js

打开文件,添加如下内容:

window.config = {};

这样即使变量尚未注入,应用也能正常加载。

接下来,在 index.html 中引用这个文件。打开 index.html,在 </body> 标签前插入以下脚本:

<script src="/config.js"></script>

这样每次访问应用时,都会加载 config.js

4.3. 创建和配置 entrypoint.sh 文件

entrypoint.sh 脚本用于在运行时将环境变量动态注入到 config.js。这种灵活性使得应用可以在不同环境(如开发、测试、生产)中运行,而无需重新构建。

在项目根目录创建该文件:

$ touch entrypoint.sh

打开文件并添加以下内容:

#!/bin/sh

# config.js 文件路径
CONFIG_FILE=/usr/share/nginx/html/config.js

# 替换 config.js 中的占位符
echo "生成运行时配置文件 $CONFIG_FILE"
cat <<EOF > $CONFIG_FILE
window.config = {
    VUE_APP_API_URL: "${VUE_APP_API_URL:-undefined}"
};
EOF

# 启动 Nginx
nginx -g "daemon off;"

这个脚本完成了几个关键功能

  • 定义了 config.js 的路径(位于 Nginx 服务目录中)
  • 使用 cat 命令将运行时变量写入 config.js
  • 占位符 ${VUE_APP_API_URL:-undefined} 会使用环境变量值,若未设置则为 undefined
  • 最后启动 Nginx,并以前台模式运行

4.4. 配置 nginx.conf

nginx.conf 是另一个关键配置文件。它确保 Nginx 正确提供 Vue.js 应用和动态生成的 config.js,并正确处理客户端路由。

在项目根目录创建该文件:

$ touch nginx.conf

添加如下配置:

worker_processes 1;

events {
    worker_connections 1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout 65;

    server {
        listen 80;

        server_name localhost;

        # 提供主应用
        location / {
            root /usr/share/nginx/html;
            index index.html;
            try_files $uri /index.html;
        }

        # 提供 config.js
        location /config.js {
            root /usr/share/nginx/html;
            default_type application/javascript;
        }
    }
}

这段配置优化了 Nginx 性能:

  • 设置 worker 进程和连接数
  • 第一个 location 块确保所有请求都通过 index.html 处理,这对 Vue.js 客户端路由至关重要
  • 第二个 location 块确保 config.js 作为 JavaScript 文件提供,以便应用在运行时加载使用

下一节我们将手动测试环境变量注入。

5. 手动注入环境变量

在容器化应用之前,我们先在本地环境中测试运行时变量注入功能

5.1. 准备环境

在项目根目录创建 .env 文件:

$ touch .env

添加如下内容:

VUE_APP_API_URL=https://v6.exchangerate-api.com/v6/API_KEY/latest/USD

这个变量将在运行时注入到应用中。

5.2. 运行 entrypoint.sh 脚本

现在使用 entrypoint.sh 脚本生成包含环境变量的 config.js 文件。

在运行前,需将 entrypoint.sh 中的 CONFIG_FILE 路径临时改为 ./public/config.js,因为本地测试时 /usr/share/nginx/html/config.js 不存在

修改如下:

CONFIG_FILE=./public/config.js

然后赋予脚本执行权限:

$ chmod +x entrypoint.sh

导出环境变量:

$ export VUE_APP_API_URL=https://v6.exchangerate-api.com/v6/API_KEY/latest/USD

运行脚本:

$ ./entrypoint.sh

脚本会在 public 目录下生成 config.js 文件。查看其内容应如下:

window.config = {
    VUE_APP_API_URL: "https://v6.exchangerate-api.com/v6/API_KEY/latest/USD"
};

确认无误后,记得将 CONFIG_FILE 路径改回 /usr/share/nginx/html/config.js 再进行容器化操作

6. 容器化应用

完成运行时环境配置后,现在我们将其容器化。

6.1. 创建 Dockerfile

Dockerfile 定义了将 Vue.js 应用构建并打包为容器的指令。我们将使用多阶段构建以减小最终镜像大小。

创建 Dockerfile

$ touch Dockerfile

添加如下内容:

# 构建阶段
FROM node:18-alpine as build-stage

RUN apk add --no-cache python3 make g++

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . .

RUN npm run build

# 生产阶段
FROM nginx:stable-alpine as production-stage

WORKDIR /usr/share/nginx/html

COPY --from=build-stage /app/dist /usr/share/nginx/html

COPY nginx.conf /etc/nginx/nginx.conf

COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

EXPOSE 80

CMD ["/entrypoint.sh"]

多阶段构建确保最终镜像只包含生产所需文件,优化大小和性能。

6.2. 配置 docker-compose.yml

docker-compose.yml 简化了容器管理流程,并提供一种便捷方式传入环境变量。

创建 docker-compose.yml 文件:

$ touch docker-compose.yml

添加如下内容:

version: "3.8"

services:
    vue-app:
        build:
            context: .
            dockerfile: Dockerfile
        ports:
            - "8080:80"
        env_file:
            - .env

该配置:

  • 指定构建上下文和 Dockerfile 路径
  • 映射主机 8080 端口到容器 80 端口
  • .env 文件加载环境变量

准备就绪后,即可构建并运行容器。

7. 测试运行时变量注入

配置好 docker-compose.yml 后,现在构建并运行容器化应用。

创建 .env 文件:

$ touch .env

添加如下内容:

VUE_APP_API_URL=https://v6.exchangerate-api.com/v6/your_api_key/latest/USD

⚠️ 请将 your_api_key 替换为你的实际 API Key

构建镜像:

$ docker-compose up --build

访问以下地址验证:

http://localhost:8080/config.js

应该看到如下内容:

window.config = {
    VUE_APP_API_URL: "https://v6.exchangerate-api.com/v6/your_api_key/latest/USD"
};

✅ 验证成功。

若需更新变量,修改 .env 文件后重启容器即可:

$ docker-compose down
$ docker-compose up

刷新 /config.js 确认更新生效。

至此,我们完成了容器化和运行时变量注入的整个流程。

8. 适配生产环境

现在我们已成功容器化并运行 Vue.js 应用,接下来探讨如何适配生产环境。

8.1. 生产环境中的环境变量管理

生产环境中,建议以下两种方式管理环境变量:

  1. 使用 .env 文件:适用于非敏感变量,敏感变量应使用更安全的方式管理,如 Docker Secrets
  2. Kubernetes 中使用 ConfigMap / Secrets:标准做法,用于管理非敏感(ConfigMap)和敏感(Secrets)数据。例如:
apiVersion: v1
kind: ConfigMap
metadata:
  name: vue-config
data:
  VUE_APP_API_URL: "https://api.production.example.com"

这些可以作为环境变量挂载到 Pod 中。

8.2. 无缝更新环境变量

根据部署平台,有以下更新方式:

  • Kubernetes:使用滚动更新策略逐步替换 Pod
  • Docker Compose / Swarm:使用蓝绿部署或最小中断重启服务

8.3. config.js 的缓存处理

生产环境中,缓存可能导致加载旧版本 config.js。可采取以下措施:

  • index.html 中添加时间戳参数:
<script src="./config.js?v=<%= Date.now() %>"></script>
  • 修改 Nginx 配置禁用缓存:
location /config.js {
    default_type application/javascript;
    add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0";
    return 200 "window.config = { VUE_APP_API_URL: '${VUE_APP_API_URL}' };";
}

8.4. 安全性保障

生产环境中,需重点关注以下安全措施:

  • 使用 AWS Secrets Manager、HashiCorp Vault 或 Kubernetes Secrets 存储敏感数据
  • config.js 包含敏感信息,限制 IP 或启用身份验证
  • 应用和配置均应通过 HTTPS 提供,防止中间人攻击

以上措施确保应用在生产环境中灵活、安全、可靠地运行。

9. 总结

本文演示了如何在 Vue.js 应用中运行时传递环境变量,解决了构建时配置的局限性。我们实现了一个实用方案,使应用无需重新构建即可动态注入和访问变量。同时,我们还容器化了应用,并探讨了如何适配生产环境。

这种方式确保应用在复杂部署环境中依然灵活易维护。

完整代码请参考 GitHub 仓库


原始标题:Passing Environment Variables to a Vue App at Runtime