Gatsby:环境变量.env返回未定义

时间:2020-07-03 05:27:00

标签: docker nginx gatsby traefik

我正在使用 Gatsby 进行开发并使用 Nginx 来提供静态文件的静态网站上。

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

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

但是,当在应用程序中调用该环境变量时,它将引发错误:

未定义

这是代码

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

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,
            })
        }

    }

.dockerignore

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;
  }
}

我似乎仍然无法分辨出什么原因导致了每次调用环境变量时导致应用程序返回 undefined error 的问题。任何形式的帮助将不胜感激。

1 个答案:

答案 0 :(得分:2)

经过与同事长时间的调试,我终于找到了答案。

这是我学到的一些东西

首先,默认情况下,盖茨比支持2种环境

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

但是,如果您注意到,我们正在npm run build中运行Dockerfile,相当于gatsby build,因此这通知应用程序我们正在production中运行。环境。

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

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

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

第三,使用前缀定义环境变量

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

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

第四,删除环境。 .dockerignore

中的配置文件

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

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

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

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,
            })
        }

    }

.dockerignore

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;
  }
}

仅此而已。

我希望这会有所帮助