环境变量
On this page

环境变量

¥Environment Variables

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

¥Remix does not do anything directly with environment variables (except during local development), but there are some patterns we find useful that we'll share in this guide.

环境变量是驻留在服务器上、可供应用使用的值。你可能熟悉无处不在的 NODE_ENV。你的部署服务器可能会自动将其设置为 "production"

¥Environment Variables are values that live on the server that your application can use. You may be familiar with the ubiquitous NODE_ENV. Your deployment server probably automatically sets that to "production".

如果 process.env.NODE_ENV 的值与有效模式("production""development""test")相对应,则运行 remix build 会使用其值进行编译。如果 process.env.NODE_ENV 的值无效,则默认使用 "production"

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

¥Here are some example environment variables you might find in the wild:

  • DATABASE_URL:Postgres 数据库的 URL

    ¥DATABASE_URL: The URL for a Postgres Database

  • STRIPE_PRIVATE_KEY:结账工作流将在服务器上使用的键

    ¥STRIPE_PRIVATE_KEY: The key a checkout workflow will use on the server

  • STRIPE_PUBLIC_KEY:结账工作流将在浏览器上使用的键

    ¥STRIPE_PUBLIC_KEY: The key a checkout workflow will use on the browser

如果你过去几年的 Web 开发经验主要集中在 JS 框架上,那么你可能会认为这些框架可以作为你的构建工具。虽然它们对于打包代码很有用,但传统上它们是 "构建参数",而不是环境变量。环境变量在服务器运行时最有用。例如,你可以更改环境变量来更改应用的行为,而无需重建或重新部署。

¥If your experience with web development is primarily with the JS frameworks in the last few years, you might think of these as something for your build to use. While they can be useful for bundling code, traditionally those are "build arguments" not environment variables. Environment variables are most useful at runtime on the server. For example, you can change an environment variable to change the behavior of your app without rebuilding or even redeploying.

服务器环境变量

¥Server Environment Variables

本地开发

¥Local Development

如果你使用 remix dev 服务器在本地运行项目,它内置了对 dotenv 的支持。

¥If you're using the remix dev server to run your project locally, it has built-in support for dotenv.

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

¥First, create an .env file in the root of your project:

touch .env

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

编辑你的 .env 文件。

¥Edit your .env file.

SOME_SECRET=super-secret

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

¥Then, when running remix dev you will be able to access those values in your loaders/actions:

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

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

¥If you're using the @remix-run/cloudflare-pages or @remix-run/cloudflare adapters, env variables work a little differently. You'll need to define your local environment variables in the .dev.vars file. It has the same syntax as .env example file mentioned above.

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

¥Then, they'll be available via Remix's context.cloudflare.env in your loader/action functions:

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

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

¥Note that .env and .dev.vars files are only for development. You should not use them in production, so Remix doesn't load them when running remix serve. You'll need to follow your host's guides on adding secrets to your production server, via the links below.

生产

¥Production

你的主机在部署到生产环境时会处理环境变量,例如:

¥Your host will handle environment variables when deployed to production, for example:

浏览器环境变量

¥Browser Environment Variables

有些人询问 Remix 是否允许他们将环境变量放入浏览器包中。这是构建密集型框架的常用策略。然而,这种方法存在一些问题,原因如下:

¥Some folks ask if Remix can let them put environment variables into browser bundles. It's a common strategy in build-heavy frameworks. However, this approach is a problem for a few reasons:

  1. 它实际上不是一个环境变量。你必须在构建时知道要部署到哪个服务器。

    ¥It's not really an environment variable. You have to know which server you're deploying to at build time.

  2. 如果不重建并重新部署,则无法更改这些值。

    ¥You can't change the values without a rebuild and redeploy.

  3. 很容易将机密信息意外泄露到可公开访问的文件中!

    ¥It's easy to accidentally leak secrets into publicly accessible files!

我们建议将所有环境变量(所有服务器机密以及浏览器中 JavaScript 所需的内容)保留在服务器上,并通过 window.ENV 将它们公开给浏览器代码。由于你始终拥有服务器,因此你不需要在包中包含这些信息;你的服务器可以在加载器中提供客户端环境变量。

¥Instead, we recommend keeping all of your environment variables on the server (all the server secrets as well as the stuff your JavaScript in the browser needs) and exposing them to your browser code through window.ENV. Since you always have a server, you don't need this information in your bundle; your server can provide the client-side environment variables in the loaders.

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

    ¥Return ENV for the client from the root loader - Inside your loader you can access your server's environment variables. Loaders only run on the server and are never bundled into your client-side 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 放在窗口上 - 这就是我们将值从服务器传递到客户端的方式。确保将其放在 <Scripts/> 之前

    ¥Put ENV on window - This is how we hand off the values from the server to the client. Make sure to put this before <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. 访问值

    ¥Access the values

    import { loadStripe } from "@stripe/stripe-js";
    
    export async function redirectToStripeCheckout(
      sessionId
    ) {
      const stripe = await loadStripe(
        window.ENV.STRIPE_PUBLIC_KEY
      );
      return stripe.redirectToCheckout({ sessionId });
    }
    
Remix v2.17 中文网 - 粤ICP备13048890号