【问题标题】:Can't access process.env values using dynamic keys无法使用动态键访问 process.env 值
【发布时间】:2021-01-17 00:46:57
【问题描述】:

我有一个 nextjs(不确定它是否有任何相关性或者它是否适用于整个 nodejs)项目,我想在其中使用动态键访问来自 process.env 的值:

const myKey = 'MY_KEY'
console.log(process.env[myKey]) //undefined

供参考,我试过了:

console.log(process.env['MY_KEY']) // gives value under MY_KEY
console.log(process.env.MY_KEY) // works too

【问题讨论】:

  • 为我工作。你能分享一个展示这种行为的可执行 sn-p 吗?
  • 我也有同样的问题。 myKey 总是返回 undefined。
  • 看到一样。最终有条件地将值分配给一个 var,但真的很想了解如何解决这个问题。
  • 你能分享一个简单的项目吗?
  • @JasperKennis 您是否正确地使用了exposing the environment variables to the browser 前缀NEXT_PUBLIC_

标签: javascript node.js next.js


【解决方案1】:

首先要注意一点,如果你想在客户端上使用env变量然后你need to prefix它们和NEXT_PUBLIC_,或者使用older way将它们暴露给@987654328里面的客户端@。

至于问题,这是由于 Webpack DefinePlugin 的工作原理,我相信 NextJs 在内部使用它。它在构建时直接替换文本,简单来说,它只是查找process.env.MY_KEY 字符串并将其替换为值。但是如果你解构它,那么插件就再也找不到process.env.MY_KEY 字符串并且你什么也得不到(process.env 对象无论如何都会生成,但它会是空的)。

虽然这仅适用于客户端代码,因为对于服务器端 Next 实际上使用真正的 process.env 对象并且解构将在那里工作。

例如,如果我们有 NEXT_PUBLIC_MY_KEY=somevalue 并且我们将其记录在代码中的某处:

  const key = 'NEXT_PUBLIC_MY_KEY';

  console.log(process.env.NEXT_PUBLIC_MY_KEY);
  console.log(process.env['NEXT_PUBLIC_MY_KEY']);
  console.log(process.env[key]);
  console.log(process.env);

在客户端你会得到:

somevalue
somevalue
undefined
{} // empty object

在服务器端你会得到:

somevalue
somevalue
somevalue
{ ... } // object with all available env values, even system ones

在较早的env docs 中有一些关于它的信息。

解决方法

您可能可以使用Runtime Configuration,但它有其自身的局限性,例如,我认为页面应该是动态的(应该使用getInitialPropsgetServerSideProps)才能工作。

// next.config.js
module.exports = {
  publicRuntimeConfig: {
    myEnv: 'somevalue',
    // or actually use process.env variables, they are all available here
    myEnv2: process.env.MY_ENV
  },
};

import getConfig from 'next/config';

const key = 'myEnv';

getConfig().publicRuntimeConfig[key] // 'somevalue' 

或者只是通过getServerSideProps 传递您的变量,就像提到的其他答案一样。

编辑: 我实际上刚刚测试了publicRuntimeConfig,它甚至可以在静态页面上工作,至少如果您使用的是next start。不知道为什么文档说页面应该有getServerSideProps。所以这可能是最终的解决方案。

【讨论】:

    【解决方案2】:

    正如其他人已经正确提到的那样,出现此问题是因为 Webpack DefinePlugin 就是这样工作的。

    解决方案

    扩展 webpack 配置。您可以过滤掉所有的环境变量,从NEXT_PUBLIC_ 开始,并使用DefinePlugin webpack 插件将它们添加到process.env 对象中。这样您就可以在浏览器中动态调用它们。

    next.config.js

    module.exports = {
      webpack: (config, { webpack, isServer }) => {
        const envs = {};
        
        Object.keys(process.env).forEach(env => {
          if (env.startsWith('NEXT_PUBLIC_')) {
            envs[env] = process.env[env];
          }
        })
        
        if (!isServer) {
          config.plugins.push(new webpack.DefinePlugin({
            'process.env': JSON.stringify(envs),
          }))
        }
    
        return config
      },
    }
    

    你的页面

    import { useEffect } from 'react';
    
    const keys = ['FOO', 'NEXT_PUBLIC_FOO'];
    
    export default function Home() {
      useEffect(() => {
        keys.forEach(key => console.log(process.env[key]));
      }, []);
    
      return (
        <>
        </>
      )
    }
    

    解决方法

    此解决方法添加所有以NEXT_PUBLIC 为前缀的环境变量,以便在前端动态可用。

    import { useEffect } from 'react';
    
    const keys = ['FOO', 'NEXT_PUBLIC_FOO'];
    
    export default function Home(props) {
      useEffect(() => {
        keys.forEach(key => console.log(props.envs[key]));
      }, []);
    
      return (
        <>
        </>
      )
    }
    
    export async function getStaticProps() {
      const envs = {};
      
      Object.keys(process.env).forEach(env => {
        if (env.startsWith('NEXT_PUBLIC_')) {
          envs[env] = process.env[env];
        }
      })
    
      return {
        props: {
          envs,
        },
      }
    }
    

    重要的是,您使用getStaticProps 方法。在这里,您过滤掉所有以NEXT_PUBLIC_ 开头的环境变量,并将它们添加到 envs 属性中。这允许它们在前端动态使用。

    在本例中,NEXT_PUBLIC_FOO 的值将记录到控制台,而FOO 的值是undefined

    【讨论】:

    • 您使用自定义DefinePlugin 的解决方案实际上会破坏服务器端process.env。您至少需要检查isServer
    • 感谢您的提醒。我已经相应地更新了我的答案并修复了这个错误
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-30
    • 2020-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多