首頁  >  文章  >  web前端  >  Next.js 公共變數

Next.js 公共變數

Barbara Streisand
Barbara Streisand原創
2024-10-21 20:41:30436瀏覽

Next.js Public Variables

Next.js 因其對環境變數的處理而受到臭名昭著的批評。儘管多年來它已經得到了改進,但它仍然存在一些可能令人困惑的怪癖,特別是當涉及到透過 process.env 物件公開的公共變數時。

所有 NEXT_PUBLIC_ 前綴的變數都是客戶端可存取的,但正如官方文件中提到的,它們僅在建置時可用,因此與 Docker 一起使用時無法在執行時間變更。

雖然我過去已經討論過這個問題,但我發現了另一種可能有趣的探索方法,即使用可以在運行時更改的全域共享變數。

設定 Polyfill

Next.js 部分支援全域變量,但我們可以透過一個小的注入腳本使用 polyfill 來使它們可用。

// app/layout.tsx
<script
  dangerouslySetInnerHTML={{
    __html: `!function(t){function e(){var e=this||self;e.globalThis=e,delete t.prototype._T_}"object"!=typeof globalThis&&(this?e():(t.defineProperty(t.prototype,"_T_",{configurable:!0,get:e}),_T_))}(Object);`,
  }}
/>

原始程式碼取自GitHub上的這個評論,它基本上創建了一個全域的globalThis對象,可用於在客戶端和伺服器之間共用變數。 Polyfill 隨 Next.js 14.x 一起提供,但它似乎破壞了某些瀏覽器中的 globalThis 對象,這就是我們使用 __html 屬性將程式碼直接注入頁面的原因。

使用 Zod 驗證變量

接下來,我們可以使用 Zod 在運行時驗證變量,如果變量無效則拋出錯誤。此步驟對於確保變數始終可用且有效、避免執行時間錯誤以及使應用程式面臨安全問題至關重要。

npm install zod

然後我們建立一個變數.ts 文件,其中包含一些實用函數,用於從 process.env 中獲取變數並將它們安全地轉換為預期類型。

// lib/env.ts
import { z } from 'zod';

// Load the variables
export const load = () => {
  return process.env;
};

// Parse or throw the variables
export function parseOrThrow(schema: z.Schema, data: unknown, error: Error) {
  const parsed = schema.safeParse(data);
  // Log the errror
  if (parsed.success) return parsed.data;
  console.error(parsed.error);
  throw error;
}

// Some zod helpers to use
export const port = z
  .string()
  .refine(
    (port) => parseInt(port) > 0 && parseInt(port) < 65536,
    'Invalid port number'
  );

export const str = z.string();
export const url = z.string().url();
export const num = z.coerce.number();
export const bool = z.coerce.boolean();

load 是一個傳回 process.env 物件的簡單函數,而 parseOrThrow 是一個實用函數,它使用 Zod 模式解析變量,並在變數無效時拋出錯誤。

最後,我們可以建立一個變數.ts 文件,其中包含變數架構以及用於載入和解析變數的實用函數。

// lib/vars.ts
import { z } from 'zod';
import { load, parseOrThrow } from './env';
import { parseOrThrow, load, str, num, bool, port } from './env';

// Define the variables schema
const schema = z.object({
  PUBLIC_VARIABLE: str.optional(),
  PUBLIC_MY_NUM: num,
  PUBLIC_BOOL: bool,
  PUBLIC_PORT: port,
});

export const loadEnv = () => {
  const env = load();
  const parsed = parseOrThrow(schema, env, new Error('Invalid variables'));
  for (const key of Object.keys(parsed)) {
    if (!globalThis[key]) {
      globalThis[key] = parsed[key];
    }
  }
};

使用變數

為了使用變量,我們需要先載入它們。我們可以在 app/layout.tsx 檔案或任何其他佈局檔案中執行此操作,以逐漸將它們暴露給應用程式的其餘部分,無論是在客戶端還是在伺服器上。

// app/layout.tsx
import { loadEnv } from '@/lib/vars';

loadEnv();

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  );
}

參考

  • Next.js 環境變數
  • Next.js GitHub 討論

以上是Next.js 公共變數的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn