History

Pin VITE_PUBLIC_ANALYTICS_PATH for cloud build

Vite reloads vite.config.ts separately for the client and SSR/Cloudflare environments, so the previous module-scope memoization of randomUUID() ran twice and produced different ids. Client and server bundles baked mismatching paths, so the worker proxy never matched the SDK's requests and PostHog calls 404'd in production. Generate the path once in scripts/build.mjs before vite starts and inherit via process.env so every environment build sees the same value.

Rhys Sullivan committed 6 months ago

Commit 242c2891 parent 40353be3 files · +32 −8Browse files

Unified · Split

3 files
  1. apps/cloud/package.json +1 −1
  2. apps/cloud/scripts/build.mjs +25 −0
  3. apps/cloud/vite.config.ts +6 −7
apps/cloud/package.json+1−1
@@ -14,7 +14,7 @@ · 13 unmodified lines
14 "db:studio:prod": "op run --env-file=.env.production -- drizzle-kit studio",14 "db:studio:prod": "op run --env-file=.env.production -- drizzle-kit studio",
15 "db:migrate:prod": "op run --env-file=.env.production -- drizzle-kit migrate",15 "db:migrate:prod": "op run --env-file=.env.production -- drizzle-kit migrate",
16 "db:migrate:dev": "op run --env-file=.env.op -- drizzle-kit migrate",16 "db:migrate:dev": "op run --env-file=.env.op -- drizzle-kit migrate",
17 "build": "turbo run build --filter @executor-js/vite-plugin && vite build",17 "build": "node scripts/build.mjs",
18 "preview": "vite preview",18 "preview": "vite preview",
19 "deploy": "op run --env-file=.env.production -- bun run build && op run --env-file=.env.production -- wrangler deploy",19 "deploy": "op run --env-file=.env.production -- bun run build && op run --env-file=.env.production -- wrangler deploy",
20 "cf-typegen": "wrangler types",20 "cf-typegen": "wrangler types",
apps/cloud/scripts/build.mjs+25−0
@@ -0,0 +1,25 @@
1// Build wrapper that pins VITE_PUBLIC_ANALYTICS_PATH for the whole build.
2//
3// Vite reloads vite.config.ts separately for the client and SSR/Cloudflare
4// environments, so a module-scoped randomUUID() ends up running twice and
5// the two bundles bake different values. The browser SDK then targets a
6// path the worker middleware never matches, and PostHog requests 404. By
7// generating once here and putting it in process.env before vite starts,
8// every environment build sees the same value.
9
10import { spawnSync } from "node:child_process";
11import { randomBytes } from "node:crypto";
12
13if (!process.env.VITE_PUBLIC_ANALYTICS_PATH) {
14 process.env.VITE_PUBLIC_ANALYTICS_PATH = randomBytes(4).toString("hex");
15}
16console.log(`[build] VITE_PUBLIC_ANALYTICS_PATH=${process.env.VITE_PUBLIC_ANALYTICS_PATH}`);
17
18const steps = ["turbo run build --filter @executor-js/vite-plugin", "vite build"];
19
20for (const step of steps) {
21 const result = spawnSync(step, { stdio: "inherit", shell: true });
22 if (result.status !== 0) {
23 process.exit(result.status ?? 1);
24 }
25}
apps/cloud/vite.config.ts+6−7
@@ -1,4 +1,3 @@
1import { randomUUID } from "node:crypto";
2import { fileURLToPath } from "node:url";1import { fileURLToPath } from "node:url";
3import { defineConfig, loadEnv, type Plugin } from "vite";2import { defineConfig, loadEnv, type Plugin } from "vite";
4import { cloudflare } from "@cloudflare/vite-plugin";3import { cloudflare } from "@cloudflare/vite-plugin";
@@ -42,17 +41,17 @@ const loadWranglerPublicVars = () => { · 37 unmodified lines
42 );41 );
43};42};
44 43
45let generatedAnalyticsPath: string | undefined;44// VITE_PUBLIC_ANALYTICS_PATH is generated once per build by `scripts/build.mjs`
46const getGeneratedAnalyticsPath = () => {45// and inherited via process.env, so the client and SSR/Cloudflare environment
47 generatedAnalyticsPath ??= randomUUID().slice(0, 8);46// builds bake the same value. The fallback "a" is for `vite dev`, where the
48 return generatedAnalyticsPath;47// proxy isn't routed anyway.
49};48const ANALYTICS_PATH = process.env.VITE_PUBLIC_ANALYTICS_PATH ?? "a";
50 49
51export default defineConfig(({ mode }) => {50export default defineConfig(({ mode }) => {
52 const env = loadEnv(mode, process.cwd(), "");51 const env = loadEnv(mode, process.cwd(), "");
53 const publicEnv = {52 const publicEnv = {
54 ...loadWranglerPublicVars(),53 ...loadWranglerPublicVars(),
55 VITE_PUBLIC_ANALYTICS_PATH: getGeneratedAnalyticsPath(),54 VITE_PUBLIC_ANALYTICS_PATH: ANALYTICS_PATH,
56 ...env,55 ...env,
57 };56 };
58 57