@reckona/mreact-router 0.0.115 → 0.0.116

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/build.js CHANGED
@@ -171,7 +171,7 @@ export async function buildApp(options) {
171
171
  ...route,
172
172
  file: relative(project.projectRoot, route.file),
173
173
  }));
174
- const [serverModuleArtifacts, clientRoutes] = await Promise.all([
174
+ const [serverModuleArtifacts, clientBundle] = await Promise.all([
175
175
  timingSink === undefined
176
176
  ? writeServerModuleArtifactFiles(serverDir, serverModules, generatedImportPolicy.runtimePackages)
177
177
  : timeBuildPhase(timingSink, "serverModuleArtifacts", () => writeServerModuleArtifactFiles(serverDir, serverModules, generatedImportPolicy.runtimePackages)),
@@ -203,6 +203,7 @@ export async function buildApp(options) {
203
203
  vitePlugins,
204
204
  })),
205
205
  ]);
206
+ const clientRoutes = clientBundle.routes;
206
207
  const navigationRuntimeScript = clientRoutes.some((route) => route.navigation === true && !route.client)
207
208
  ? timingSink === undefined
208
209
  ? await writeNavigationRuntimeBundle(clientDir, project.clientConsolePureFunctions)
@@ -213,6 +214,10 @@ export async function buildApp(options) {
213
214
  : clientRoutes.map((route) => route.navigation === true && !route.client
214
215
  ? { ...route, navigationScript: navigationRuntimeScript }
215
216
  : route);
217
+ const clientManifestAssets = Array.from(new Set([
218
+ ...clientBundle.assets,
219
+ ...(navigationRuntimeScript === undefined ? [] : [navigationRuntimeScript]),
220
+ ])).sort();
216
221
  const prerenderedRoutes = timingSink === undefined
217
222
  ? await prerenderStaticRoutes({
218
223
  appDir: project.routesDir,
@@ -290,6 +295,7 @@ export async function buildApp(options) {
290
295
  : { serverModuleRenderFiles: serverModuleArtifacts.renderFiles }),
291
296
  };
292
297
  const clientManifest = {
298
+ ...(clientManifestAssets.length === 0 ? {} : { assets: clientManifestAssets }),
293
299
  ...(publicAssets.length === 0 ? {} : { publicAssets }),
294
300
  routes: clientManifestRoutes,
295
301
  };
@@ -1993,7 +1999,7 @@ async function renderCloudflareStringRoute(props) {
1993
1999
  for (const shell of layoutShells) {
1994
2000
  html += shell.prefix;
1995
2001
  }
1996
- html += String(await pageComponent(props) ?? "");
2002
+ html += withCloudflareHydrationMarkers(props, String(await pageComponent(props) ?? ""));
1997
2003
  for (const shell of [...layoutShells].reverse()) {
1998
2004
  html += shell.suffix;
1999
2005
  }
@@ -2130,7 +2136,7 @@ async function renderCloudflareStringRoute(props) {
2130
2136
  for (const shell of layoutShells) {
2131
2137
  html += shell.prefix;
2132
2138
  }
2133
- html += String(await pageComponent(props) ?? "");
2139
+ html += withCloudflareHydrationMarkers(props, String(await pageComponent(props) ?? ""));
2134
2140
  for (const shell of [...layoutShells].reverse()) {
2135
2141
  html += shell.suffix;
2136
2142
  }
@@ -2222,7 +2228,10 @@ function renderCloudflareStreamRoute(props) {
2222
2228
  const shell = layoutShells[index];
2223
2229
  $sink.append(index === 0 ? injectCloudflareHead(shell.prefix, metadata, routeHeadTags) : shell.prefix);
2224
2230
  }
2231
+ const hydrationMarker = cloudflareHydrationMarkerParts(props);
2232
+ $sink.append(hydrationMarker.prefix);
2225
2233
  await pageComponent($sink, props);
2234
+ $sink.append(hydrationMarker.suffix);
2226
2235
  renderOutOfOrderReorderScript($sink);
2227
2236
  for (const shell of [...layoutShells].reverse()) {
2228
2237
  $sink.append(shell.suffix);
@@ -2343,6 +2352,54 @@ function readSlotName(attributes) {
2343
2352
  return match?.[1] ?? match?.[2];
2344
2353
  }
2345
2354
 
2355
+ function withCloudflareHydrationMarkers(props, html) {
2356
+ const marker = cloudflareHydrationMarkerParts(props);
2357
+ return marker.prefix === "" && marker.suffix === "" ? html : \`\${marker.prefix}\${html}\${marker.suffix}\`;
2358
+ }
2359
+
2360
+ function cloudflareHydrationMarkerParts(props) {
2361
+ const route = props.clientManifest.routes.find((route) => route.path === props.route.path && route.client === true);
2362
+ if (route?.script === undefined) {
2363
+ return { prefix: "", suffix: "" };
2364
+ }
2365
+ const routeId = route.routeId ?? cloudflareRouteIdForPath(props.route.path);
2366
+ const escapedRouteId = escapeHtmlAttribute(routeId);
2367
+ const propsJson = escapeScriptJson(JSON.stringify({
2368
+ params: props.params,
2369
+ request: { url: props.request.url },
2370
+ data: props.data,
2371
+ }));
2372
+ const clientReferencesJson = route.clientReferenceManifest === undefined || route.clientReferenceManifest.length === 0
2373
+ ? undefined
2374
+ : escapeScriptJson(JSON.stringify(route.clientReferenceManifest));
2375
+ return {
2376
+ prefix: \`<div data-mreact-route-id="\${escapedRouteId}">\`,
2377
+ suffix: [
2378
+ "</div>",
2379
+ \`<script type="application/json" id="mreact-props-\${escapedRouteId}">\${propsJson}</script>\`,
2380
+ clientReferencesJson === undefined
2381
+ ? undefined
2382
+ : \`<script type="application/json" id="mreact-client-references-\${escapedRouteId}">\${clientReferencesJson}</script>\`,
2383
+ \`<script type="module" src="/_mreact/client/\${escapeHtmlAttribute(route.script)}"></script>\`,
2384
+ ].filter((part) => part !== undefined).join(""),
2385
+ };
2386
+ }
2387
+
2388
+ function escapeScriptJson(json) {
2389
+ return json.replaceAll("<", "\\\\u003c");
2390
+ }
2391
+
2392
+ function cloudflareRouteIdForPath(path) {
2393
+ if (path === "/") {
2394
+ return "index";
2395
+ }
2396
+ return path
2397
+ .slice(1)
2398
+ .replaceAll("/", "_")
2399
+ .replaceAll(":", "_")
2400
+ .replace(/[^A-Za-z0-9_$-]/g, "_");
2401
+ }
2402
+
2346
2403
  async function resolveRouteMetadata(modules, props) {
2347
2404
  const metadata = [];
2348
2405
  const context = {
@@ -3022,7 +3079,10 @@ async function writeClientRouteBundles(options) {
3022
3079
  }));
3023
3080
  const clientEntries = entries.filter((entry) => "build" in entry);
3024
3081
  if (clientEntries.length === 0) {
3025
- return entries.flatMap((entry) => ("manifest" in entry ? [entry.manifest] : []));
3082
+ return {
3083
+ assets: [],
3084
+ routes: entries.flatMap((entry) => ("manifest" in entry ? [entry.manifest] : [])),
3085
+ };
3026
3086
  }
3027
3087
  let output;
3028
3088
  try {
@@ -3069,7 +3129,17 @@ async function writeClientRouteBundles(options) {
3069
3129
  await mkdir(dirname(join(options.clientDir, asset.fileName)), { recursive: true });
3070
3130
  await writeFile(join(options.clientDir, asset.fileName), source);
3071
3131
  }
3072
- return entries.map((entry) => {
3132
+ const generatedAssets = new Set();
3133
+ for (const chunk of output.chunks) {
3134
+ generatedAssets.add(chunk.fileName);
3135
+ if (options.sourceMaps === "linked" && chunk.map !== undefined) {
3136
+ generatedAssets.add(`${chunk.fileName}.map`);
3137
+ }
3138
+ }
3139
+ for (const asset of output.assets ?? []) {
3140
+ generatedAssets.add(asset.fileName);
3141
+ }
3142
+ const routes = entries.map((entry) => {
3073
3143
  if (!("build" in entry)) {
3074
3144
  return entry.manifest;
3075
3145
  }
@@ -3089,6 +3159,10 @@ async function writeClientRouteBundles(options) {
3089
3159
  path: entry.route.path,
3090
3160
  kind: entry.route.kind,
3091
3161
  client: true,
3162
+ ...(entry.build.clientReferenceManifest === undefined ||
3163
+ entry.build.clientReferenceManifest.length === 0
3164
+ ? {}
3165
+ : { clientReferenceManifest: entry.build.clientReferenceManifest }),
3092
3166
  ...(entry.css.length === 0 ? {} : { css: entry.css }),
3093
3167
  ...(routeOutput.chunk.imports.length === 0 ? {} : { imports: routeOutput.chunk.imports }),
3094
3168
  ...(entry.navigation ? { navigation: entry.navigation } : {}),
@@ -3098,6 +3172,10 @@ async function writeClientRouteBundles(options) {
3098
3172
  devScript: clientScriptForPath(entry.route.path),
3099
3173
  };
3100
3174
  });
3175
+ return {
3176
+ assets: Array.from(generatedAssets).sort(),
3177
+ routes,
3178
+ };
3101
3179
  }
3102
3180
  async function writeRouteCssAssetBatches(options) {
3103
3181
  const cssInputs = await mapWithBuildConcurrency(options.pageRoutes, async (route) => {