繁体   English   中英

无法使用动态键访问 process.env 值

[英]Can't access process.env values using dynamic keys

我有一个 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

首先,要注意一件事,如果你想在客户端使用env变量,那么你需要在它们NEXT_PUBLIC_加上NEXT_PUBLIC_ 前缀,或者使用旧的方式将它们暴露给next.config.js的客户端。

至于问题,这是由于 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 所以这可能是最终的解决方案。

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

解决方案

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

下一个.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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM