diff --git a/js/app/README.md b/js/app/README.md index 330af035f..88bba8c7f 100644 --- a/js/app/README.md +++ b/js/app/README.md @@ -61,6 +61,10 @@ without replaying successfully loaded scripts. Styles come from design tokens at build time; no React, theme provider, fonts, or app modules load to show it. Development Metro and installed iOS/Android entrypoints are unchanged. +The bootstrap build uses the project's installed TypeScript compiler to read +design tokens. It does not require Node's optional native TypeScript support or +`--experimental-strip-types`; the existing Node 22 requirement is unchanged. + This reduces **bytes required for the first loading UI**, not the bytes required for a usable Home screen. The app still downloads automatically after that first paint; route-level chunks remain deferred until opened. diff --git a/js/app/package.json b/js/app/package.json index 39e740ed8..d00a1daf1 100644 --- a/js/app/package.json +++ b/js/app/package.json @@ -18,8 +18,8 @@ "brand": "pnpm --filter @streamplace/brand generate", "build": "pnpm run build:web && pnpm run prebuild", "build:web": "pnpm run brand && node scripts/generate-build-info.js && pnpm run export && node exportClientExpoConfig.js > dist/expoConfig.json", - "export": "(expo export --dump-sourcemap || expo export --dump-sourcemap) && node --experimental-strip-types scripts/bootstrap-web.mjs", - "analyze:web": "pnpm run brand && EXPO_ATLAS=true expo export --platform web --output-dir .expo/atlas-web --dump-sourcemap && node --experimental-strip-types scripts/bootstrap-web.mjs .expo/atlas-web && expo-atlas --no-open", + "export": "(expo export --dump-sourcemap || expo export --dump-sourcemap) && node scripts/bootstrap-web.mjs", + "analyze:web": "pnpm run brand && EXPO_ATLAS=true expo export --platform web --output-dir .expo/atlas-web --dump-sourcemap && node scripts/bootstrap-web.mjs .expo/atlas-web && expo-atlas --no-open", "check": "pnpm --filter @streamplace/i18n compile && bash -c 'set -euo pipefail;export OUT=$(mktemp -d); npx tsc -p . --outDir $OUT; rm -rf $OUT'", "prebuild": "pnpm run brand && EXPO_NO_GIT_STATUS=1 expo prebuild --clean && sed -i.bak 's/org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m/org.gradle.jvmargs=-Xmx4096m -XX:MaxMetaspaceSize=1024m/' android/gradle.properties && pnpm run find-node", "prepare": "which pod && pnpm run prepare-ios || echo 'not a mac, not installing pods' && mkdir -p ./public && cp -r ../i18n/public/locales ./public/", diff --git a/js/app/scripts/bootstrap-web.mjs b/js/app/scripts/bootstrap-web.mjs index 1b30f008b..a1fbf63f8 100644 --- a/js/app/scripts/bootstrap-web.mjs +++ b/js/app/scripts/bootstrap-web.mjs @@ -1,7 +1,18 @@ import { createHash } from "node:crypto"; import { readFile, writeFile } from "node:fs/promises"; import path from "node:path"; -import { +import ts from "typescript"; + +// Tokens have only type imports. Compile them with the project's TypeScript +// dependency so this works even when Node was built without type stripping. +const { outputText } = ts.transpileModule( + await readFile( + new URL("../../components/src/lib/theme/tokens.ts", import.meta.url), + "utf8", + ), + { compilerOptions: { module: ts.ModuleKind.ESNext } }, +); +const { borderRadius, motion, spacing, @@ -9,7 +20,9 @@ import { textAlphas, touchTargets, typeScale, -} from "../../components/src/lib/theme/tokens.ts"; +} = await import( + `data:text/javascript;base64,${Buffer.from(outputText).toString("base64")}` +); // Expo's shared chunk is eager even when every app screen is lazy. Keep its // generated bundles intact, but let a tiny bootloader start them after paint.