环境变量
此页面

环境变量

Remix 本身不会直接处理环境变量(除了在本地开发期间),但有一些我们认为有用的模式,我们将在本指南中分享。

环境变量是在服务器上存在的、您的应用程序可以使用的值。您可能熟悉无处不在的 NODE_ENV。您的部署服务器可能会自动将其设置为“production”。

运行 remix build 会使用 process.env.NODE_ENV 的值进行编译,前提是它与有效模式相对应:“production”、“development”或“test”。如果 process.env.NODE_ENV 的值无效,则默认使用“production”。

以下是一些您可能在实际应用中遇到的环境变量示例

  • DATABASE_URL:Postgres 数据库的 URL
  • STRIPE_PRIVATE_KEY:结账工作流在服务器上使用的密钥
  • STRIPE_PUBLIC_KEY:结账工作流在浏览器上使用的密钥

如果您在过去几年的 Web 开发经验主要来自 JS 框架,您可能会认为这些是构建使用的东西。虽然它们可以用于捆绑代码,但传统上这些是“构建参数”,而不是环境变量。环境变量在**服务器运行时**最有用。例如,您可以更改环境变量以更改应用程序的行为,而无需重新构建甚至重新部署。

服务器环境变量

本地开发

如果您使用 remix dev 服务器在本地运行项目,它内置支持 dotenv

首先,在项目的根目录中创建一个 .env 文件

touch .env

不要将您的 .env 文件提交到 git,关键是它包含机密信息!

编辑您的 .env 文件。

SOME_SECRET=super-secret

然后,在运行 remix dev 时,您将能够在您的加载器/操作中访问这些值

export async function loader() {
  console.log(process.env.SOME_SECRET);
}

如果您使用的是 @remix-run/cloudflare-pages@remix-run/cloudflare 适配器,则环境变量的工作方式略有不同。您需要在 .dev.vars 文件中定义您的本地环境变量。它与上面提到的 .env 示例文件具有相同的语法。

然后,它们将通过 Remix 的 context.cloudflare.env 在您的 loader/action 函数中可用

export const loader = async ({
  context,
}: LoaderFunctionArgs) => {
  console.log(context.cloudflare.env.SOME_SECRET);
};

请注意,.env.dev.vars 文件仅用于开发。您不应该在生产环境中使用它们,因此 Remix 在运行 remix serve 时不会加载它们。您需要按照主机提供的指南,通过以下链接将机密信息添加到生产服务器。

生产环境

部署到生产环境时的环境变量将由您的主机处理,例如

浏览器环境变量

有些人会问 Remix 是否可以让他们将环境变量放入浏览器捆绑包中。这在构建密集型框架中是一种常见的策略。但是,这种方法存在一些问题

  1. 它实际上并不是一个环境变量。您必须在构建时知道要部署到的服务器。
  2. 您无法在不重新构建和重新部署的情况下更改这些值。
  3. 很容易意外地将密钥泄漏到公开可访问的文件中!

我们建议将所有环境变量都保存在服务器上(所有服务器密钥以及浏览器中的 JavaScript 代码需要的部分),并通过window.ENV将其暴露给浏览器代码。由于您始终拥有服务器,因此您不需要在捆绑包中包含此信息,您的服务器可以在加载器中提供客户端环境变量。

  1. 从根加载器返回ENV以供客户端使用 - 在加载器中,您可以访问服务器的环境变量。加载器仅在服务器上运行,并且永远不会捆绑到客户端 JavaScript 中。

    export async function loader() {
      return json({
        ENV: {
          STRIPE_PUBLIC_KEY: process.env.STRIPE_PUBLIC_KEY,
          FAUNA_DB_URL: process.env.FAUNA_DB_URL,
        },
      });
    }
    
    export function Root() {
      return (
        <html lang="en">
          <head>
            <Meta />
            <Links />
          </head>
          <body>
            <Outlet />
            <Scripts />
          </body>
        </html>
      );
    }
    
  2. ENV放到 window 上 - 这是我们将值从服务器传递到客户端的方式。请确保将其放在<Scripts/>之前。

    export async function loader() {
      return json({
        ENV: {
          STRIPE_PUBLIC_KEY: process.env.STRIPE_PUBLIC_KEY,
        },
      });
    }
    
    export function Root() {
      const data = useLoaderData<typeof loader>();
      return (
        <html lang="en">
          <head>
            <Meta />
            <Links />
          </head>
          <body>
            <Outlet />
            <script
              dangerouslySetInnerHTML={{
                __html: `window.ENV = ${JSON.stringify(
                  data.ENV
                )}`,
              }}
            />
            <Scripts />
          </body>
        </html>
      );
    }
    
  3. 访问这些值

    import { loadStripe } from "@stripe/stripe-js";
    
    export async function redirectToStripeCheckout(
      sessionId
    ) {
      const stripe = await loadStripe(
        window.ENV.STRIPE_PUBLIC_KEY
      );
      return stripe.redirectToCheckout({ sessionId });
    }
    
文档和示例许可证 MIT