【问题标题】:Gatsby: Environment variables .env return undefinedGatsby:环境变量 .env 返回未定义
【发布时间】:2020-07-03 05:27:00
【问题描述】:

我正在开发一个静态网站,使用 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;
  }
}

我似乎仍然无法确定导致应用程序在调用环境变量时返回未定义错误的问题的原因。任何形式的帮助都将受到高度赞赏。

【问题讨论】:

    标签: docker nginx gatsby traefik


    【解决方案1】:

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

    这是我学到的一些东西

    首先,Gatsby 默认支持两种环境

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

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

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

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

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

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

    除了在.env.* 文件中定义的这些项目环境变量之外,您还可以定义操作系统环境变量。以 GATSBY_ 为前缀的 OS Env Vars 将在浏览器 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,
                })
            }
    
        }
    

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

    就是这样。

    我希望这会有所帮助

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-12
      • 2019-01-08
      • 2016-11-11
      • 2020-10-06
      • 1970-01-01
      • 2021-12-14
      • 1970-01-01
      • 2020-04-03
      相关资源
      最近更新 更多