React Router v7 已發佈。 查看文件
環境變數
本頁內容

環境變數

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:瀏覽器上結帳流程將使用的金鑰

如果您在過去幾年主要使用 JS 框架進行網頁開發,您可能會認為這些是您的建置要使用的東西。雖然它們對於捆綁程式碼很有用,但傳統上那些是「建置參數」,而不是環境變數。環境變數在*伺服器上的執行時*最有用。例如,您可以變更環境變數來變更應用程式的行為,而無需重新建置甚至重新部署。

伺服器環境變數

本地開發

如果您使用 remix dev 伺服器在本機執行您的專案,它內建支援 dotenv

首先,在您的專案根目錄中建立一個 .env 檔案

touch .env

不要將您的 .env 檔案提交到 git,重點是它包含機密!

編輯您的 .env 檔案。

SOME_SECRET=super-secret

然後,當執行 remix dev 時,您將可以在您的 loaders/actions 中存取這些值

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 將它們公開給您的瀏覽器程式碼。由於您始終擁有伺服器,因此您不需要在套件中包含此資訊,您的伺服器可以在 loader 中提供用戶端環境變數。

  1. 從根 loader 返回 ENV 給用戶端 - 在您的 loader 中,您可以存取您伺服器的環境變數。Loader 只會在伺服器上執行,永遠不會被打包到您的用戶端 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