@reckona/mreact-router 0.0.120 → 0.0.122
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/README.md +1 -1
- package/dist/build.d.ts +1 -0
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +117 -46
- package/dist/build.js.map +1 -1
- package/dist/client.d.ts +1 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +15 -1
- package/dist/client.js.map +1 -1
- package/dist/module-runner.js +14 -6
- package/dist/module-runner.js.map +1 -1
- package/dist/render.d.ts +1 -0
- package/dist/render.d.ts.map +1 -1
- package/dist/render.js +23 -2
- package/dist/render.js.map +1 -1
- package/dist/route-styles.d.ts +1 -0
- package/dist/route-styles.d.ts.map +1 -1
- package/dist/route-styles.js +23 -2
- package/dist/route-styles.js.map +1 -1
- package/dist/serve.d.ts.map +1 -1
- package/dist/serve.js +5 -0
- package/dist/serve.js.map +1 -1
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js +15 -1
- package/dist/vite.js.map +1 -1
- package/package.json +11 -11
- package/src/build.ts +552 -371
- package/src/client.ts +34 -11
- package/src/module-runner.ts +26 -11
- package/src/render.ts +26 -2
- package/src/route-styles.ts +30 -2
- package/src/serve.ts +11 -0
- package/src/vite.ts +24 -1
package/README.md
CHANGED
|
@@ -324,7 +324,7 @@ For Cloudflare Workers, `mreact-router build --target=cloudflare` emits `.mreact
|
|
|
324
324
|
|
|
325
325
|
For Cloudflare Pages advanced mode, run `mreact-router package cloudflare-pages --from .mreact --out .mreact/pages` after `mreact-router build --target=cloudflare`, then deploy with `wrangler pages deploy .mreact/pages`. The package command creates a Pages output directory with bundled `_worker.js`, `_mreact/client/*` static route assets, root public assets, and `mreact-cloudflare-pages-artifact.json`. Pages provides the `ASSETS` binding to `_worker.js`; mreact's generated worker reads that binding and serves only generated client manifest assets, route-linked CSS, and public files. The package step bundles the generated Worker entry, route registry, route chunks, and router adapter code, so application deploy scripts do not need to copy `worker.mjs` manually or decide whether Wrangler should bundle package imports. If your Worker graph includes dependencies that import Node builtins such as `node:util` or bare `util`, configure Cloudflare Pages with the `nodejs_compat` compatibility flag so the packaged Worker can use Cloudflare's Node.js compatibility runtime.
|
|
326
326
|
|
|
327
|
-
User Vite plugins from the project config are forwarded into router bundle builds after the `mreact-router` plugin itself is removed, so MDX-style syntax transforms and custom content loaders can participate in server, client, Cloudflare, and prerender bundles. Vite `define` values are also forwarded into generated Cloudflare server bundles, including `import.meta.env.*` aliases and plain define identifiers used by loaders and route handlers. Client assets, route stylesheet assets imported by pages/layouts/templates, and copied public assets are served only when they appear in the generated manifest allow-list. Dynamic routes resolve modules through a build-time registry keyed by `route.file`, not by constructing module ids from request input. Generated Cloudflare route modules preserve app-router layout/template shells and named slots for both string and `stream = true` pages, including route-local `<Await>` boundaries and local server-component imports. Generated Cloudflare server route modules dispatch method exports such as `GET`, `POST`, and `ALL` with decoded dynamic params plus `context.env`, `context.context`, `context.request`, and `context.route`, so handlers can use Worker bindings directly. The Cloudflare adapter marks streamed HTML with `Cache-Control: no-transform` and `Content-Encoding: identity` so Workers compression does not gzip-buffer the first shell before placeholders can paint. Pass `onResponse` to add cross-cutting response headers to rendered, static, asset, reload, not-found, and error responses. If a generated Cloudflare route module cannot produce the `data-mreact-route-id` marker contract required by client navigation, the adapter returns a reload signal for `x-mreact-navigation: 1` requests so the browser performs a normal document navigation without first buffering the full HTML response.
|
|
327
|
+
User Vite plugins from the project config are forwarded into router bundle builds after the `mreact-router` plugin itself is removed, so MDX-style syntax transforms and custom content loaders can participate in server, client, Cloudflare, and prerender bundles. Vite `define` values are also forwarded into generated Cloudflare server bundles, including `import.meta.env.*` aliases and plain define identifiers used by loaders and route handlers. Client assets, route stylesheet assets imported by pages/layouts/templates or special `error.tsx`/`not-found.tsx` boundaries, and copied public assets are served only when they appear in the generated manifest allow-list. Dynamic routes resolve modules through a build-time registry keyed by `route.file`, not by constructing module ids from request input. Generated Cloudflare route modules preserve app-router layout/template shells and named slots for both string and `stream = true` pages, including route-local `<Await>` boundaries and local server-component imports. Generated Cloudflare server route modules dispatch method exports such as `GET`, `POST`, and `ALL` with decoded dynamic params plus `context.env`, `context.context`, `context.request`, and `context.route`, so handlers can use Worker bindings directly. The Cloudflare adapter marks streamed HTML with `Cache-Control: no-transform` and `Content-Encoding: identity` so Workers compression does not gzip-buffer the first shell before placeholders can paint. Pass `onResponse` to add cross-cutting response headers to rendered, static, asset, reload, not-found, and error responses. If a generated Cloudflare route module cannot produce the `data-mreact-route-id` marker contract required by client navigation, the adapter returns a reload signal for `x-mreact-navigation: 1` requests so the browser performs a normal document navigation without first buffering the full HTML response.
|
|
328
328
|
|
|
329
329
|
For AWS Lambda, use `createPreloadedAwsLambdaRequestHandler()` with API Gateway
|
|
330
330
|
HTTP API v2 or Lambda Function URL payload format 2.0:
|
package/dist/build.d.ts
CHANGED
|
@@ -97,6 +97,7 @@ export interface BuiltRouteSourceAnalysisSummary {
|
|
|
97
97
|
authIncludesClaims: boolean;
|
|
98
98
|
cachePolicy?: RouteCachePolicy | undefined;
|
|
99
99
|
clientBoundaryImports: readonly string[];
|
|
100
|
+
clientBoundaryFallbackImports: readonly string[];
|
|
100
101
|
clientRoute: boolean;
|
|
101
102
|
hasLoader: boolean;
|
|
102
103
|
routeCode: string;
|
package/dist/build.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"AAwCA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":"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"}
|
package/dist/build.js
CHANGED
|
@@ -10,14 +10,14 @@ import { compilerModuleContextForSource, collectClientRouteReferences, createCli
|
|
|
10
10
|
import { buildClientRouteBatchOutput, buildNavigationRuntimeBundle, clientScriptForPath, routeIdForPath, } from "./navigation-runtime.js";
|
|
11
11
|
import { bundleAppRouterSourceModule, fileImportMetaUrlPlugin, importAppRouterSourceModule, } from "./module-runner.js";
|
|
12
12
|
import { scanAppRoutes } from "./routes.js";
|
|
13
|
-
import { appFileConventionForRootFilename
|
|
13
|
+
import { appFileConventionForRootFilename } from "./file-conventions.js";
|
|
14
14
|
import { resolveAppRouterProjectOptions, resolveBuildTargets, } from "./config.js";
|
|
15
15
|
import { routeCachePolicyFromSource } from "./cache.js";
|
|
16
16
|
import { bundleMiddlewareModuleCode, renderAppRequest } from "./render.js";
|
|
17
17
|
import { createAppRouterImportPolicyPlugin } from "./import-policy.js";
|
|
18
18
|
import { hasGenerateStaticParamsExport, hasLoaderExport, hasPrerenderExport, isStreamRouteSource, routeClosureMayUseAwaitBoundary, stripRouteBuildExports, stripRouteClientOnlyExports, stripRouteClientSource, stripRouteLoaderOnlyExports, stripRouteMetadataOnlyExports, stripRouteRequestOnlyExports, } from "./route-source.js";
|
|
19
19
|
import { bundleRouterModule, bundleRouterModules, } from "./bundle-pipeline.js";
|
|
20
|
-
import { collectRouteCssFilesFromSources } from "./route-styles.js";
|
|
20
|
+
import { collectRouteCssFilesFromSources, collectSpecialBoundaryFiles } from "./route-styles.js";
|
|
21
21
|
import { existingRouteShellCandidates } from "./route-shells.js";
|
|
22
22
|
import { sourceModuleCandidates } from "./source-modules.js";
|
|
23
23
|
import { collectBuildInferredServerActions } from "./server-action-inference.js";
|
|
@@ -217,6 +217,7 @@ export async function buildApp(options) {
|
|
|
217
217
|
: route);
|
|
218
218
|
const clientManifestAssets = Array.from(new Set([
|
|
219
219
|
...clientBundle.assets,
|
|
220
|
+
...clientBundle.styles.flatMap((style) => style.css),
|
|
220
221
|
...(navigationRuntimeScript === undefined ? [] : [navigationRuntimeScript]),
|
|
221
222
|
])).sort();
|
|
222
223
|
const prerenderedRoutes = timingSink === undefined
|
|
@@ -301,6 +302,7 @@ export async function buildApp(options) {
|
|
|
301
302
|
...(clientManifestAssets.length === 0 ? {} : { assets: clientManifestAssets }),
|
|
302
303
|
...(publicAssets.length === 0 ? {} : { publicAssets }),
|
|
303
304
|
routes: clientManifestRoutes,
|
|
305
|
+
...(clientBundle.styles.length === 0 ? {} : { styles: clientBundle.styles }),
|
|
304
306
|
};
|
|
305
307
|
const writeManifestFiles = async () => {
|
|
306
308
|
await Promise.all([
|
|
@@ -416,6 +418,7 @@ async function analyzeBuildRouteSources(options) {
|
|
|
416
418
|
{
|
|
417
419
|
...analyzeBuildSource(source, route.file),
|
|
418
420
|
clientBoundaryImports: clientInference.clientBoundaryImports,
|
|
421
|
+
clientBoundaryFallbackImports: clientInference.clientBoundaryFallbackImports,
|
|
419
422
|
clientRoute: clientInference.client,
|
|
420
423
|
file,
|
|
421
424
|
route,
|
|
@@ -784,7 +787,9 @@ async function findRuntimePackageJson(packageName, startDir) {
|
|
|
784
787
|
}
|
|
785
788
|
}
|
|
786
789
|
function isRuntimePackageSpecifier(specifier) {
|
|
787
|
-
if (specifier.startsWith(".") ||
|
|
790
|
+
if (specifier.startsWith(".") ||
|
|
791
|
+
specifier.startsWith("/") ||
|
|
792
|
+
/^[A-Za-z][A-Za-z0-9+.-]*:/.test(specifier)) {
|
|
788
793
|
return false;
|
|
789
794
|
}
|
|
790
795
|
const packageName = runtimePackageNameForSpecifier(specifier);
|
|
@@ -867,7 +872,9 @@ function isSourceModuleFile(file) {
|
|
|
867
872
|
return /\.(?:mreact\.tsx|tsx?|jsx?|mjs|mts|cjs|cts)$/.test(file);
|
|
868
873
|
}
|
|
869
874
|
function isAppRelativeFile(file, relativeRoutesDir) {
|
|
870
|
-
return relativeRoutesDir === "" ||
|
|
875
|
+
return (relativeRoutesDir === "" ||
|
|
876
|
+
file === relativeRoutesDir ||
|
|
877
|
+
file.startsWith(`${relativeRoutesDir}/`));
|
|
871
878
|
}
|
|
872
879
|
function moduleIdForBuildFile(file, relativeRoutesDir) {
|
|
873
880
|
return relativeRoutesDir === "" ? file : file.slice(relativeRoutesDir.length + 1);
|
|
@@ -921,9 +928,7 @@ async function copyAppFileConventionAssets(appDir, outDir) {
|
|
|
921
928
|
if (convention === undefined || convention.kind !== "asset") {
|
|
922
929
|
continue;
|
|
923
930
|
}
|
|
924
|
-
const outputPath = convention.path.startsWith("/")
|
|
925
|
-
? convention.path.slice(1)
|
|
926
|
-
: convention.path;
|
|
931
|
+
const outputPath = convention.path.startsWith("/") ? convention.path.slice(1) : convention.path;
|
|
927
932
|
await copyFile(join(appDir, entry.name), join(outDir, outputPath));
|
|
928
933
|
paths.push(convention.path);
|
|
929
934
|
}
|
|
@@ -1113,7 +1118,7 @@ async function buildServerModuleArtifacts(options) {
|
|
|
1113
1118
|
metadataArtifactFiles.has(file)) {
|
|
1114
1119
|
if (loaderArtifactFiles.has(file)) {
|
|
1115
1120
|
const code = requestBatchOutputs.get(routeRequestArtifactBatchKey(file, "loader")) ??
|
|
1116
|
-
await bundleRouteLoaderModuleCode({
|
|
1121
|
+
(await bundleRouteLoaderModuleCode({
|
|
1117
1122
|
appDir: options.project.routesDir,
|
|
1118
1123
|
bundleCache: options.bundleCache,
|
|
1119
1124
|
cacheDir: options.cacheDir,
|
|
@@ -1121,7 +1126,7 @@ async function buildServerModuleArtifacts(options) {
|
|
|
1121
1126
|
filename: absoluteFile,
|
|
1122
1127
|
importPolicy: requestModuleImportPolicy,
|
|
1123
1128
|
vitePlugins: options.vitePlugins,
|
|
1124
|
-
});
|
|
1129
|
+
}));
|
|
1125
1130
|
artifact.loader = {
|
|
1126
1131
|
code,
|
|
1127
1132
|
sourceHash: hashText(source),
|
|
@@ -1129,7 +1134,7 @@ async function buildServerModuleArtifacts(options) {
|
|
|
1129
1134
|
}
|
|
1130
1135
|
if (metadataArtifactFiles.has(file)) {
|
|
1131
1136
|
const code = requestBatchOutputs.get(routeRequestArtifactBatchKey(file, "metadata")) ??
|
|
1132
|
-
await bundleRouteRequestModuleCode({
|
|
1137
|
+
(await bundleRouteRequestModuleCode({
|
|
1133
1138
|
appDir: options.project.routesDir,
|
|
1134
1139
|
bundleCache: options.bundleCache,
|
|
1135
1140
|
cacheDir: options.cacheDir,
|
|
@@ -1138,7 +1143,7 @@ async function buildServerModuleArtifacts(options) {
|
|
|
1138
1143
|
importPolicy: requestModuleImportPolicy,
|
|
1139
1144
|
label: "Metadata",
|
|
1140
1145
|
vitePlugins: options.vitePlugins,
|
|
1141
|
-
});
|
|
1146
|
+
}));
|
|
1142
1147
|
artifact.routeMetadata = {
|
|
1143
1148
|
code,
|
|
1144
1149
|
sourceHash: hashText(source),
|
|
@@ -1148,7 +1153,7 @@ async function buildServerModuleArtifacts(options) {
|
|
|
1148
1153
|
const batchedRequestCode = requestBatchOutputs.get(routeRequestArtifactBatchKey(file, "request"));
|
|
1149
1154
|
artifact.request = {
|
|
1150
1155
|
code: batchedRequestCode ??
|
|
1151
|
-
await buildRequestModuleArtifactCode({
|
|
1156
|
+
(await buildRequestModuleArtifactCode({
|
|
1152
1157
|
appDir: options.project.routesDir,
|
|
1153
1158
|
bundleCache: options.bundleCache,
|
|
1154
1159
|
cacheDir: options.cacheDir,
|
|
@@ -1157,7 +1162,7 @@ async function buildServerModuleArtifacts(options) {
|
|
|
1157
1162
|
routeKind: route?.kind,
|
|
1158
1163
|
source,
|
|
1159
1164
|
vitePlugins: options.vitePlugins,
|
|
1160
|
-
}),
|
|
1165
|
+
})),
|
|
1161
1166
|
sourceHash: hashText(source),
|
|
1162
1167
|
};
|
|
1163
1168
|
}
|
|
@@ -1190,8 +1195,9 @@ async function buildServerModuleArtifacts(options) {
|
|
|
1190
1195
|
vitePlugins: options.vitePlugins,
|
|
1191
1196
|
})
|
|
1192
1197
|
: undefined;
|
|
1193
|
-
const clientBoundaryImports = routeAnalysis?.clientBoundaryImports ??
|
|
1194
|
-
|
|
1198
|
+
const clientBoundaryImports = routeAnalysis?.clientBoundaryImports ?? clientInference?.clientBoundaryImports ?? [];
|
|
1199
|
+
const clientBoundaryFallbackImports = routeAnalysis?.clientBoundaryFallbackImports ??
|
|
1200
|
+
clientInference?.clientBoundaryFallbackImports ??
|
|
1195
1201
|
[];
|
|
1196
1202
|
for (const diagnostic of clientInference?.diagnostics ?? []) {
|
|
1197
1203
|
console.warn(formatClientRouteInferenceDiagnostic(diagnostic));
|
|
@@ -1206,6 +1212,7 @@ async function buildServerModuleArtifacts(options) {
|
|
|
1206
1212
|
cache: options.serverTransformCache,
|
|
1207
1213
|
code,
|
|
1208
1214
|
clientBoundaryImports,
|
|
1215
|
+
clientBoundaryFallbackImports,
|
|
1209
1216
|
filename: join(options.projectRoot, file),
|
|
1210
1217
|
moduleContextCache: options.clientRouteInferenceCache,
|
|
1211
1218
|
serverOutput,
|
|
@@ -1284,6 +1291,7 @@ async function buildServerComponentBundleArtifactCode(options) {
|
|
|
1284
1291
|
async function transformServerRouteSource(options) {
|
|
1285
1292
|
const cacheKey = stableCacheKey({
|
|
1286
1293
|
clientBoundaryImports: options.clientBoundaryImports,
|
|
1294
|
+
clientBoundaryFallbackImports: options.clientBoundaryFallbackImports ?? [],
|
|
1287
1295
|
codeHash: hashText(options.code),
|
|
1288
1296
|
filename: resolve(options.filename),
|
|
1289
1297
|
serverOutput: options.serverOutput,
|
|
@@ -1302,6 +1310,7 @@ async function transformServerRouteSource(options) {
|
|
|
1302
1310
|
return transformCompilerModuleContext({
|
|
1303
1311
|
code: options.code,
|
|
1304
1312
|
clientBoundaryImports: options.clientBoundaryImports,
|
|
1313
|
+
clientBoundaryFallbackImports: options.clientBoundaryFallbackImports ?? [],
|
|
1305
1314
|
dev: false,
|
|
1306
1315
|
filename: options.filename,
|
|
1307
1316
|
moduleContext,
|
|
@@ -1316,8 +1325,11 @@ async function transformServerRouteSource(options) {
|
|
|
1316
1325
|
function builtRouteSourceAnalysisSummary(options) {
|
|
1317
1326
|
return {
|
|
1318
1327
|
authIncludesClaims: options.analysis.authIncludesClaims,
|
|
1319
|
-
...(options.analysis.cachePolicy === undefined
|
|
1328
|
+
...(options.analysis.cachePolicy === undefined
|
|
1329
|
+
? {}
|
|
1330
|
+
: { cachePolicy: options.analysis.cachePolicy }),
|
|
1320
1331
|
clientBoundaryImports: options.analysis.clientBoundaryImports,
|
|
1332
|
+
clientBoundaryFallbackImports: options.analysis.clientBoundaryFallbackImports,
|
|
1321
1333
|
clientRoute: options.analysis.clientRoute,
|
|
1322
1334
|
hasLoader: options.analysis.hasLoader,
|
|
1323
1335
|
routeCode: options.analysis.routeCode,
|
|
@@ -1536,9 +1548,9 @@ function isMiddlewareFile(appDir, file) {
|
|
|
1536
1548
|
return file === join(appDir, "middleware.ts") || file === join(appDir, "middleware.mreact.ts");
|
|
1537
1549
|
}
|
|
1538
1550
|
function hasMetadataExport(code) {
|
|
1539
|
-
return /\bexport\s+const\s+metadata\s*=/.test(code) ||
|
|
1551
|
+
return (/\bexport\s+const\s+metadata\s*=/.test(code) ||
|
|
1540
1552
|
/\bexport\s+(?:async\s+)?function\s+generateMetadata\b/.test(code) ||
|
|
1541
|
-
/\bexport\s*\{[^}]*\bgenerateMetadata\b[^}]*\}/.test(code);
|
|
1553
|
+
/\bexport\s*\{[^}]*\bgenerateMetadata\b[^}]*\}/.test(code));
|
|
1542
1554
|
}
|
|
1543
1555
|
async function readDeclaredProjectPackages(projectRoot) {
|
|
1544
1556
|
try {
|
|
@@ -1563,11 +1575,13 @@ async function writeCloudflareRouteModules(options) {
|
|
|
1563
1575
|
const analysis = options.sourceAnalysis.byFile.get(routeFile);
|
|
1564
1576
|
return analysis === undefined
|
|
1565
1577
|
? []
|
|
1566
|
-
: [
|
|
1578
|
+
: [
|
|
1579
|
+
{
|
|
1567
1580
|
route,
|
|
1568
1581
|
routeFile,
|
|
1569
1582
|
routeId: routeIdForPath(route.path),
|
|
1570
|
-
}
|
|
1583
|
+
},
|
|
1584
|
+
];
|
|
1571
1585
|
}));
|
|
1572
1586
|
await mkdir(routesDir, { recursive: true });
|
|
1573
1587
|
const serverRouteModules = await buildCloudflareServerRouteModuleBatch({
|
|
@@ -1583,7 +1597,8 @@ async function writeCloudflareRouteModules(options) {
|
|
|
1583
1597
|
cacheDir: options.cacheDir,
|
|
1584
1598
|
define: options.define,
|
|
1585
1599
|
routes: requiredRoutes
|
|
1586
|
-
.filter(({ route, routeFile }) => route.kind === "page" &&
|
|
1600
|
+
.filter(({ route, routeFile }) => route.kind === "page" &&
|
|
1601
|
+
options.sourceAnalysis.byRouteFile.get(routeFile)?.hasLoader === true)
|
|
1587
1602
|
.map(({ route, routeId }) => ({ filename: route.file, routeId })),
|
|
1588
1603
|
root: options.projectRoot,
|
|
1589
1604
|
vitePlugins: options.vitePlugins,
|
|
@@ -1690,9 +1705,7 @@ async function writeCloudflareRouteModules(options) {
|
|
|
1690
1705
|
throw new Error("Missing bundled Cloudflare component module.");
|
|
1691
1706
|
}
|
|
1692
1707
|
const componentImport = `./${componentFile.split("/").pop() ?? componentFile}`;
|
|
1693
|
-
routeModuleExports = [
|
|
1694
|
-
cloudflarePageRouteFacadeModuleSource(componentImport),
|
|
1695
|
-
];
|
|
1708
|
+
routeModuleExports = [cloudflarePageRouteFacadeModuleSource(componentImport)];
|
|
1696
1709
|
}
|
|
1697
1710
|
catch (error) {
|
|
1698
1711
|
throw new Error(`Failed to build Cloudflare route module for ${routeFile}: ${errorMessage(error)}`);
|
|
@@ -2073,9 +2086,7 @@ async function buildCloudflareServerComponentModule(options) {
|
|
|
2073
2086
|
filename: `${options.filename}.mreact-cloudflare-component.js`,
|
|
2074
2087
|
cacheDir: options.cacheDir,
|
|
2075
2088
|
define: options.define,
|
|
2076
|
-
modules: metadataModule === undefined
|
|
2077
|
-
? new Map()
|
|
2078
|
-
: new Map([["mreact:metadata", metadataModule]]),
|
|
2089
|
+
modules: metadataModule === undefined ? new Map() : new Map([["mreact:metadata", metadataModule]]),
|
|
2079
2090
|
plugins: [
|
|
2080
2091
|
cloudflareServerSourceTransformPlugin({
|
|
2081
2092
|
projectRoot: options.projectRoot,
|
|
@@ -2627,9 +2638,7 @@ export const slots = routeModule.slots;`;
|
|
|
2627
2638
|
cacheDir: options.cacheDir,
|
|
2628
2639
|
define: options.define,
|
|
2629
2640
|
filename: `${options.filename}.mreact-cloudflare-${options.serverOutput}-component.js`,
|
|
2630
|
-
modules: metadataModule === undefined
|
|
2631
|
-
? new Map()
|
|
2632
|
-
: new Map([["mreact:metadata", metadataModule]]),
|
|
2641
|
+
modules: metadataModule === undefined ? new Map() : new Map([["mreact:metadata", metadataModule]]),
|
|
2633
2642
|
plugins: [
|
|
2634
2643
|
cloudflareServerSourceTransformPlugin({
|
|
2635
2644
|
projectRoot: options.projectRoot,
|
|
@@ -2891,6 +2900,7 @@ async function transformCloudflareServerSource(options) {
|
|
|
2891
2900
|
const output = transformCompilerModuleContext({
|
|
2892
2901
|
code: options.source,
|
|
2893
2902
|
clientBoundaryImports: clientInference.clientBoundaryImports,
|
|
2903
|
+
clientBoundaryFallbackImports: clientInference.clientBoundaryFallbackImports,
|
|
2894
2904
|
dev: false,
|
|
2895
2905
|
filename: options.filename,
|
|
2896
2906
|
moduleContext,
|
|
@@ -2900,7 +2910,9 @@ async function transformCloudflareServerSource(options) {
|
|
|
2900
2910
|
});
|
|
2901
2911
|
const fatalDiagnostics = output.diagnostics.filter((diagnostic) => diagnostic.code !== "MR_UNSUPPORTED_SERVER_EVENT_HANDLER");
|
|
2902
2912
|
if (fatalDiagnostics.length > 0) {
|
|
2903
|
-
throw new Error(fatalDiagnostics
|
|
2913
|
+
throw new Error(fatalDiagnostics
|
|
2914
|
+
.map((diagnostic) => formatDiagnostic(options.filename, diagnostic))
|
|
2915
|
+
.join("\n"));
|
|
2904
2916
|
}
|
|
2905
2917
|
return output.code;
|
|
2906
2918
|
}
|
|
@@ -2932,9 +2944,18 @@ function cloudflareWorkspaceRuntimePlugin() {
|
|
|
2932
2944
|
"@reckona/mreact-compat/event-priority",
|
|
2933
2945
|
packageFile("react-compat", "@reckona/mreact-compat", "event-priority"),
|
|
2934
2946
|
],
|
|
2935
|
-
[
|
|
2936
|
-
|
|
2937
|
-
|
|
2947
|
+
[
|
|
2948
|
+
"@reckona/mreact-compat/flight",
|
|
2949
|
+
packageFile("react-compat", "@reckona/mreact-compat", "flight"),
|
|
2950
|
+
],
|
|
2951
|
+
[
|
|
2952
|
+
"@reckona/mreact-compat/hooks",
|
|
2953
|
+
packageFile("react-compat", "@reckona/mreact-compat", "hooks-entry"),
|
|
2954
|
+
],
|
|
2955
|
+
[
|
|
2956
|
+
"@reckona/mreact-compat/internal",
|
|
2957
|
+
packageFile("react-compat", "@reckona/mreact-compat", "internal"),
|
|
2958
|
+
],
|
|
2938
2959
|
[
|
|
2939
2960
|
"@reckona/mreact-compat/jsx-dev-runtime",
|
|
2940
2961
|
packageFile("react-compat", "@reckona/mreact-compat", "jsx-dev-runtime"),
|
|
@@ -2943,9 +2964,15 @@ function cloudflareWorkspaceRuntimePlugin() {
|
|
|
2943
2964
|
"@reckona/mreact-compat/jsx-runtime",
|
|
2944
2965
|
packageFile("react-compat", "@reckona/mreact-compat", "jsx-runtime"),
|
|
2945
2966
|
],
|
|
2946
|
-
[
|
|
2967
|
+
[
|
|
2968
|
+
"@reckona/mreact-compat/scheduler",
|
|
2969
|
+
packageFile("react-compat", "@reckona/mreact-compat", "scheduler"),
|
|
2970
|
+
],
|
|
2947
2971
|
["@reckona/mreact-query", packageFile("query", "@reckona/mreact-query", "index")],
|
|
2948
|
-
[
|
|
2972
|
+
[
|
|
2973
|
+
"@reckona/mreact-reactive-core",
|
|
2974
|
+
packageFile("reactive-core", "@reckona/mreact-reactive-core", "index"),
|
|
2975
|
+
],
|
|
2949
2976
|
[
|
|
2950
2977
|
"@reckona/mreact-router/adapters/cloudflare",
|
|
2951
2978
|
packageFile("router", "@reckona/mreact-router", "adapters/cloudflare"),
|
|
@@ -3046,6 +3073,14 @@ async function writeClientRouteBundles(options) {
|
|
|
3046
3073
|
sourceAnalysis: options.sourceAnalysis,
|
|
3047
3074
|
vitePlugins: options.vitePlugins,
|
|
3048
3075
|
});
|
|
3076
|
+
const specialCssAssets = await writeSpecialRouteCssAssetBatches({
|
|
3077
|
+
appDir: options.appDir,
|
|
3078
|
+
cacheDir: options.cacheDir,
|
|
3079
|
+
clientDir: options.clientDir,
|
|
3080
|
+
projectRoot: options.projectRoot,
|
|
3081
|
+
sourceAnalysis: options.sourceAnalysis,
|
|
3082
|
+
vitePlugins: options.vitePlugins,
|
|
3083
|
+
});
|
|
3049
3084
|
const entries = await Promise.all(options.routes.map(async (route) => {
|
|
3050
3085
|
if (route.kind !== "page") {
|
|
3051
3086
|
return {
|
|
@@ -3114,6 +3149,7 @@ async function writeClientRouteBundles(options) {
|
|
|
3114
3149
|
return {
|
|
3115
3150
|
assets: [],
|
|
3116
3151
|
routes: entries.flatMap((entry) => ("manifest" in entry ? [entry.manifest] : [])),
|
|
3152
|
+
styles: specialCssAssets,
|
|
3117
3153
|
};
|
|
3118
3154
|
}
|
|
3119
3155
|
let output;
|
|
@@ -3155,9 +3191,7 @@ async function writeClientRouteBundles(options) {
|
|
|
3155
3191
|
await writeFile(join(mapBaseDir, sourceMap), map);
|
|
3156
3192
|
}
|
|
3157
3193
|
for (const asset of output.assets ?? []) {
|
|
3158
|
-
const source = typeof asset.source === "string"
|
|
3159
|
-
? asset.source
|
|
3160
|
-
: Buffer.from(asset.source).toString("utf8");
|
|
3194
|
+
const source = typeof asset.source === "string" ? asset.source : Buffer.from(asset.source).toString("utf8");
|
|
3161
3195
|
await mkdir(dirname(join(options.clientDir, asset.fileName)), { recursive: true });
|
|
3162
3196
|
await writeFile(join(options.clientDir, asset.fileName), source);
|
|
3163
3197
|
}
|
|
@@ -3207,8 +3241,49 @@ async function writeClientRouteBundles(options) {
|
|
|
3207
3241
|
return {
|
|
3208
3242
|
assets: Array.from(generatedAssets).sort(),
|
|
3209
3243
|
routes,
|
|
3244
|
+
styles: specialCssAssets,
|
|
3210
3245
|
};
|
|
3211
3246
|
}
|
|
3247
|
+
async function writeSpecialRouteCssAssetBatches(options) {
|
|
3248
|
+
const boundaryFiles = await collectSpecialBoundaryFiles(options.appDir);
|
|
3249
|
+
const entries = await mapWithBuildConcurrency(boundaryFiles, async (file) => {
|
|
3250
|
+
const cssFiles = await collectRouteCssFilesFromSources({
|
|
3251
|
+
appDir: options.appDir,
|
|
3252
|
+
pageFile: file,
|
|
3253
|
+
projectRoot: options.projectRoot,
|
|
3254
|
+
readSource: (sourceFile) => buildSourceAnalysisForFile(options.sourceAnalysis, options.projectRoot, sourceFile)?.source,
|
|
3255
|
+
});
|
|
3256
|
+
if (cssFiles.length === 0) {
|
|
3257
|
+
return undefined;
|
|
3258
|
+
}
|
|
3259
|
+
const css = await writeRouteCssAssetsForFiles({
|
|
3260
|
+
cacheDir: options.cacheDir,
|
|
3261
|
+
clientDir: options.clientDir,
|
|
3262
|
+
cssFiles,
|
|
3263
|
+
pageFile: file,
|
|
3264
|
+
projectRoot: options.projectRoot,
|
|
3265
|
+
routeIds: [specialBoundaryRouteId(options.appDir, file)],
|
|
3266
|
+
vitePlugins: options.vitePlugins,
|
|
3267
|
+
});
|
|
3268
|
+
return css.length === 0
|
|
3269
|
+
? undefined
|
|
3270
|
+
: {
|
|
3271
|
+
css,
|
|
3272
|
+
file: relative(options.appDir, file).split(sep).join("/"),
|
|
3273
|
+
};
|
|
3274
|
+
});
|
|
3275
|
+
return entries
|
|
3276
|
+
.filter((entry) => entry !== undefined)
|
|
3277
|
+
.sort((left, right) => left.file.localeCompare(right.file));
|
|
3278
|
+
}
|
|
3279
|
+
function specialBoundaryRouteId(appDir, file) {
|
|
3280
|
+
const relativeFile = relative(appDir, file).split(sep);
|
|
3281
|
+
const filename = relativeFile.pop() ?? "boundary.tsx";
|
|
3282
|
+
const boundaryName = filename.replace(/(?:\.mreact)?\.tsx$/u, "");
|
|
3283
|
+
const routeParts = relativeFile.filter((part) => !part.startsWith("(") || !part.endsWith(")"));
|
|
3284
|
+
const path = `/${[...routeParts, boundaryName].join("/")}`;
|
|
3285
|
+
return routeIdForPath(path);
|
|
3286
|
+
}
|
|
3212
3287
|
async function writeRouteCssAssetBatches(options) {
|
|
3213
3288
|
const cssInputs = await mapWithBuildConcurrency(options.pageRoutes, async (route) => {
|
|
3214
3289
|
const cssFiles = await collectRouteCssFilesFromSources({
|
|
@@ -3276,9 +3351,7 @@ async function writeRouteCssAssetsForFiles(options) {
|
|
|
3276
3351
|
? (options.routeIds[0] ?? "index")
|
|
3277
3352
|
: `shared.${hashText(cssFiles.join("\0")).slice(0, 8)}`;
|
|
3278
3353
|
for (const [index, asset] of cssAssets.entries()) {
|
|
3279
|
-
const source = typeof asset.source === "string"
|
|
3280
|
-
? asset.source
|
|
3281
|
-
: Buffer.from(asset.source).toString("utf8");
|
|
3354
|
+
const source = typeof asset.source === "string" ? asset.source : Buffer.from(asset.source).toString("utf8");
|
|
3282
3355
|
const hash = createHash("sha256").update(source).digest("hex").slice(0, 8);
|
|
3283
3356
|
const cssFile = `assets/routes/${routeStem}${cssAssets.length === 1 ? "" : `.${index}`}.${hash}.css`;
|
|
3284
3357
|
await mkdir(dirname(join(options.clientDir, cssFile)), { recursive: true });
|
|
@@ -3552,6 +3625,7 @@ async function validateProductionRoutes(options) {
|
|
|
3552
3625
|
cache: options.serverTransformCache,
|
|
3553
3626
|
code: analysis.routeCode,
|
|
3554
3627
|
clientBoundaryImports: analysis.clientBoundaryImports,
|
|
3628
|
+
clientBoundaryFallbackImports: analysis.clientBoundaryFallbackImports,
|
|
3555
3629
|
filename: route.file,
|
|
3556
3630
|
moduleContextCache: options.clientRouteInferenceCache,
|
|
3557
3631
|
serverOutput: analysis.streamRoute ? "stream" : "string",
|
|
@@ -3576,10 +3650,7 @@ async function collectBuildFiles(projectRoot, allowedSourceDirs, appDir) {
|
|
|
3576
3650
|
}
|
|
3577
3651
|
return [{ file, relativeFile }];
|
|
3578
3652
|
});
|
|
3579
|
-
const fileContents = await mapWithBuildConcurrency(sourceFiles, async ({ file, relativeFile }) => [
|
|
3580
|
-
relativeFile,
|
|
3581
|
-
await readFile(file, "utf8"),
|
|
3582
|
-
]);
|
|
3653
|
+
const fileContents = await mapWithBuildConcurrency(sourceFiles, async ({ file, relativeFile }) => [relativeFile, await readFile(file, "utf8")]);
|
|
3583
3654
|
for (const [relativeFile, source] of fileContents) {
|
|
3584
3655
|
files[relativeFile] = source;
|
|
3585
3656
|
}
|