Next.js wurde für seinen Umgang mit Umgebungsvariablen heftig kritisiert. Obwohl es im Laufe der Jahre verbessert wurde, weist es immer noch einige Macken auf, die verwirrend sein können, insbesondere wenn es um öffentliche Variablen geht, die über das Objekt „process.env“ verfügbar gemacht werden.
Alle Variablen mit dem Präfix NEXT_PUBLIC_ sind clientseitig zugänglich, aber wie in der offiziellen Dokumentation erwähnt, sind sie nur zur Build-Zeit verfügbar und können sich daher zur Laufzeit nicht ändern, wenn sie mit Docker verwendet werden.
Obwohl ich dieses Problem bereits in der Vergangenheit behandelt habe, habe ich einen anderen Ansatz gefunden, dessen Erkundung interessant sein könnte: die Verwendung global gemeinsam genutzter Variablen, die zur Laufzeit geändert werden können.
Globale Variablen werden teilweise von Next.js unterstützt, aber wir können eine Polyfüllung verwenden, um sie mithilfe eines kleinen injizierten Skripts verfügbar zu machen.
// 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);`, }} />
Der Originalcode stammt aus diesem Kommentar auf GitHub und erstellt im Grunde ein globales globalThis-Objekt, das zum Austausch von Variablen zwischen dem Client und dem Server verwendet werden kann. Das Polyfill kommt mit Next.js 14.x, aber es scheint das globalThis-Objekt in einigen Browsern zu beschädigen, deshalb verwenden wir die __html-Eigenschaft, um den Code direkt in die Seite einzufügen.
Als nächstes können wir Zod verwenden, um die Variablen zur Laufzeit zu validieren und einen Fehler auszulösen, wenn die Variablen ungültig sind. Dieser Schritt ist von entscheidender Bedeutung, um sicherzustellen, dass die Variablen immer verfügbar und gültig sind, um Laufzeitfehler zu vermeiden und die Anwendung Sicherheitsproblemen auszusetzen.
npm install zod
Wir erstellen dann eine Variable.ts-Datei, die einige Hilfsfunktionen enthält, um die Variablen aus Process.env abzurufen und sie sicher in den erwarteten Typ umzuwandeln.
// 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 ist eine einfache Funktion, die das Objekt „process.env“ zurückgibt, während parseOrThrow eine Hilfsfunktion ist, die die Variablen mithilfe eines Zod-Schemas analysiert und einen Fehler auslöst, wenn die Variablen ungültig sind.
Schließlich können wir eine Variable.ts-Datei erstellen, die das Variablenschema und die Dienstprogrammfunktionen zum Laden und Analysieren der Variablen enthält.
// 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]; } } };
Um die Variablen verwenden zu können, müssen wir sie zuerst laden. Wir können dies in der Datei app/layout.tsx oder einer anderen Layoutdatei tun, um sie nach und nach für den Rest der Anwendung verfügbar zu machen, sowohl auf dem Client als auch auf dem Server.
// 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> ); }
Das obige ist der detaillierte Inhalt vonÖffentliche Variablen von Next.js. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!