盖茨比:环境变量 .env return 未定义

Gatsby: Environment variables .env return undefined

我正在开发一个静态网站,使用 Gatsby 进行开发,使用 Nginx 提供静态文件。

我还在使用 Docker 进行测试和生产部署,并使用 Traefik 将流量路由到 docker 应用程序的容器。

我在应用程序文件中定义了一个环境变量,该环境变量是从应用程序根文件夹中的 .env 文件调用的。

但是,当在应用程序中调用该环境变量时,它会抛出错误:

undefined

代码如下:

Docker文件

# Set base image
FROM node:latest AS builder

# Set working directory
WORKDIR /app

# Copy package.json and install packages
COPY package.json .
RUN npm install

# Copy other project files and build
COPY . ./
RUN npm run build

# Set nginx image
FROM nginx:latest

# Nginx config
RUN rm -rf /etc/nginx/conf.d/default.conf
COPY ./nginx/default.conf /etc/nginx/conf.d/default.conf

# Static build
COPY --from=builder /app/public /usr/share/nginx/html

# Set working directory
WORKDIR /usr/share/nginx/html

# Start Nginx server
CMD ["/bin/bash", "-c", "nginx -g \"daemon off;\""]

.env

GATSBY_API_URL=https://myapi.mywebsite.com

docker-compose.yml

version: "3"

services:
  web:
    image: my-website
    build:
      context: .
      dockerfile: Dockerfile
    environment:
      GATSBY_API_URL: ${GATSBY_API_URL}
    expose:
      - "80"
    labels:
      - traefik.enable=true
      - traefik.http.routers.my-website.rule=Host(`my-website.com`)
    restart: always
    volumes:
      - .:/app
networks:
  default:
    external:
      name: traefik-proxy

index.js

const onSubmit = async (values) => {
        try {
            const res = await axios.post(`${process.env.GATSBY_API_URL}/api/EmployeeDetail/verify`, values)
            // console.log(res, 'verify endpoint');
            if( res.data.requestSuccessful === true ) {
                dispatchVerifyData({ 
                    type : 'UPDATE_VERIFY_DATA', 
                    verifyData: {
                        res: res.data.responseData,
                        loanType: values.loanType
                    }
                })
                handleNext()
            } else {
                setIsSuccessful({
                    status: false,
                    message: res.data.message
                })
            }            

        } catch (error) {
            //error state Unsuccessful 
            console.log(error, 'error')
            setIsSuccessful({
                status: false,
            })
        }

    }

.docker忽略

node_modules
npm-debug.log
.DS_Store
.bin
.git
.gitignore
.bundleignore
.bundle
.byebug_history
.rspec
tmp
log
test
config/deploy
public/packs
public/packs-test
yarn-error.log
coverage/
.env
.env.production

Nginx default.conf

server {
  listen 80;
  add_header Cache-Control no-cache;
  location / {
    root   /usr/share/nginx/html;
    index  index.html index.htm;
    try_files $uri $uri/ /index.html;
    expires -1;
  }
  error_page   500 502 503 504  /50x.html;
  location = /50x.html {
    root   /usr/share/nginx/html;
  }
}

我似乎仍然无法判断导致应用程序在调用环境变量时 return 一个 未定义错误 的问题的原因是什么。我们将不胜感激任何形式的帮助。

经过与同事长时间的调试,我终于想通了。

这是我学到的一些东西:

首先,Gatsby默认支持2种环境:

  1. 发展。如果你运行gatsby develop,那么你将处于development环境
  2. 产量。如果你 运行 gatsby buildgatsby serve,那么你将在 production 环境中。

但是,如果您注意到我们 运行ning npm run build 在我们的 Dockerfile 中相当于 gatsby build,所以这会通知应用程序我们是 运行宁在production。环境。

其次,为客户端定义环境变量JavaScript

对于您想要在客户端浏览器中访问的项目环境变量 JavaScript,您可以定义一个环境配置文件,.env.development and/or .env.production,在你的根文件夹。根据您的活动环境,将找到正确的环境并将其值作为环境变量嵌入到浏览器中 JavaScript。

换句话说,我们需要将我们的环境配置文件从 .env 重命名为 .env.production 以允许 Gatsby 应用程序在我们的 production 环境中识别它。

三、使用前缀定义环境变量

除了 .env.* 文件中定义的这些项目环境变量外,您还可以定义 OS 环境变量。 OS 以 GATSBY_ 为前缀的环境变量将在浏览器 JavaScript.

中可用

如果您注意到得很好,我们已经在 .env 配置文件中将其定义为 - GATSBY_API_URL=https://myapi.mywebsite.com,因此我们对此没有任何问题。

第四,去除环境。来自 .dockerignore

的配置文件

如果我们清楚地观察客户端 Javascript 的环境变量值是如何嵌入到浏览器中的 JavaScript,您会发现它是在构建时完成的,而不是 运行时间。

因此,我们需要从 .dockerignore 中删除 .env.* 配置文件,并删除 docker-compose.yml 文件中的 environment 选项,因为它不再是必需的,因为我们没有在 运行 时间内嵌入环境变量的值。

所以我们的代码现在看起来像这样:

Dockerfile

# Set base image
FROM node:latest AS builder

# Set working directory
WORKDIR /app

# Copy package.json and install packages
COPY package.json .
RUN npm install

# Copy other project files and build
COPY . ./
RUN npm run build

# Set nginx image
FROM nginx:latest

# Nginx config
RUN rm -rf /etc/nginx/conf.d/default.conf
COPY ./nginx/default.conf /etc/nginx/conf.d/default.conf

# Static build
COPY --from=builder /app/public /usr/share/nginx/html

# Set working directory
WORKDIR /usr/share/nginx/html

# Start Nginx server
CMD ["/bin/bash", "-c", "nginx -g \"daemon off;\""]

.env.production

GATSBY_API_URL=https://myapi.mywebsite.com

docker-compose.yml

version: "3"

services:
  web:
    image: my-website
    build:
      context: .
      dockerfile: Dockerfile
    expose:
      - "80"
    labels:
      - traefik.enable=true
      - traefik.http.routers.my-website.rule=Host(`my-website.com`)
    restart: always
    volumes:
      - .:/app
networks:
  default:
    external:
      name: traefik-proxy

index.js

const onSubmit = async (values) => {
        try {
            const res = await axios.post(`${process.env.GATSBY_API_URL}/api/EmployeeDetail/verify`, values)
            // console.log(res, 'verify endpoint');
            if( res.data.requestSuccessful === true ) {
                dispatchVerifyData({ 
                    type : 'UPDATE_VERIFY_DATA', 
                    verifyData: {
                        res: res.data.responseData,
                        loanType: values.loanType
                    }
                })
                handleNext()
            } else {
                setIsSuccessful({
                    status: false,
                    message: res.data.message
                })
            }            

        } catch (error) {
            //error state Unsuccessful 
            console.log(error, 'error')
            setIsSuccessful({
                status: false,
            })
        }

    }

.docker忽略

node_modules
npm-debug.log
.DS_Store
.bin
.git
.gitignore
.bundleignore
.bundle
.byebug_history
.rspec
tmp
log
test
config/deploy
public/packs
public/packs-test
yarn-error.log
coverage/

Nginx default.conf

server {
  listen 80;
  add_header Cache-Control no-cache;
  location / {
    root   /usr/share/nginx/html;
    index  index.html index.htm;
    try_files $uri $uri/ /index.html;
    expires -1;
  }
  error_page   500 502 503 504  /50x.html;
  location = /50x.html {
    root   /usr/share/nginx/html;
  }
}

就这些了。

希望对您有所帮助