【问题标题】:Interpolate env vars client side in gatsby react app在 gatsby react 应用程序中插入 env vars 客户端
【发布时间】:2020-09-25 00:47:28
【问题描述】:

我使用 Gatsby 作为静态站点生成器并使用 Netlify 进行部署。

Netlify 允许您在其 UI 后端设置环境变量。

我在 Netlify 后端设置了一些环境变量,以便能够将订阅者发布到邮件列表。

DATA_NO = 'XXXX'
LIST_ID = '123456'
API_KEY = 'XXXXXXXXXXXXXXXXXXXXXXXXXX'

在我的 src 文件中,我有一个组件,它响应 onSubmit 事件并构造一个 URL 来发布新订阅者。

(axios用作发送HTTP请求等的包)

import React, { useState } from "react"
import axios from 'axios'

const Form = () => {

    const [userEmail, setState] = useState({'email_address': ''})

    const creds = 'anystring:'+ process.env.API_KEY
    let URL = 'https://'+ process.env.DATA_NO +'.api.example.com/3.0'
    URL += '/lists/'+ process.env.LIST_ID +'/members'

    const submitSubscribe = async e => {
        e.preventDefault()

        const payload = {
            'email_address': userEmail.email_address,
            'status': 'subscribed'
        }

        try {          
            const response = await axios.post( URL , payload, {
                headers: {
                    'Authorization': 'Basic ' + Buffer.from(creds ).toString('base64')
                }
            })
            console.log('r', response)
            console.log('r data', response.data)
          } catch(err) {
            console.log(err);
          }

    }

    return (
        <form name="newsletter-signup" method="post" onSubmit={submitSubscribe}>
            {/*<input type="hidden" name="form-name" value="newsletter-signup" />*/}
            <input type="email" placeholder="Email required" onChange={handleChange} value={userEmail.email_address} required />
            <button type="submit" className="button primary-button-inverted">Send'</button>
        </form>
    )
}

所以,在运行时,我的env varsundefined 出现。

我一直在看 Netlify 文档,他们一直说您需要插入值给客户端才能使用它们。我理解这里的逻辑。这些环境变量需要在构建时打印和捆绑,而不是在运行时调用。

我正在努力解决的问题是如何我该怎么做?

我在项目的根目录中设置了一个.env.development 文件。我尝试用GATSBY_ 为我的环境变量添加前缀,但我仍然遇到同样的问题。

我尝试使用 require('dotenv').config(),但我不确定 在哪里 将其准确放置(在我的 gatsby-node.jsgatsby-config.js 中)还是我需要在页面上包含我的组件那就是使用这些环境变量。

我希望能够将这些变量设置在一个地方(如果在开发中进行测试,可能会设置两个),但我不想进行太多调整以便能够在开发和生产版本中使用它们。

我也知道 Netlify 或 Gatsby 可以将这些变量处理到我的源代码中的 functions/ 文件夹中,我可以以某种方式使用它,但这似乎比我只需要发布一个简单的表单。

请帮忙!

更新

当前代码:

在我的项目根目录中,我创建了两个.env 文件,一个用于开发,一个用于生产。它们各自共享以下格式(请记住,我正在使用 GatsbyJS 进行开发):

GATSBY_MC_API_KEY="xxxxxxxxxxxxxxxxxxxxxxxxx-xxxx"
GATSBY_MC_DATA_NO="xxxx"
GATSBY_MC_AUDIENCE_ID="xxxxxxxxxxx"

我在src/config/config.js 中设置了一个单独的config.js 文件来组织和验证我的env vars(感谢@Baboo_)。它看起来像:

export const MC_API_KEY = process.env.GATSBY_MC_API_KEY;
export const MC_DATA_NO = process.env.GATSBY_MC_DATA_NO;
export const MC_AUDIENCE_ID = process.env.GATSBY_MC_AUDIENCE_ID;

const envVars = [
    {name: "MC_API_KEY", value: MC_API_KEY},
    {name: "MC_DATA_NO", value: MC_DATA_NO},
    {name: "MC_AUDIENCE_ID", value: MC_AUDIENCE_ID}
]

export const checkEnvVars = () => {
    const envVarsNotLoaded = envVars.filter((envVar) => envVar.value !== undefined);
    if (envVarsNotLoaded.length > 0) {
        throw new Error(`Could not load env vars ${envVarsNotLoaded.join(",")}`);
    }
}

checkEnvVars()

但是,当我运行 gatsby develop 时,会抛出“无法加载环境变量”错误。

【问题讨论】:

    标签: javascript environment-variables gatsby netlify


    【解决方案1】:

    你做对了。

    你所要做的确实是在你的环境变量前面加上GATSBY_,Gatsby 会自动加载它们。然后在您的代码中调用它们:

    const creds = 'anystring:'+ process.env.GATSBY_API_KEY
    let URL = 'https://'+ process.env.GATSBY_DATA_NO +'.api.example.com/3.0'
    tURL += '/lists/'+ process.env.GATSBY_LIST_ID +'/members'
    

    确保使用整个字符串process.env.GATSBY_LIST_ID 而不是process.env[GATSBY_LIST_ID],因为对象process.envundefined

    本地

    确保创建到.env 文件、.env.development.env.production。运行gatsby develop 时使用前者,运行gatsby build 时使用后者。

    您可能已经知道不应该提交这些文件。

    网络化

    在 Netlify 上的部署管道中添加相同的环境变量。这是related doc。这样,Netlify 可以在部署时构建您的网站。

    改进

    不要直接引用环境变量,而是创建一个加载它们的文件,如果其中一个无法检索,则抛出错误。这样你会在加载失败时注意到你并节省调试时间。

    例子:

    // config.js
    export const API_KEY = process.env.GATSBY_API_KEY;
    export const DATA_NO = process.env.GATSBY_DATA_NO ;
    
    const envVars = [
        {name: "API_KEY", value: API_KEY},
        {name: "DATA_NO", value: DATA_NO},
    ]
    
    const checkEnvVars = () => {
        const envVarsNotLoaded = envVars.filter(isUndefined);
        if (envVarsNotLoaded.length > 0) {
            throw new Error(`Could not load env vars ${envVarsNotLoaded.join(",")}`);
        }
    }
    
    const isUndefined = (envVar) => typeof envVar.value === "undefined";
    
    // component.js
    import React, { useState } from "react"
    import axios from 'axios'
    // Import environment variables
    import { API_KEY, DATA_NO } from "./config"
    
    const Form = () => {
        // ...
    
        const [userEmail, setState] = useState({'email_address': ''})
    
        const creds = 'anystring:'+ API_KEY
        let URL = 'https://'+ DATA_NO +'.api.example.com/3.0'
    

    【讨论】:

    • 很好的答案,感谢改进提示 - 我总是喜欢学习更好的编码方法!我创建了两个.env 文件并在其中放置了相同的全局变量,它们都以GATSBY_ 前缀开头(例如:GATSBY_API_KEY=XXXXXXXXX 然后我在src/config/config.js 中创建了一个config.js 文件(这需要在项目路径中吗? ). 我按照您的建议导出变量,例如:export const API_KEY = process.env.GATSBY_API_KEY。我像您的示例一样构建了对象,并且正在使用您的调试功能 - 它正在工作!我仍然无法加载变量?
    • 很高兴听到这个消息!当你说你仍然无法加载变量时,你的意思是在 Netlify 的构建期间?
    • 我在本地环境中无法通过gatsby develop。在我的config.js 文件中,我最后调用了checkEnvVars 函数,它一直抛出错误。
    • 您是否尝试过清理 gatsby 在根文件夹中创建的 .cache 文件夹?
    • 我在检查环境变量是否未定义的代码中犯了一个错误。我更新了我的答案。您可以使用更新后的代码进行测试
    猜你喜欢
    • 2021-09-20
    • 2021-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-10
    • 2019-05-31
    • 2019-12-30
    相关资源
    最近更新 更多