Remix 不會直接處理環境變數(除了在本地開發期間),但我們發現一些有用的模式,將在本指南中分享。
環境變數是存在於伺服器上,您的應用程式可以使用的值。您可能熟悉常見的 NODE_ENV
。您的部署伺服器可能會自動將其設定為「production」。
remix build
會使用 process.env.NODE_ENV
的值進行編譯,如果該值對應到有效的模式:「production」、「development」或「test」。如果 process.env.NODE_ENV
的值無效,則預設使用「production」。
以下是一些您可能會在實際應用中找到的環境變數範例
DATABASE_URL
:Postgres 資料庫的 URLSTRIPE_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 是否可以將環境變數放入瀏覽器套件中。這在建構密集型框架中是很常見的策略。然而,這種方法存在一些問題:
我們建議您將所有環境變數都保存在伺服器上(包括所有伺服器機密資訊以及瀏覽器中 JavaScript 需要的內容),並透過 window.ENV
將它們公開給您的瀏覽器程式碼。由於您始終擁有伺服器,因此您不需要在套件中包含此資訊,您的伺服器可以在 loader 中提供用戶端環境變數。
從根 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>
);
}
將 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>
);
}
存取這些值
import { loadStripe } from "@stripe/stripe-js";
export async function redirectToStripeCheckout(
sessionId
) {
const stripe = await loadStripe(
window.ENV.STRIPE_PUBLIC_KEY
);
return stripe.redirectToCheckout({ sessionId });
}