From 627d10b7c1250c0e895a198f8ff481572b3c6cee Mon Sep 17 00:00:00 2001 From: James Date: Sun, 13 Oct 2024 00:45:56 +0100 Subject: [PATCH] refactor: move process.env to ALS proxy --- .../cloudflare/src/cli/templates/worker.ts | 64 +++++++++++-------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/packages/cloudflare/src/cli/templates/worker.ts b/packages/cloudflare/src/cli/templates/worker.ts index dacbf4d4..2eebb066 100644 --- a/packages/cloudflare/src/cli/templates/worker.ts +++ b/packages/cloudflare/src/cli/templates/worker.ts @@ -13,12 +13,19 @@ import type { CloudflareContext } from "../../api"; const NON_BODY_RESPONSES = new Set([101, 204, 205, 304]); +const processEnvALS = new AsyncLocalStorage>(); const cloudflareContextALS = new AsyncLocalStorage(); // Note: this symbol needs to be kept in sync with the one defined in `src/api/get-cloudflare-context.ts` // eslint-disable-next-line @typescript-eslint/no-explicit-any (globalThis as any)[Symbol.for("__cloudflare-context__")] = createALSProxy(cloudflareContextALS); +globalThis.process = { + ...globalThis.process, + // @ts-expect-error - populated when we run inside the ALS context + env: createALSProxy(processEnvALS), +}; + // Injected at build time const nextConfig: NextConfig = JSON.parse(process.env.__NEXT_PRIVATE_STANDALONE_CONFIG ?? "{}"); @@ -26,40 +33,41 @@ let requestHandler: NodeRequestHandler | null = null; export default { async fetch(request, env, ctx) { - return cloudflareContextALS.run({ env, ctx, cf: request.cf }, async () => { - if (requestHandler == null) { - globalThis.process.env = { ...globalThis.process.env, ...env }; - // Note: "next/dist/server/next-server" is a cjs module so we have to `require` it not to confuse esbuild - // (since esbuild can run in projects with different module resolutions) - // eslint-disable-next-line @typescript-eslint/no-require-imports - const NextNodeServer = require("next/dist/server/next-server") - .default as typeof import("next/dist/server/next-server").default; - - requestHandler = new NextNodeServer({ - conf: nextConfig, - customServer: false, - dev: false, - dir: "", - minimalMode: false, - }).getRequestHandler(); - } + return processEnvALS.run({ NODE_ENV: "production", ...env }, () => { + return cloudflareContextALS.run({ env, ctx, cf: request.cf }, async () => { + if (requestHandler == null) { + // Note: "next/dist/server/next-server" is a cjs module so we have to `require` it not to confuse esbuild + // (since esbuild can run in projects with different module resolutions) + // eslint-disable-next-line @typescript-eslint/no-require-imports + const NextNodeServer = require("next/dist/server/next-server") + .default as typeof import("next/dist/server/next-server").default; + + requestHandler = new NextNodeServer({ + conf: nextConfig, + customServer: false, + dev: false, + dir: "", + minimalMode: false, + }).getRequestHandler(); + } - const url = new URL(request.url); + const url = new URL(request.url); - if (url.pathname === "/_next/image") { - const imageUrl = - url.searchParams.get("url") ?? "https://developers.cloudflare.com/_astro/logo.BU9hiExz.svg"; - if (imageUrl.startsWith("/")) { - return env.ASSETS.fetch(new URL(imageUrl, request.url)); + if (url.pathname === "/_next/image") { + const imageUrl = + url.searchParams.get("url") ?? "https://developers.cloudflare.com/_astro/logo.BU9hiExz.svg"; + if (imageUrl.startsWith("/")) { + return env.ASSETS.fetch(new URL(imageUrl, request.url)); + } + return fetch(imageUrl, { cf: { cacheEverything: true } }); } - return fetch(imageUrl, { cf: { cacheEverything: true } }); - } - const { req, res, webResponse } = getWrappedStreams(request, ctx); + const { req, res, webResponse } = getWrappedStreams(request, ctx); - ctx.waitUntil(Promise.resolve(requestHandler(new NodeNextRequest(req), new NodeNextResponse(res)))); + ctx.waitUntil(Promise.resolve(requestHandler(new NodeNextRequest(req), new NodeNextResponse(res)))); - return await webResponse(); + return await webResponse(); + }); }); }, } as ExportedHandler<{ ASSETS: Fetcher }>;