feat(islands): serve the island runtime in dev, prod, and static builds
Adds /__wrnexus/islands.js (the bootstrap) and the /__wrnexus/island/ prefix (mount runtime, island bundles, shared chunks) to all three serving paths. Dev reuses the browserArtifactPaths registry pattern from pipeline.ts. Prod mirrors the clientModulesDir handler, including its filename allowlist, so island names cannot escape the output directory. The bootstrap is inert without a data-wrn-island marker, so island-free pages still download nothing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -24,6 +24,7 @@ import {
|
||||
import { basename, dirname, extname, join, relative, resolve } from "node:path";
|
||||
import { buildRouter, type Route } from "@wrnexus/router";
|
||||
import { getComponentControllerRuntime, getReactiveRuntime } from "@wrnexus/csr";
|
||||
import { getIslandRuntime } from "@wrnexus/react/runtime";
|
||||
import {
|
||||
analyzeRuntimeImports,
|
||||
analyzeRuntimeRequirements,
|
||||
@@ -112,6 +113,7 @@ export async function runBuild(appRoot: string): Promise<void> {
|
||||
const clientModulesDir = join(distDir, "client");
|
||||
const reactivePath = join(distDir, "reactive.js");
|
||||
const controllersPath = join(distDir, "controllers.js");
|
||||
const islandsPath = join(distDir, "islands.js");
|
||||
const publicDir = join(root, "public");
|
||||
const distPublicDir = join(distDir, "public");
|
||||
const config = await loadAppConfig(root);
|
||||
@@ -493,6 +495,16 @@ export async function runBuild(appRoot: string): Promise<void> {
|
||||
assetHash.update(controllerCode);
|
||||
console.log(`✓ Controllers: ${controllersPath}`);
|
||||
|
||||
// Island bootstrap: emitted unconditionally but inert without markers, so a
|
||||
// build with no islands still ships no React.
|
||||
const islandCode = await buildBrowserRuntime(
|
||||
getIslandRuntime(),
|
||||
islandsPath,
|
||||
join(compiledDir, "islands.entry.js"),
|
||||
);
|
||||
assetHash.update(islandCode);
|
||||
console.log(`✓ Islands: ${islandsPath}`);
|
||||
|
||||
// 1a) Theme tokens + client switcher (always emitted; built-in light/dark).
|
||||
const theme = resolveThemeConfig(config.theme, config.cookies);
|
||||
const themeCss = renderThemeCss(theme);
|
||||
|
||||
Reference in New Issue
Block a user