NextJS 服务器端环境变量由于某种原因未定义?

问题描述 投票:0回答:1

这并不是一个真正的问题,但我只是在花了几个小时搜索这个问题后自己想出来的......

所以,因为我看到了很多相关的帖子,但没有一个与这种特定的情况和背景有关,也许在这里阅读这篇文章的你可能会遇到同样的问题?因此,我决定把它留在这里以防万一......

如果由于某种原因这不是一个好的解决方案,请留下评论解释具体原因,我很乐意将其删除以防止错误信息!


问题

NextJS/ReactJS 应用程序产生运行时错误,因为在服务器端未定义环境变量。

我使用了一个名为

.env.local
的本地(未跟踪)文件,该文件运行良好,直到我决定创建要从 lib 文件夹中运行的异步函数。然后,开始发生错误,提示未定义特定的环境变量。


徒劳的尝试让它发挥作用(对于这个特定的上下文)

我之前尝试过(有些尝试是无用的,我知道......):

  • 使用名为
    .env.development
  • 的不同名称文件
  • 对环境变量使用“NEXT_PUBLIC”前缀(如果它们是敏感信息,则很危险!)
  • 使用某种转发,通过
    next.config.js
    文件

无济于事。


解决方案

尽管没有添加“使用客户端”,但我相信它默认是这样的,因为这些函数是从客户端组件调用的(这很有意义,不是吗?) - 或者,它们仍然是服务器组件,但是由于某种原因没有与环境变量同步?

因此,我在此类异步函数的顶部添加了“使用服务器”,以强制在服务器端构建它们。问题解决了(对我来说,希望对你来说也是:))

reactjs variables next.js undefined environment
1个回答
0
投票

我不太清楚你的意思是什么。

  • 您确实可以在环境变量前加上

    NEXT_PUBLIC
    前缀,使它们在客户端可用,是的,您应该非常谨慎地处理敏感信息。

  • 如果在文件顶部没有使用

    "use server"
    指令,则在应用程序目录之外的任何其他文件夹中创建文件并将其导入客户端组件中确实会使其成为正常功能(无需服务器端访问)。

只是为了澄清您在上述声明中所写的内容:


示例

假设您有一个名为

utils.ts
的文件和一个调用实用程序文件中定义的函数之一的客户端组件。

// lib/utils.ts
function sayHello(): string {
  return `Hello, ${process.env.USER_NAME}!`;
}

// components/MyComponent.ts
"use client";

export default function MyComponent(): JSX.Element {
  const [greeting, setGreeting] = useState(sayHello());
  return <p>{greeting}</p>;
}

看上面的例子,组件的输出将是一个包含句子

Hello, undefined!
的段落,因为环境变量没有以
NEXT_PUBLIC
为前缀,因此在客户端不可用。


服务器操作

使用

"use server"
指令并使函数异步时能够访问变量的原因是因为您刚刚将其转换为服务器操作,如下所示:

// lib/utils.ts
"use server";

async function sayHello(): string {
  return `Hello, ${process.env.USER_NAME}!`;
}

// components/MyComponent.ts
"use client";

export default function MyComponent(): JSX.Element {
  const [greeting, setGreeting] = useState();

  useEffect(() => {
    const fetchGreeting = async () => setGreeting(await sayHello());
    fetchGreeting();
  }, []);

  return <p>{greeting}</p>;
}

如果要复制上述代码,一旦组件安装,就会往返服务器,然后执行该函数,返回问候语字符串。这不是要走的路。


更好的方法

如上面的示例所示,对于一个组件来说,这样做可能没问题,但它很快就会变成大量样板代码和大量的网络开销。到达这里的方法是通过页面中的道具传递您的信息:

import { sayHello } from "@/lib/utils";

export default async function Page(): Promise<JSX.Element> {
  const greeting = sayHello(); // synchronous, no server action needed
  return <MyComponent greeting={greeting} />;
}
© www.soinside.com 2019 - 2024. All rights reserved.