VueCLI3 应用程序 (nginx/docker) 使用环境特定变量

VueCLI3 app (nginx/docker) use environment specific variables

如何从 Vue 应用程序外部化使用 环境变量:

一些细节:

项目构建一次并部署到测试和实际环境。因此,我想外部化一些变量,这些变量 通过环境 发生变化(例如要调用的 URL、域、用户名等)。带有 VUE_APP_ 前缀的 .env 文件变体的经典用法无助于解决此问题,因为它们的值是在构建阶段注入到代码中的:它们一旦构建就不是变量。

试了一下,我发现了一个blog post making use of dotenv and some extra configuration; but I could not put it together with the configuration in this VueCLI 3 official guide。虽然解决方案不需要采用类似的方法,但我只是想出一条路。

可能不是有用的信息,但我打算在 Kubernetes 配置中的 Config Maps 中定义这些环境变量。

我想我已经完成了这个案子。我在这里留下决议。

  1. .env.development 中定义特定于环境的环境变量(用于开发目的),并将它们也添加到具有相应值的 Pod configuration 中。

  2. 在您的 Vue 项目源文件夹中的某处添加一个 configuration.js 文件。它将充当确定运行时是开发(本地)还是生产(容器)的包装器。就像显示的 here,但 importing/configuring dotenv 不是必需的:

    export default class Configuration {
      static get EnvConfig () {
        return {
          envKey1: '$ENV_KEY_1',
          envKey2: '$ENV_KEY_2'
        }
      }
    
      static value (key) {
        // If the key does not exist in the EnvConfig object of the class, return null
        if (!this.EnvConfig.hasOwnProperty(key)) {
          console.error(`Configuration: There is no key named "${key}". Please add it in Configuration class.`)
          return
        }
    
        // Get the value
        const value = this.EnvConfig[key]
    
        // If the value is null, return
        if (!value) {
          console.error(`Configuration: Value for "${key}" is not defined`)
          return
        }
    
        if (!value.startsWith('$VUE_APP_')) {
          // value was already replaced, it seems we are in production (containerized).
          return value
        }
    
        // value was not replaced, it seems we are in development.
        const envName = value.substr(1) // Remove $ and get current value from process.env
        const envValue = process.env[envName]
    
        if (!envValue) {
          console.error(`Configuration: Environment variable "${envName}" is not defined`)
          return
        }
    
        return envValue
      }
    }
    
    
  3. 创建一个 entrypoint.sh。经过一些修改,它看起来像这样:

    #!/bin/bash
    
    function join_by { local IFS=""; shift; echo "$*"; }
    
    # Find vue env vars
    vars=$(env | grep VUE_APP_ | awk -F = '{print "$"}')
    vars=$(join_by ',' $vars)
    echo "Found variables $vars"
    
    for file in /app/js/app.*;
    do
      echo "Processing $file ...";
    
      # Use the existing JS file as template
      cp $file $file.tmpl
      envsubst "$vars" < $file.tmpl > $file
      rm $file.tmpl
    done
    
    nginx -g 'daemon off;'
    
  4. 在您的 Dockerfile 中,为 运行 添加一个 CMD 上面的 entrypoint.sh 脚本 作为容器期间的引导脚本创作。这样,每次启动容器时,它都会从 pod 配置中获取环境变量,并将其注入 步骤 2.[=24= 中显示的配置 class ]

    # build stage
    FROM node:lts-alpine as build-stage
    
    # make the 'app' folder the current working directory
    WORKDIR /app
    
    # Copy package*.json and install dependencies in a separaate step to enable caching
    COPY package*.json ./
    RUN npm install
    
    # copy project files and folders to the current working directory
    COPY ./ .
    
    # install dependencies and build app for production with minification
    RUN npm run build
    
    # Production stage
    FROM nginx as production-stage
    
    RUN mkdir /app
    
    # copy 'dist' content from the previous stage i.e. build
    COPY --from=build-stage /app/dist /app
    
    # copy nginx configuration
    COPY nginx.conf /etc/nginx/nginx.conf
    
    # Copy the bootstrapping script to inject environment-specific values and pass it as argument current to entrypoint
    COPY entrypoint.sh entrypoint.sh
    
    # Make the file executable
    RUN chmod +x ./entrypoint.sh
    
    CMD ["./entrypoint.sh"]
    
    

最后,像 Configuration.value('envKey1') 一样使用我们的包装器配置 class 而不是 process.env。瞧!