【问题标题】:NextJS process.env.NEXT_PUBLIC variable is empty in productionNextJS process.env.NEXT_PUBLIC 变量在生产中为空
【发布时间】:2021-10-28 09:46:52
【问题描述】:

我有一个 NextJS “^11.1.2” 应用程序,它在 Dockerfile 中构建并通过 CI/CD 部署到生产环境。 但我的 process.env 变量没有呈现

我的客户端代码中有这个,应该在运行时呈现:

const PublicApiUrl = process.env.NEXT_PUBLIC_API_URL;

在我的 (Gitlab) CI/CD 管道中,我通过 AUTO_DEVOPS_BUILD_IMAGE_EXTRA_ARGS 添加了一些 --build-args,以及 ENVARG

AUTO_DEVOPS_BUILD_IMAGE_EXTRA_ARGS --build-arg=NEXT_PUBLIC_API_URL=https://my.api.com --build-arg=NEXT_PUBLIC_API_URL=https://my.api.com --build-arg=NEXT_PUBLIC_BUILDER_KEY=XXXXXX
NEXT_PUBLIC_API_URL=https://my.api.com
API_URL=https://my.api.com

Dockerfile

ARG API_URL
ENV API_URL=$API_URL
ARG NEXT_PUBLIC_API_URL
ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL
ARG NEXT_PUBLIC_BUILDER_KEY
ENV NEXT_PUBLIC_BUILDER_KEY=$NEXT_PUBLIC_BUILDER_KEY
RUN npm run build # which resolves in "build": "next build"

下面的这个值肯定是捡到的(我做了一个RUN env,可以看到变量在那里)。

这是我在 Kubernetes 的 configMap,它将 .env.local 文件挂载到容器中:

apiVersion: v1
kind: ConfigMap
metadata:
  name: frontend-env-local
  annotations:
    "helm.sh/resource-policy": keep
data:
  .env: |-
    NEXT_PUBLIC_API_URL=https://my.api.url
    API_URL=https://my.api.url

这是我的部署,它将configMap 作为.env.local 安装到容器中:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
  labels:
    app: frontend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: frontend
  template:
    metadata:
      labels:
        app: frontend
    spec:
      volumes:
      - configMap:
          defaultMode: 420
          items:
          - key: .env
            path: .env.local
          name: frontend-env-local
        name: frontend-env-local
      imagePullSecrets: 
        - name: gitlab-credentials
      containers:
        - name: frontend
          image: "registry.gitlab.com/myapp:latest"
          imagePullPolicy: Always
          ports:
            - name: http
              containerPort: 5000
              protocol: TCP
          volumeMounts:
          - mountPath: /app/.env.local
            name: frontend-env-local
            readOnly: true
            subPath: .env.local

当我在本地构建 next build 时,它可以工作并且我的变量被渲染。

但是当我推送、构建和部署它并运行应用程序时,它是一个空字符串:

const PublicApiUrl = "";

为什么 NextJS 无法识别变量?

我登录到生产(Kubernetes pod)终端并运行env。变量也存在。

任何想法为什么会发生这种情况?

【问题讨论】:

  • 你在用什么主机之类的?
  • @illiachill Kubernetes

标签: kubernetes next.js dockerfile gitlab-ci


【解决方案1】:

我还必须像这样在next.config.js 中定义变量:

module.exports = {
    serverRuntimeConfig: {
        API_URL: process.env.API_URL,
    },
    // Will be available on both server and client
    publicRuntimeConfig: {
        NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL,
    }
}

在那次更改之后,似乎既不需要 configMap 也不需要挂载的卷...只有我的 CI/CD 中的 --build-arg 以及 Dockerfile 中的 ARGENV

【讨论】:

    【解决方案2】:

    您不需要在 next.config.js 中定义变量 - 不好的做法。

    分别定义您的 env 文件

    当地人:

    您需要创建environments 文件夹,然后在此文件夹中创建您的.env.local;在这里你定义你的局部变量。 完成此操作后,在 package.json 文件中填写 scripts 部分:

    "scripts": {
        //you need to add this line - defining your .env.local file inside 
        "local": "env-cmd -f environments/.env.local node server.js",
        "build": "next build",
      },
    

    所以,在您使用 npm 命令启动 local server 后,将其设置为 npm run local

    对于您的服务器:

    您需要在您的服务器上以某种方式定义environment variables。在vercel上它在settings/environment variables

    附:您“缺少”process.env.NEXT_PUBLIC_API_URL 的值,因为 GitHub 通常会忽略 .env 文件 - 您更新了您的环境变量。您的文件 process.env.NEXT_PUBLIC_API_URL 在服务器上丢失,这就是为什么您有 null 值。

    【讨论】:

      【解决方案3】:

      如果您使用的是 Docker,请在构建项目之前检查 .env file 是否在 DockerFile 中。

      Example DockerFile:
      FROM node:16.14.0-alpine3.14 as build
      
      WORKDIR /app
      
      # Copy in only the parts needed to install dependencies
      # (This avoids rebuilds if the package.json hasn’t changed)
      COPY package.json  .
      COPY package-lock.json .
      COPY .env.production .
      
      # Install dependencies (including dev dependencies)
      RUN npm install
      
      # Copy in the rest of the project
      # (include node_modules in a .dockerignore file)
      COPY . .
      
      # Build the project
      RUN npm run build
      
      # Second stage: runtime
      FROM node:16.14.0-alpine3.14
      
      WORKDIR /app
      
      ENV NODE_ENV=production
      
      # Again get dependencies, but this time only install
      # runtime dependencies
      COPY package.json  .
      COPY package-lock.json .
      RUN npm install --only=production
      
      # Get the built application from the first stage
      COPY --from=build /app/.next/ /app/.next/
      
      # Set runtime metadata
      ENV PORT 3000
      EXPOSE 3000
      
      

      【讨论】:

        猜你喜欢
        • 2020-07-16
        • 2020-10-04
        • 2021-01-28
        • 1970-01-01
        • 1970-01-01
        • 2020-10-19
        • 2020-10-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多