@reckona/mreact-router 0.0.119 → 0.0.121
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 +3 -1
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +96 -45
- package/dist/build.js.map +1 -1
- package/dist/bundle-pipeline.d.ts +3 -3
- package/dist/bundle-pipeline.d.ts.map +1 -1
- package/dist/bundle-pipeline.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.map +1 -1
- package/dist/render.js +19 -2
- package/dist/render.js.map +1 -1
- package/package.json +11 -11
- package/src/build.ts +523 -369
- package/src/bundle-pipeline.ts +2 -2
- package/src/client.ts +34 -11
- package/src/module-runner.ts +26 -11
- package/src/render.ts +20 -2
package/src/build.ts
CHANGED
|
@@ -39,9 +39,7 @@ import {
|
|
|
39
39
|
} from "./module-runner.js";
|
|
40
40
|
import { scanAppRoutes } from "./routes.js";
|
|
41
41
|
import type { AppRoute } from "./routes.js";
|
|
42
|
-
import {
|
|
43
|
-
appFileConventionForRootFilename,
|
|
44
|
-
} from "./file-conventions.js";
|
|
42
|
+
import { appFileConventionForRootFilename } from "./file-conventions.js";
|
|
45
43
|
import {
|
|
46
44
|
resolveAppRouterProjectOptions,
|
|
47
45
|
resolveBuildTargets,
|
|
@@ -98,7 +96,7 @@ export interface BuildAppOptions extends AppRouterProjectOptions {
|
|
|
98
96
|
onBuildPhaseTiming?: ((timing: BuildAppPhaseTiming) => void) | undefined;
|
|
99
97
|
outDir: string;
|
|
100
98
|
targets?: readonly AppRouterBuildTarget[] | undefined;
|
|
101
|
-
viteConfig?: Pick<UserConfig, "plugins"> | undefined;
|
|
99
|
+
viteConfig?: Pick<UserConfig, "define" | "plugins"> | undefined;
|
|
102
100
|
}
|
|
103
101
|
|
|
104
102
|
export type BuildAppPhase =
|
|
@@ -210,6 +208,7 @@ export interface BuiltRouteSourceAnalysisSummary {
|
|
|
210
208
|
authIncludesClaims: boolean;
|
|
211
209
|
cachePolicy?: RouteCachePolicy | undefined;
|
|
212
210
|
clientBoundaryImports: readonly string[];
|
|
211
|
+
clientBoundaryFallbackImports: readonly string[];
|
|
213
212
|
clientRoute: boolean;
|
|
214
213
|
hasLoader: boolean;
|
|
215
214
|
routeCode: string;
|
|
@@ -233,6 +232,7 @@ interface BuildSourceAnalysis {
|
|
|
233
232
|
|
|
234
233
|
interface BuildRouteSourceAnalysis extends BuildSourceAnalysis {
|
|
235
234
|
clientBoundaryImports: readonly string[];
|
|
235
|
+
clientBoundaryFallbackImports: readonly string[];
|
|
236
236
|
clientRoute: boolean;
|
|
237
237
|
file: string;
|
|
238
238
|
route: AppRoute & { kind: "page" };
|
|
@@ -273,6 +273,7 @@ export async function buildApp(options: BuildAppOptions): Promise<BuildAppResult
|
|
|
273
273
|
: await timeBuildPhase(timingSink, "scan", () =>
|
|
274
274
|
scanAppRoutes({ appDir: project.routesDir }),
|
|
275
275
|
);
|
|
276
|
+
const viteDefine = options.viteConfig?.define;
|
|
276
277
|
const vitePlugins = options.viteConfig?.plugins;
|
|
277
278
|
const files =
|
|
278
279
|
timingSink === undefined
|
|
@@ -427,7 +428,11 @@ export async function buildApp(options: BuildAppOptions): Promise<BuildAppResult
|
|
|
427
428
|
}));
|
|
428
429
|
const [serverModuleArtifacts, clientBundle] = await Promise.all([
|
|
429
430
|
timingSink === undefined
|
|
430
|
-
? writeServerModuleArtifactFiles(
|
|
431
|
+
? writeServerModuleArtifactFiles(
|
|
432
|
+
serverDir,
|
|
433
|
+
serverModules,
|
|
434
|
+
generatedImportPolicy.runtimePackages,
|
|
435
|
+
)
|
|
431
436
|
: timeBuildPhase(timingSink, "serverModuleArtifacts", () =>
|
|
432
437
|
writeServerModuleArtifactFiles(
|
|
433
438
|
serverDir,
|
|
@@ -519,6 +524,7 @@ export async function buildApp(options: BuildAppOptions): Promise<BuildAppResult
|
|
|
519
524
|
timingSink === undefined
|
|
520
525
|
? await writeCloudflareRouteModules({
|
|
521
526
|
cloudflareDir,
|
|
527
|
+
define: viteDefine,
|
|
522
528
|
files,
|
|
523
529
|
prerenderedRoutes,
|
|
524
530
|
projectRoot: project.projectRoot,
|
|
@@ -531,6 +537,7 @@ export async function buildApp(options: BuildAppOptions): Promise<BuildAppResult
|
|
|
531
537
|
: await timeBuildPhase(timingSink, "cloudflare", () =>
|
|
532
538
|
writeCloudflareRouteModules({
|
|
533
539
|
cloudflareDir,
|
|
540
|
+
define: viteDefine,
|
|
534
541
|
files,
|
|
535
542
|
prerenderedRoutes,
|
|
536
543
|
projectRoot: project.projectRoot,
|
|
@@ -740,6 +747,7 @@ async function analyzeBuildRouteSources(options: {
|
|
|
740
747
|
{
|
|
741
748
|
...analyzeBuildSource(source, route.file),
|
|
742
749
|
clientBoundaryImports: clientInference.clientBoundaryImports,
|
|
750
|
+
clientBoundaryFallbackImports: clientInference.clientBoundaryFallbackImports,
|
|
743
751
|
clientRoute: clientInference.client,
|
|
744
752
|
file,
|
|
745
753
|
route,
|
|
@@ -1201,7 +1209,11 @@ async function collectRuntimeOptionalPackages(options: {
|
|
|
1201
1209
|
{ packageName: options.packageName, optional: false, startDir: options.projectRoot },
|
|
1202
1210
|
];
|
|
1203
1211
|
|
|
1204
|
-
for (
|
|
1212
|
+
for (
|
|
1213
|
+
let index = 0;
|
|
1214
|
+
index < queue.length && seenPackageJson.size < maxRuntimePackageManifestReads;
|
|
1215
|
+
index += 1
|
|
1216
|
+
) {
|
|
1205
1217
|
const item = queue[index];
|
|
1206
1218
|
if (item === undefined || !isValidRuntimePackageName(item.packageName)) {
|
|
1207
1219
|
continue;
|
|
@@ -1297,7 +1309,11 @@ async function findRuntimePackageJson(
|
|
|
1297
1309
|
}
|
|
1298
1310
|
|
|
1299
1311
|
function isRuntimePackageSpecifier(specifier: string): boolean {
|
|
1300
|
-
if (
|
|
1312
|
+
if (
|
|
1313
|
+
specifier.startsWith(".") ||
|
|
1314
|
+
specifier.startsWith("/") ||
|
|
1315
|
+
/^[A-Za-z][A-Za-z0-9+.-]*:/.test(specifier)
|
|
1316
|
+
) {
|
|
1301
1317
|
return false;
|
|
1302
1318
|
}
|
|
1303
1319
|
|
|
@@ -1425,7 +1441,11 @@ function isSourceModuleFile(file: string): boolean {
|
|
|
1425
1441
|
}
|
|
1426
1442
|
|
|
1427
1443
|
function isAppRelativeFile(file: string, relativeRoutesDir: string): boolean {
|
|
1428
|
-
return
|
|
1444
|
+
return (
|
|
1445
|
+
relativeRoutesDir === "" ||
|
|
1446
|
+
file === relativeRoutesDir ||
|
|
1447
|
+
file.startsWith(`${relativeRoutesDir}/`)
|
|
1448
|
+
);
|
|
1429
1449
|
}
|
|
1430
1450
|
|
|
1431
1451
|
function moduleIdForBuildFile(file: string, relativeRoutesDir: string): string {
|
|
@@ -1465,10 +1485,7 @@ async function collectPublicAssetPaths(publicDir: string): Promise<string[]> {
|
|
|
1465
1485
|
return paths.sort();
|
|
1466
1486
|
}
|
|
1467
1487
|
|
|
1468
|
-
async function copyAppFileConventionAssets(
|
|
1469
|
-
appDir: string,
|
|
1470
|
-
outDir: string,
|
|
1471
|
-
): Promise<string[]> {
|
|
1488
|
+
async function copyAppFileConventionAssets(appDir: string, outDir: string): Promise<string[]> {
|
|
1472
1489
|
let entries: Dirent[];
|
|
1473
1490
|
try {
|
|
1474
1491
|
entries = await readdir(appDir, { withFileTypes: true });
|
|
@@ -1493,9 +1510,7 @@ async function copyAppFileConventionAssets(
|
|
|
1493
1510
|
continue;
|
|
1494
1511
|
}
|
|
1495
1512
|
|
|
1496
|
-
const outputPath = convention.path.startsWith("/")
|
|
1497
|
-
? convention.path.slice(1)
|
|
1498
|
-
: convention.path;
|
|
1513
|
+
const outputPath = convention.path.startsWith("/") ? convention.path.slice(1) : convention.path;
|
|
1499
1514
|
await copyFile(join(appDir, entry.name), join(outDir, outputPath));
|
|
1500
1515
|
paths.push(convention.path);
|
|
1501
1516
|
}
|
|
@@ -1745,205 +1760,219 @@ async function buildServerModuleArtifacts(options: {
|
|
|
1745
1760
|
}
|
|
1746
1761
|
}
|
|
1747
1762
|
|
|
1748
|
-
const requestBatchOutputs =
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
const artifactEntries = await mapWithBuildConcurrency(Object.entries(options.files), async ([file, source]) => {
|
|
1760
|
-
const absoluteFile = join(options.projectRoot, file);
|
|
1761
|
-
const route = routeByFile.get(file);
|
|
1762
|
-
const routeAnalysis = options.sourceAnalysis.byRouteFile.get(file);
|
|
1763
|
-
const artifact: BuiltServerModuleArtifact = {};
|
|
1763
|
+
const requestBatchOutputs =
|
|
1764
|
+
requestBatchEntries.length >= 3
|
|
1765
|
+
? await bundleRouteRequestModuleBatchCode({
|
|
1766
|
+
appDir: options.project.routesDir,
|
|
1767
|
+
bundleCache: options.bundleCache,
|
|
1768
|
+
cacheDir: options.cacheDir,
|
|
1769
|
+
entries: requestBatchEntries,
|
|
1770
|
+
importPolicy: requestModuleImportPolicy,
|
|
1771
|
+
vitePlugins: options.vitePlugins,
|
|
1772
|
+
})
|
|
1773
|
+
: new Map<string, string>();
|
|
1764
1774
|
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
await bundleRouteLoaderModuleCode({
|
|
1773
|
-
appDir: options.project.routesDir,
|
|
1774
|
-
bundleCache: options.bundleCache,
|
|
1775
|
-
cacheDir: options.cacheDir,
|
|
1776
|
-
code: stripRouteLoaderOnlyExports(source, absoluteFile),
|
|
1777
|
-
filename: absoluteFile,
|
|
1778
|
-
importPolicy: requestModuleImportPolicy,
|
|
1779
|
-
vitePlugins: options.vitePlugins,
|
|
1780
|
-
});
|
|
1781
|
-
artifact.loader = {
|
|
1782
|
-
code,
|
|
1783
|
-
sourceHash: hashText(source),
|
|
1784
|
-
};
|
|
1785
|
-
}
|
|
1775
|
+
const artifactEntries = await mapWithBuildConcurrency(
|
|
1776
|
+
Object.entries(options.files),
|
|
1777
|
+
async ([file, source]) => {
|
|
1778
|
+
const absoluteFile = join(options.projectRoot, file);
|
|
1779
|
+
const route = routeByFile.get(file);
|
|
1780
|
+
const routeAnalysis = options.sourceAnalysis.byRouteFile.get(file);
|
|
1781
|
+
const artifact: BuiltServerModuleArtifact = {};
|
|
1786
1782
|
|
|
1787
|
-
if (
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1783
|
+
if (
|
|
1784
|
+
requestArtifactFiles.has(file) ||
|
|
1785
|
+
loaderArtifactFiles.has(file) ||
|
|
1786
|
+
metadataArtifactFiles.has(file)
|
|
1787
|
+
) {
|
|
1788
|
+
if (loaderArtifactFiles.has(file)) {
|
|
1789
|
+
const code =
|
|
1790
|
+
requestBatchOutputs.get(routeRequestArtifactBatchKey(file, "loader")) ??
|
|
1791
|
+
(await bundleRouteLoaderModuleCode({
|
|
1792
|
+
appDir: options.project.routesDir,
|
|
1793
|
+
bundleCache: options.bundleCache,
|
|
1794
|
+
cacheDir: options.cacheDir,
|
|
1795
|
+
code: stripRouteLoaderOnlyExports(source, absoluteFile),
|
|
1796
|
+
filename: absoluteFile,
|
|
1797
|
+
importPolicy: requestModuleImportPolicy,
|
|
1798
|
+
vitePlugins: options.vitePlugins,
|
|
1799
|
+
}));
|
|
1800
|
+
artifact.loader = {
|
|
1801
|
+
code,
|
|
1802
|
+
sourceHash: hashText(source),
|
|
1803
|
+
};
|
|
1804
|
+
}
|
|
1804
1805
|
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
artifact.request = {
|
|
1810
|
-
code: batchedRequestCode ??
|
|
1811
|
-
await buildRequestModuleArtifactCode({
|
|
1806
|
+
if (metadataArtifactFiles.has(file)) {
|
|
1807
|
+
const code =
|
|
1808
|
+
requestBatchOutputs.get(routeRequestArtifactBatchKey(file, "metadata")) ??
|
|
1809
|
+
(await bundleRouteRequestModuleCode({
|
|
1812
1810
|
appDir: options.project.routesDir,
|
|
1813
1811
|
bundleCache: options.bundleCache,
|
|
1814
1812
|
cacheDir: options.cacheDir,
|
|
1813
|
+
code: stripRouteMetadataOnlyExports(source, absoluteFile),
|
|
1815
1814
|
filename: absoluteFile,
|
|
1816
1815
|
importPolicy: requestModuleImportPolicy,
|
|
1817
|
-
|
|
1818
|
-
source,
|
|
1816
|
+
label: "Metadata",
|
|
1819
1817
|
vitePlugins: options.vitePlugins,
|
|
1820
|
-
})
|
|
1821
|
-
|
|
1822
|
-
|
|
1818
|
+
}));
|
|
1819
|
+
artifact.routeMetadata = {
|
|
1820
|
+
code,
|
|
1821
|
+
sourceHash: hashText(source),
|
|
1822
|
+
};
|
|
1823
|
+
}
|
|
1824
|
+
|
|
1825
|
+
if (requestArtifactFiles.has(file)) {
|
|
1826
|
+
const batchedRequestCode = requestBatchOutputs.get(
|
|
1827
|
+
routeRequestArtifactBatchKey(file, "request"),
|
|
1828
|
+
);
|
|
1829
|
+
artifact.request = {
|
|
1830
|
+
code:
|
|
1831
|
+
batchedRequestCode ??
|
|
1832
|
+
(await buildRequestModuleArtifactCode({
|
|
1833
|
+
appDir: options.project.routesDir,
|
|
1834
|
+
bundleCache: options.bundleCache,
|
|
1835
|
+
cacheDir: options.cacheDir,
|
|
1836
|
+
filename: absoluteFile,
|
|
1837
|
+
importPolicy: requestModuleImportPolicy,
|
|
1838
|
+
routeKind: route?.kind,
|
|
1839
|
+
source,
|
|
1840
|
+
vitePlugins: options.vitePlugins,
|
|
1841
|
+
})),
|
|
1842
|
+
sourceHash: hashText(source),
|
|
1843
|
+
};
|
|
1844
|
+
}
|
|
1823
1845
|
}
|
|
1824
|
-
}
|
|
1825
1846
|
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1847
|
+
if (!isServerComponentFile(file)) {
|
|
1848
|
+
return Object.keys(artifact).length > 0 ? ([file, artifact] as const) : undefined;
|
|
1849
|
+
}
|
|
1829
1850
|
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1851
|
+
const closureUsesAwait =
|
|
1852
|
+
routeAnalysis?.streamRoute ??
|
|
1853
|
+
shouldBuildRouteAsStream({
|
|
1854
|
+
filename: file,
|
|
1855
|
+
files: options.files,
|
|
1856
|
+
projectRoot: options.projectRoot,
|
|
1857
|
+
source,
|
|
1858
|
+
});
|
|
1859
|
+
const streamRoute = route !== undefined && closureUsesAwait;
|
|
1860
|
+
const serverOutputs =
|
|
1861
|
+
streamRoute || (route === undefined && closureUsesAwait)
|
|
1862
|
+
? (["stream", "string"] as const)
|
|
1863
|
+
: (["string"] as const);
|
|
1864
|
+
const code =
|
|
1865
|
+
routeAnalysis?.routeCode ??
|
|
1866
|
+
(route === undefined ? source : stripRouteBuildExports(source, absoluteFile));
|
|
1867
|
+
const clientInference =
|
|
1868
|
+
routeAnalysis === undefined
|
|
1869
|
+
? await inferClientRouteModule({
|
|
1870
|
+
...(route === undefined ? {} : { appDir: options.project.routesDir }),
|
|
1871
|
+
cache: options.clientRouteInferenceCache,
|
|
1872
|
+
code:
|
|
1873
|
+
route === undefined
|
|
1874
|
+
? stripRouteClientOnlyExports(source, absoluteFile)
|
|
1875
|
+
: stripRouteClientSource({ code: source, filename: route.file }),
|
|
1876
|
+
filename: join(options.projectRoot, file),
|
|
1877
|
+
...(route === undefined ? {} : { routePath: route.path }),
|
|
1878
|
+
vitePlugins: options.vitePlugins,
|
|
1879
|
+
})
|
|
1880
|
+
: undefined;
|
|
1881
|
+
const clientBoundaryImports =
|
|
1882
|
+
routeAnalysis?.clientBoundaryImports ?? clientInference?.clientBoundaryImports ?? [];
|
|
1883
|
+
const clientBoundaryFallbackImports =
|
|
1884
|
+
routeAnalysis?.clientBoundaryFallbackImports ??
|
|
1885
|
+
clientInference?.clientBoundaryFallbackImports ??
|
|
1886
|
+
[];
|
|
1887
|
+
|
|
1888
|
+
for (const diagnostic of clientInference?.diagnostics ?? []) {
|
|
1889
|
+
console.warn(formatClientRouteInferenceDiagnostic(diagnostic));
|
|
1890
|
+
}
|
|
1860
1891
|
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1892
|
+
if (routeAnalysis !== undefined) {
|
|
1893
|
+
artifact.analysis = builtRouteSourceAnalysisSummary({
|
|
1894
|
+
analysis: routeAnalysis,
|
|
1895
|
+
});
|
|
1896
|
+
}
|
|
1864
1897
|
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1898
|
+
const serverOutputArtifacts = await mapWithBuildConcurrency(
|
|
1899
|
+
serverOutputs,
|
|
1900
|
+
async (serverOutput) => {
|
|
1901
|
+
const output = await transformServerRouteSource({
|
|
1902
|
+
cache: options.serverTransformCache,
|
|
1903
|
+
code,
|
|
1904
|
+
clientBoundaryImports,
|
|
1905
|
+
clientBoundaryFallbackImports,
|
|
1906
|
+
filename: join(options.projectRoot, file),
|
|
1907
|
+
moduleContextCache: options.clientRouteInferenceCache,
|
|
1908
|
+
serverOutput,
|
|
1909
|
+
});
|
|
1910
|
+
const fatalDiagnostics = output.diagnostics.filter(
|
|
1911
|
+
(diagnostic) => diagnostic.code !== "MR_UNSUPPORTED_SERVER_EVENT_HANDLER",
|
|
1912
|
+
);
|
|
1870
1913
|
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1914
|
+
if (fatalDiagnostics.length > 0) {
|
|
1915
|
+
if (
|
|
1916
|
+
serverOutput === "string" &&
|
|
1917
|
+
streamRoute &&
|
|
1918
|
+
route?.kind === "page" &&
|
|
1919
|
+
fatalDiagnostics.every(
|
|
1920
|
+
(diagnostic) => diagnostic.code === "MR_UNSUPPORTED_AWAIT_INNER_COMPONENT",
|
|
1921
|
+
)
|
|
1922
|
+
) {
|
|
1923
|
+
return undefined;
|
|
1924
|
+
}
|
|
1925
|
+
|
|
1926
|
+
throw new Error(
|
|
1927
|
+
fatalDiagnostics.map((diagnostic) => formatDiagnostic(file, diagnostic)).join("\n"),
|
|
1928
|
+
);
|
|
1929
|
+
}
|
|
1885
1930
|
|
|
1886
|
-
if (fatalDiagnostics.length > 0) {
|
|
1887
1931
|
if (
|
|
1888
1932
|
serverOutput === "string" &&
|
|
1889
1933
|
streamRoute &&
|
|
1890
1934
|
route?.kind === "page" &&
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
)
|
|
1935
|
+
source.includes("<Await") &&
|
|
1936
|
+
/\bLink\b/.test(source)
|
|
1894
1937
|
) {
|
|
1938
|
+
// Native Link renders pre-rendered children as HTML. Keep direct
|
|
1939
|
+
// Await renderers on the stream artifact so the string artifact
|
|
1940
|
+
// cannot drop deferred Link content before the boundary resolves.
|
|
1895
1941
|
return undefined;
|
|
1896
1942
|
}
|
|
1897
1943
|
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1944
|
+
return [
|
|
1945
|
+
serverOutput,
|
|
1946
|
+
{
|
|
1947
|
+
...(options.prebundleServerComponents
|
|
1948
|
+
? {
|
|
1949
|
+
bundleCode: await buildServerComponentBundleArtifactCode({
|
|
1950
|
+
clientRouteInferenceCache: options.clientRouteInferenceCache,
|
|
1951
|
+
code: output.code,
|
|
1952
|
+
filename: absoluteFile,
|
|
1953
|
+
root: options.projectRoot,
|
|
1954
|
+
serverOutput,
|
|
1955
|
+
vitePlugins: options.vitePlugins,
|
|
1956
|
+
}),
|
|
1957
|
+
}
|
|
1958
|
+
: {}),
|
|
1959
|
+
code: output.code,
|
|
1960
|
+
metadata: output.metadata,
|
|
1961
|
+
sourceHash: hashText(code),
|
|
1962
|
+
},
|
|
1963
|
+
] as const;
|
|
1964
|
+
},
|
|
1965
|
+
);
|
|
1902
1966
|
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
route?.kind === "page" &&
|
|
1907
|
-
source.includes("<Await") &&
|
|
1908
|
-
/\bLink\b/.test(source)
|
|
1909
|
-
) {
|
|
1910
|
-
// Native Link renders pre-rendered children as HTML. Keep direct
|
|
1911
|
-
// Await renderers on the stream artifact so the string artifact
|
|
1912
|
-
// cannot drop deferred Link content before the boundary resolves.
|
|
1913
|
-
return undefined;
|
|
1967
|
+
for (const entry of serverOutputArtifacts) {
|
|
1968
|
+
if (entry !== undefined) {
|
|
1969
|
+
artifact[entry[0]] = entry[1];
|
|
1914
1970
|
}
|
|
1915
|
-
|
|
1916
|
-
return [
|
|
1917
|
-
serverOutput,
|
|
1918
|
-
{
|
|
1919
|
-
...(options.prebundleServerComponents
|
|
1920
|
-
? {
|
|
1921
|
-
bundleCode: await buildServerComponentBundleArtifactCode({
|
|
1922
|
-
clientRouteInferenceCache: options.clientRouteInferenceCache,
|
|
1923
|
-
code: output.code,
|
|
1924
|
-
filename: absoluteFile,
|
|
1925
|
-
root: options.projectRoot,
|
|
1926
|
-
serverOutput,
|
|
1927
|
-
vitePlugins: options.vitePlugins,
|
|
1928
|
-
}),
|
|
1929
|
-
}
|
|
1930
|
-
: {}),
|
|
1931
|
-
code: output.code,
|
|
1932
|
-
metadata: output.metadata,
|
|
1933
|
-
sourceHash: hashText(code),
|
|
1934
|
-
},
|
|
1935
|
-
] as const;
|
|
1936
|
-
},
|
|
1937
|
-
);
|
|
1938
|
-
|
|
1939
|
-
for (const entry of serverOutputArtifacts) {
|
|
1940
|
-
if (entry !== undefined) {
|
|
1941
|
-
artifact[entry[0]] = entry[1];
|
|
1942
1971
|
}
|
|
1943
|
-
}
|
|
1944
1972
|
|
|
1945
|
-
|
|
1946
|
-
|
|
1973
|
+
return [file, artifact] as const;
|
|
1974
|
+
},
|
|
1975
|
+
);
|
|
1947
1976
|
|
|
1948
1977
|
for (const entry of artifactEntries) {
|
|
1949
1978
|
if (entry !== undefined) {
|
|
@@ -1981,6 +2010,7 @@ async function buildServerComponentBundleArtifactCode(options: {
|
|
|
1981
2010
|
async function transformServerRouteSource(options: {
|
|
1982
2011
|
cache: ServerTransformCache;
|
|
1983
2012
|
clientBoundaryImports: readonly string[];
|
|
2013
|
+
clientBoundaryFallbackImports?: readonly string[];
|
|
1984
2014
|
code: string;
|
|
1985
2015
|
filename: string;
|
|
1986
2016
|
moduleContextCache: ClientRouteInferenceCache;
|
|
@@ -1988,6 +2018,7 @@ async function transformServerRouteSource(options: {
|
|
|
1988
2018
|
}): Promise<ServerTransformOutput> {
|
|
1989
2019
|
const cacheKey = stableCacheKey({
|
|
1990
2020
|
clientBoundaryImports: options.clientBoundaryImports,
|
|
2021
|
+
clientBoundaryFallbackImports: options.clientBoundaryFallbackImports ?? [],
|
|
1991
2022
|
codeHash: hashText(options.code),
|
|
1992
2023
|
filename: resolve(options.filename),
|
|
1993
2024
|
serverOutput: options.serverOutput,
|
|
@@ -2009,6 +2040,7 @@ async function transformServerRouteSource(options: {
|
|
|
2009
2040
|
return transformCompilerModuleContext({
|
|
2010
2041
|
code: options.code,
|
|
2011
2042
|
clientBoundaryImports: options.clientBoundaryImports,
|
|
2043
|
+
clientBoundaryFallbackImports: options.clientBoundaryFallbackImports ?? [],
|
|
2012
2044
|
dev: false,
|
|
2013
2045
|
filename: options.filename,
|
|
2014
2046
|
moduleContext,
|
|
@@ -2026,8 +2058,11 @@ function builtRouteSourceAnalysisSummary(options: {
|
|
|
2026
2058
|
}): BuiltRouteSourceAnalysisSummary {
|
|
2027
2059
|
return {
|
|
2028
2060
|
authIncludesClaims: options.analysis.authIncludesClaims,
|
|
2029
|
-
...(options.analysis.cachePolicy === undefined
|
|
2061
|
+
...(options.analysis.cachePolicy === undefined
|
|
2062
|
+
? {}
|
|
2063
|
+
: { cachePolicy: options.analysis.cachePolicy }),
|
|
2030
2064
|
clientBoundaryImports: options.analysis.clientBoundaryImports,
|
|
2065
|
+
clientBoundaryFallbackImports: options.analysis.clientBoundaryFallbackImports,
|
|
2031
2066
|
clientRoute: options.analysis.clientRoute,
|
|
2032
2067
|
hasLoader: options.analysis.hasLoader,
|
|
2033
2068
|
routeCode: options.analysis.routeCode,
|
|
@@ -2086,7 +2121,10 @@ function usesRuntimeCacheControl(code: string): boolean {
|
|
|
2086
2121
|
return /\bcacheControl\s*\(/.test(code);
|
|
2087
2122
|
}
|
|
2088
2123
|
|
|
2089
|
-
function routeRequestArtifactBatchKey(
|
|
2124
|
+
function routeRequestArtifactBatchKey(
|
|
2125
|
+
file: string,
|
|
2126
|
+
kind: "loader" | "metadata" | "request",
|
|
2127
|
+
): string {
|
|
2090
2128
|
return `${kind}:${file}`;
|
|
2091
2129
|
}
|
|
2092
2130
|
|
|
@@ -2126,15 +2164,15 @@ async function buildRequestModuleArtifactCode(options: {
|
|
|
2126
2164
|
});
|
|
2127
2165
|
}
|
|
2128
2166
|
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2167
|
+
return await bundleRouteLoaderModuleCode({
|
|
2168
|
+
appDir: options.appDir,
|
|
2169
|
+
bundleCache: options.bundleCache,
|
|
2170
|
+
cacheDir: options.cacheDir,
|
|
2171
|
+
code: stripRouteRequestOnlyExports(options.source, options.filename),
|
|
2172
|
+
filename: options.filename,
|
|
2173
|
+
importPolicy: options.importPolicy,
|
|
2174
|
+
vitePlugins: options.vitePlugins,
|
|
2175
|
+
});
|
|
2138
2176
|
}
|
|
2139
2177
|
|
|
2140
2178
|
async function bundleRouteLoaderModuleCode(options: {
|
|
@@ -2211,24 +2249,29 @@ async function bundleRouteRequestModuleBatchCode(options: {
|
|
|
2211
2249
|
label: "Request artifact",
|
|
2212
2250
|
}),
|
|
2213
2251
|
],
|
|
2214
|
-
root:
|
|
2252
|
+
root:
|
|
2253
|
+
options.importPolicy?.projectRoot ?? dirname(options.entries[0]?.filename ?? options.appDir),
|
|
2215
2254
|
vitePlugins: options.vitePlugins,
|
|
2216
2255
|
});
|
|
2217
2256
|
|
|
2218
2257
|
if (output.chunks.some((chunk) => !chunk.isEntry)) {
|
|
2219
|
-
const fallbackEntries = await mapWithBuildConcurrency(
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2258
|
+
const fallbackEntries = await mapWithBuildConcurrency(
|
|
2259
|
+
options.entries,
|
|
2260
|
+
async (entry) =>
|
|
2261
|
+
[
|
|
2262
|
+
entry.key,
|
|
2263
|
+
await bundleRouteRequestModuleCode({
|
|
2264
|
+
appDir: options.appDir,
|
|
2265
|
+
bundleCache: options.bundleCache,
|
|
2266
|
+
cacheDir: options.cacheDir,
|
|
2267
|
+
code: entry.code,
|
|
2268
|
+
filename: entry.filename,
|
|
2269
|
+
importPolicy: options.importPolicy,
|
|
2270
|
+
label: entry.label,
|
|
2271
|
+
vitePlugins: options.vitePlugins,
|
|
2272
|
+
}),
|
|
2273
|
+
] as const,
|
|
2274
|
+
);
|
|
2232
2275
|
return new Map(fallbackEntries);
|
|
2233
2276
|
}
|
|
2234
2277
|
|
|
@@ -2343,9 +2386,11 @@ function isMiddlewareFile(appDir: string, file: string): boolean {
|
|
|
2343
2386
|
}
|
|
2344
2387
|
|
|
2345
2388
|
function hasMetadataExport(code: string): boolean {
|
|
2346
|
-
return
|
|
2389
|
+
return (
|
|
2390
|
+
/\bexport\s+const\s+metadata\s*=/.test(code) ||
|
|
2347
2391
|
/\bexport\s+(?:async\s+)?function\s+generateMetadata\b/.test(code) ||
|
|
2348
|
-
/\bexport\s*\{[^}]*\bgenerateMetadata\b[^}]*\}/.test(code)
|
|
2392
|
+
/\bexport\s*\{[^}]*\bgenerateMetadata\b[^}]*\}/.test(code)
|
|
2393
|
+
);
|
|
2349
2394
|
}
|
|
2350
2395
|
|
|
2351
2396
|
async function readDeclaredProjectPackages(projectRoot: string): Promise<string[]> {
|
|
@@ -2409,6 +2454,7 @@ interface RouteRequestModuleBatchEntry {
|
|
|
2409
2454
|
async function writeCloudflareRouteModules(options: {
|
|
2410
2455
|
cacheDir?: string | undefined;
|
|
2411
2456
|
cloudflareDir: string;
|
|
2457
|
+
define?: UserConfig["define"] | undefined;
|
|
2412
2458
|
files: Record<string, string>;
|
|
2413
2459
|
prerenderedRoutes: Record<string, BuiltPrerenderedRoute>;
|
|
2414
2460
|
projectRoot: string;
|
|
@@ -2428,11 +2474,13 @@ async function writeCloudflareRouteModules(options: {
|
|
|
2428
2474
|
|
|
2429
2475
|
return analysis === undefined
|
|
2430
2476
|
? []
|
|
2431
|
-
: [
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2477
|
+
: [
|
|
2478
|
+
{
|
|
2479
|
+
route,
|
|
2480
|
+
routeFile,
|
|
2481
|
+
routeId: routeIdForPath(route.path),
|
|
2482
|
+
},
|
|
2483
|
+
];
|
|
2436
2484
|
}),
|
|
2437
2485
|
);
|
|
2438
2486
|
|
|
@@ -2440,6 +2488,7 @@ async function writeCloudflareRouteModules(options: {
|
|
|
2440
2488
|
|
|
2441
2489
|
const serverRouteModules = await buildCloudflareServerRouteModuleBatch({
|
|
2442
2490
|
cacheDir: options.cacheDir,
|
|
2491
|
+
define: options.define,
|
|
2443
2492
|
routes: requiredRoutes
|
|
2444
2493
|
.filter(({ route }) => route.kind === "server" || route.kind === "metadata")
|
|
2445
2494
|
.map(({ route, routeId }) => ({ filename: route.file, routeId })),
|
|
@@ -2448,9 +2497,12 @@ async function writeCloudflareRouteModules(options: {
|
|
|
2448
2497
|
});
|
|
2449
2498
|
const loaderRouteModules = await buildCloudflareRouteLoaderModuleBatch({
|
|
2450
2499
|
cacheDir: options.cacheDir,
|
|
2500
|
+
define: options.define,
|
|
2451
2501
|
routes: requiredRoutes
|
|
2452
|
-
.filter(
|
|
2453
|
-
route
|
|
2502
|
+
.filter(
|
|
2503
|
+
({ route, routeFile }) =>
|
|
2504
|
+
route.kind === "page" &&
|
|
2505
|
+
options.sourceAnalysis.byRouteFile.get(routeFile)?.hasLoader === true,
|
|
2454
2506
|
)
|
|
2455
2507
|
.map(({ route, routeId }) => ({ filename: route.file, routeId })),
|
|
2456
2508
|
root: options.projectRoot,
|
|
@@ -2474,6 +2526,7 @@ async function writeCloudflareRouteModules(options: {
|
|
|
2474
2526
|
);
|
|
2475
2527
|
const directComponentModules = await buildCloudflareServerComponentModuleBatch({
|
|
2476
2528
|
cacheDir: options.cacheDir,
|
|
2529
|
+
define: options.define,
|
|
2477
2530
|
projectRoot: options.projectRoot,
|
|
2478
2531
|
routes: directComponentRoutes,
|
|
2479
2532
|
serverModules: options.serverModules,
|
|
@@ -2482,6 +2535,7 @@ async function writeCloudflareRouteModules(options: {
|
|
|
2482
2535
|
});
|
|
2483
2536
|
const stringShellComponentModules = await buildCloudflareStringRouteComponentModuleBatch({
|
|
2484
2537
|
cacheDir: options.cacheDir,
|
|
2538
|
+
define: options.define,
|
|
2485
2539
|
projectRoot: options.projectRoot,
|
|
2486
2540
|
routes: stringShellComponentRoutes,
|
|
2487
2541
|
serverModules: options.serverModules,
|
|
@@ -2496,112 +2550,120 @@ async function writeCloudflareRouteModules(options: {
|
|
|
2496
2550
|
writeCloudflareBatchedRouteModuleChunks(options.cloudflareDir, stringShellComponentModules),
|
|
2497
2551
|
]);
|
|
2498
2552
|
|
|
2499
|
-
const registryEntries = await mapWithBuildConcurrency(
|
|
2500
|
-
|
|
2501
|
-
|
|
2553
|
+
const registryEntries = await mapWithBuildConcurrency(
|
|
2554
|
+
requiredRoutes,
|
|
2555
|
+
async ({ route, routeFile, routeId }) => {
|
|
2556
|
+
const routeModuleFile = `routes/${routeId}.mjs`;
|
|
2557
|
+
let routeModuleExports: string[];
|
|
2502
2558
|
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2559
|
+
if (route.kind === "server" || route.kind === "metadata") {
|
|
2560
|
+
try {
|
|
2561
|
+
const serverRouteModule = serverRouteModules.entries.get(routeId);
|
|
2506
2562
|
|
|
2507
|
-
|
|
2508
|
-
|
|
2563
|
+
if (serverRouteModule === undefined) {
|
|
2564
|
+
throw new Error(`Missing bundled Cloudflare ${route.kind} route module.`);
|
|
2565
|
+
}
|
|
2566
|
+
|
|
2567
|
+
const serverRouteFile = serverRouteModule.fileName;
|
|
2568
|
+
const serverRouteImport = `./${serverRouteFile.split("/").pop() ?? serverRouteFile}`;
|
|
2569
|
+
routeModuleExports = [
|
|
2570
|
+
`export * from ${JSON.stringify(serverRouteImport)};`,
|
|
2571
|
+
...(route.kind === "metadata"
|
|
2572
|
+
? [`export { default } from ${JSON.stringify(serverRouteImport)};`]
|
|
2573
|
+
: []),
|
|
2574
|
+
];
|
|
2575
|
+
} catch (error) {
|
|
2576
|
+
throw new Error(
|
|
2577
|
+
`Failed to build Cloudflare ${route.kind} route module for ${routeFile}: ${errorMessage(error)}`,
|
|
2578
|
+
);
|
|
2509
2579
|
}
|
|
2510
2580
|
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
`export * from ${JSON.stringify(serverRouteImport)};`,
|
|
2515
|
-
...(route.kind === "metadata"
|
|
2516
|
-
? [`export { default } from ${JSON.stringify(serverRouteImport)};`]
|
|
2517
|
-
: []),
|
|
2518
|
-
];
|
|
2519
|
-
} catch (error) {
|
|
2520
|
-
throw new Error(
|
|
2521
|
-
`Failed to build Cloudflare ${route.kind} route module for ${routeFile}: ${errorMessage(error)}`,
|
|
2581
|
+
await writeFile(
|
|
2582
|
+
join(options.cloudflareDir, routeModuleFile),
|
|
2583
|
+
`${routeModuleExports.join("\n")}\n`,
|
|
2522
2584
|
);
|
|
2585
|
+
return `${JSON.stringify(routeFile)}: () => import(${JSON.stringify(`./${routeModuleFile}`)})`;
|
|
2523
2586
|
}
|
|
2524
2587
|
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
options.serverModules[routeFile]?.analysis?.streamRoute === true ||
|
|
2531
|
-
options.sourceAnalysis.byRouteFile.get(routeFile)?.streamRoute === true
|
|
2532
|
-
? "stream"
|
|
2533
|
-
: "string";
|
|
2588
|
+
const serverOutput =
|
|
2589
|
+
options.serverModules[routeFile]?.analysis?.streamRoute === true ||
|
|
2590
|
+
options.sourceAnalysis.byRouteFile.get(routeFile)?.streamRoute === true
|
|
2591
|
+
? "stream"
|
|
2592
|
+
: "string";
|
|
2534
2593
|
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
stringShellComponentRouteIds.has(routeId)
|
|
2594
|
+
try {
|
|
2595
|
+
const batchedComponent = stringShellComponentRouteIds.has(routeId)
|
|
2538
2596
|
? stringShellComponentModules.entries.get(routeId)
|
|
2539
2597
|
: directComponentRouteIds.has(routeId)
|
|
2540
2598
|
? directComponentModules.entries.get(routeId)
|
|
2541
2599
|
: undefined;
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2600
|
+
let componentFile = batchedComponent?.fileName;
|
|
2601
|
+
|
|
2602
|
+
if (batchedComponent === undefined) {
|
|
2603
|
+
const componentOutput =
|
|
2604
|
+
serverOutput === "stream"
|
|
2605
|
+
? await buildCloudflareStreamRouteComponentModule({
|
|
2606
|
+
cacheDir: options.cacheDir,
|
|
2607
|
+
define: options.define,
|
|
2608
|
+
filename: route.file,
|
|
2609
|
+
projectRoot: options.projectRoot,
|
|
2610
|
+
routesDir: options.routesDir,
|
|
2611
|
+
serverModules: options.serverModules,
|
|
2612
|
+
sourceAnalysis: options.sourceAnalysis,
|
|
2613
|
+
vitePlugins: options.vitePlugins,
|
|
2614
|
+
})
|
|
2615
|
+
: await buildCloudflareStringRouteComponentModule({
|
|
2616
|
+
cacheDir: options.cacheDir,
|
|
2617
|
+
define: options.define,
|
|
2618
|
+
filename: route.file,
|
|
2619
|
+
projectRoot: options.projectRoot,
|
|
2620
|
+
routesDir: options.routesDir,
|
|
2621
|
+
serverModules: options.serverModules,
|
|
2622
|
+
sourceAnalysis: options.sourceAnalysis,
|
|
2623
|
+
vitePlugins: options.vitePlugins,
|
|
2624
|
+
});
|
|
2625
|
+
|
|
2626
|
+
componentFile = `routes/${routeId}.${hashText(componentOutput).slice(0, 8)}.component.mjs`;
|
|
2627
|
+
await writeFile(join(options.cloudflareDir, componentFile), componentOutput);
|
|
2628
|
+
}
|
|
2565
2629
|
|
|
2566
|
-
componentFile
|
|
2567
|
-
|
|
2568
|
-
|
|
2630
|
+
if (componentFile === undefined) {
|
|
2631
|
+
throw new Error("Missing bundled Cloudflare component module.");
|
|
2632
|
+
}
|
|
2569
2633
|
|
|
2570
|
-
|
|
2571
|
-
|
|
2634
|
+
const componentImport = `./${componentFile.split("/").pop() ?? componentFile}`;
|
|
2635
|
+
routeModuleExports = [cloudflarePageRouteFacadeModuleSource(componentImport)];
|
|
2636
|
+
} catch (error) {
|
|
2637
|
+
throw new Error(
|
|
2638
|
+
`Failed to build Cloudflare route module for ${routeFile}: ${errorMessage(error)}`,
|
|
2639
|
+
);
|
|
2572
2640
|
}
|
|
2573
2641
|
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
];
|
|
2578
|
-
} catch (error) {
|
|
2579
|
-
throw new Error(
|
|
2580
|
-
`Failed to build Cloudflare route module for ${routeFile}: ${errorMessage(error)}`,
|
|
2581
|
-
);
|
|
2582
|
-
}
|
|
2642
|
+
if (options.sourceAnalysis.byRouteFile.get(routeFile)?.hasLoader === true) {
|
|
2643
|
+
try {
|
|
2644
|
+
const loaderModule = loaderRouteModules.entries.get(routeId);
|
|
2583
2645
|
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2646
|
+
if (loaderModule === undefined) {
|
|
2647
|
+
throw new Error("Missing bundled Cloudflare loader module.");
|
|
2648
|
+
}
|
|
2587
2649
|
|
|
2588
|
-
|
|
2589
|
-
|
|
2650
|
+
const loaderFile = loaderModule.fileName;
|
|
2651
|
+
const loaderImport = `./${loaderFile.split("/").pop() ?? loaderFile}`;
|
|
2652
|
+
routeModuleExports.push(`export { loader } from ${JSON.stringify(loaderImport)};`);
|
|
2653
|
+
} catch (error) {
|
|
2654
|
+
throw new Error(
|
|
2655
|
+
`Failed to build Cloudflare loader module for ${routeFile}: ${errorMessage(error)}`,
|
|
2656
|
+
);
|
|
2590
2657
|
}
|
|
2591
|
-
|
|
2592
|
-
const loaderFile = loaderModule.fileName;
|
|
2593
|
-
const loaderImport = `./${loaderFile.split("/").pop() ?? loaderFile}`;
|
|
2594
|
-
routeModuleExports.push(`export { loader } from ${JSON.stringify(loaderImport)};`);
|
|
2595
|
-
} catch (error) {
|
|
2596
|
-
throw new Error(
|
|
2597
|
-
`Failed to build Cloudflare loader module for ${routeFile}: ${errorMessage(error)}`,
|
|
2598
|
-
);
|
|
2599
2658
|
}
|
|
2600
|
-
}
|
|
2601
2659
|
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2660
|
+
await writeFile(
|
|
2661
|
+
join(options.cloudflareDir, routeModuleFile),
|
|
2662
|
+
`${routeModuleExports.join("\n")}\n`,
|
|
2663
|
+
);
|
|
2664
|
+
return `${JSON.stringify(routeFile)}: () => import(${JSON.stringify(`./${routeModuleFile}`)})`;
|
|
2665
|
+
},
|
|
2666
|
+
);
|
|
2605
2667
|
|
|
2606
2668
|
const registrySource = [
|
|
2607
2669
|
`export const routeModules = {`,
|
|
@@ -2754,6 +2816,7 @@ interface CloudflareShellFile {
|
|
|
2754
2816
|
|
|
2755
2817
|
async function buildCloudflareServerComponentModuleBatch(options: {
|
|
2756
2818
|
cacheDir?: string | undefined;
|
|
2819
|
+
define?: UserConfig["define"] | undefined;
|
|
2757
2820
|
projectRoot: string;
|
|
2758
2821
|
routes: readonly CloudflareBatchedComponentRoute[];
|
|
2759
2822
|
serverModules: Record<string, BuiltServerModuleArtifact>;
|
|
@@ -2769,6 +2832,7 @@ async function buildCloudflareServerComponentModuleBatch(options: {
|
|
|
2769
2832
|
options.routes.map(async (route) => {
|
|
2770
2833
|
const metadataModule = await buildCloudflareRouteMetadataExportModule({
|
|
2771
2834
|
cacheDir: options.cacheDir,
|
|
2835
|
+
define: options.define,
|
|
2772
2836
|
filename: route.filename,
|
|
2773
2837
|
hasMetadata: buildSourceAnalysisForFile(
|
|
2774
2838
|
options.sourceAnalysis,
|
|
@@ -2801,6 +2865,7 @@ async function buildCloudflareServerComponentModuleBatch(options: {
|
|
|
2801
2865
|
const output = await bundleRouterModules({
|
|
2802
2866
|
cacheDir: options.cacheDir,
|
|
2803
2867
|
chunkFileNames: "routes/chunks/[name].[hash].mjs",
|
|
2868
|
+
define: options.define,
|
|
2804
2869
|
entries: bundleEntries,
|
|
2805
2870
|
entryFileNames: "routes/[name].[hash].mjs",
|
|
2806
2871
|
minify: true,
|
|
@@ -2844,6 +2909,7 @@ async function buildCloudflareServerComponentModuleBatch(options: {
|
|
|
2844
2909
|
|
|
2845
2910
|
async function buildCloudflareStringRouteComponentModuleBatch(options: {
|
|
2846
2911
|
cacheDir?: string | undefined;
|
|
2912
|
+
define?: UserConfig["define"] | undefined;
|
|
2847
2913
|
projectRoot: string;
|
|
2848
2914
|
routes: readonly CloudflareBatchedStringRoute[];
|
|
2849
2915
|
serverModules: Record<string, BuiltServerModuleArtifact>;
|
|
@@ -2861,6 +2927,7 @@ async function buildCloudflareStringRouteComponentModuleBatch(options: {
|
|
|
2861
2927
|
const pageMetadataId = `mreact:metadata:${route.routeId}:page`;
|
|
2862
2928
|
const pageMetadataModule = await buildCloudflareRouteMetadataExportModule({
|
|
2863
2929
|
cacheDir: options.cacheDir,
|
|
2930
|
+
define: options.define,
|
|
2864
2931
|
filename: route.filename,
|
|
2865
2932
|
hasMetadata: buildSourceAnalysisForFile(
|
|
2866
2933
|
options.sourceAnalysis,
|
|
@@ -2878,7 +2945,9 @@ async function buildCloudflareStringRouteComponentModuleBatch(options: {
|
|
|
2878
2945
|
contents: pageMetadataModule,
|
|
2879
2946
|
resolveDir: dirname(route.filename),
|
|
2880
2947
|
});
|
|
2881
|
-
metadataImports.push(
|
|
2948
|
+
metadataImports.push(
|
|
2949
|
+
`import * as pageMetadataModule from ${JSON.stringify(pageMetadataId)};`,
|
|
2950
|
+
);
|
|
2882
2951
|
}
|
|
2883
2952
|
|
|
2884
2953
|
const shellMetadataImports = await Promise.all(
|
|
@@ -2886,6 +2955,7 @@ async function buildCloudflareStringRouteComponentModuleBatch(options: {
|
|
|
2886
2955
|
const shellMetadataId = `mreact:metadata:${route.routeId}:shell:${index}`;
|
|
2887
2956
|
const shellMetadataModule = await buildCloudflareRouteMetadataExportModule({
|
|
2888
2957
|
cacheDir: options.cacheDir,
|
|
2958
|
+
define: options.define,
|
|
2889
2959
|
filename: shell.file,
|
|
2890
2960
|
hasMetadata: buildSourceAnalysisForFile(
|
|
2891
2961
|
options.sourceAnalysis,
|
|
@@ -2926,6 +2996,7 @@ async function buildCloudflareStringRouteComponentModuleBatch(options: {
|
|
|
2926
2996
|
const output = await bundleRouterModules({
|
|
2927
2997
|
cacheDir: options.cacheDir,
|
|
2928
2998
|
chunkFileNames: "routes/chunks/[name].[hash].mjs",
|
|
2999
|
+
define: options.define,
|
|
2929
3000
|
entries: bundleEntries,
|
|
2930
3001
|
entryFileNames: "routes/[name].[hash].mjs",
|
|
2931
3002
|
minify: true,
|
|
@@ -3055,6 +3126,7 @@ ${cloudflareShellRuntimeSource()}`;
|
|
|
3055
3126
|
|
|
3056
3127
|
async function buildCloudflareServerComponentModule(options: {
|
|
3057
3128
|
cacheDir?: string | undefined;
|
|
3129
|
+
define?: UserConfig["define"] | undefined;
|
|
3058
3130
|
filename: string;
|
|
3059
3131
|
projectRoot: string;
|
|
3060
3132
|
serverOutput: ServerOutputMode;
|
|
@@ -3064,8 +3136,13 @@ async function buildCloudflareServerComponentModule(options: {
|
|
|
3064
3136
|
}): Promise<string> {
|
|
3065
3137
|
const metadataModule = await buildCloudflareRouteMetadataExportModule({
|
|
3066
3138
|
cacheDir: options.cacheDir,
|
|
3139
|
+
define: options.define,
|
|
3067
3140
|
filename: options.filename,
|
|
3068
|
-
hasMetadata: buildSourceAnalysisForFile(
|
|
3141
|
+
hasMetadata: buildSourceAnalysisForFile(
|
|
3142
|
+
options.sourceAnalysis,
|
|
3143
|
+
options.projectRoot,
|
|
3144
|
+
options.filename,
|
|
3145
|
+
)?.hasMetadata,
|
|
3069
3146
|
root: options.projectRoot,
|
|
3070
3147
|
vitePlugins: options.vitePlugins,
|
|
3071
3148
|
});
|
|
@@ -3078,9 +3155,9 @@ async function buildCloudflareServerComponentModule(options: {
|
|
|
3078
3155
|
entry,
|
|
3079
3156
|
filename: `${options.filename}.mreact-cloudflare-component.js`,
|
|
3080
3157
|
cacheDir: options.cacheDir,
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
: new Map([["mreact:metadata", metadataModule]]),
|
|
3158
|
+
define: options.define,
|
|
3159
|
+
modules:
|
|
3160
|
+
metadataModule === undefined ? new Map() : new Map([["mreact:metadata", metadataModule]]),
|
|
3084
3161
|
plugins: [
|
|
3085
3162
|
cloudflareServerSourceTransformPlugin({
|
|
3086
3163
|
projectRoot: options.projectRoot,
|
|
@@ -3113,6 +3190,7 @@ export const slots = routeModule.slots;`;
|
|
|
3113
3190
|
|
|
3114
3191
|
async function buildCloudflareStringRouteComponentModule(options: {
|
|
3115
3192
|
cacheDir?: string | undefined;
|
|
3193
|
+
define?: UserConfig["define"] | undefined;
|
|
3116
3194
|
filename: string;
|
|
3117
3195
|
projectRoot: string;
|
|
3118
3196
|
routesDir: string;
|
|
@@ -3125,6 +3203,7 @@ async function buildCloudflareStringRouteComponentModule(options: {
|
|
|
3125
3203
|
if (shellFiles.length === 0) {
|
|
3126
3204
|
return buildCloudflareServerComponentModule({
|
|
3127
3205
|
cacheDir: options.cacheDir,
|
|
3206
|
+
define: options.define,
|
|
3128
3207
|
filename: options.filename,
|
|
3129
3208
|
projectRoot: options.projectRoot,
|
|
3130
3209
|
serverModules: options.serverModules,
|
|
@@ -3136,6 +3215,7 @@ async function buildCloudflareStringRouteComponentModule(options: {
|
|
|
3136
3215
|
|
|
3137
3216
|
const pageModule = await buildCloudflareComponentExportModule({
|
|
3138
3217
|
cacheDir: options.cacheDir,
|
|
3218
|
+
define: options.define,
|
|
3139
3219
|
filename: options.filename,
|
|
3140
3220
|
projectRoot: options.projectRoot,
|
|
3141
3221
|
serverModules: options.serverModules,
|
|
@@ -3147,6 +3227,7 @@ async function buildCloudflareStringRouteComponentModule(options: {
|
|
|
3147
3227
|
shellFiles.map((shell) =>
|
|
3148
3228
|
buildCloudflareComponentExportModule({
|
|
3149
3229
|
cacheDir: options.cacheDir,
|
|
3230
|
+
define: options.define,
|
|
3150
3231
|
filename: shell.file,
|
|
3151
3232
|
projectRoot: options.projectRoot,
|
|
3152
3233
|
serverModules: options.serverModules,
|
|
@@ -3156,7 +3237,9 @@ async function buildCloudflareStringRouteComponentModule(options: {
|
|
|
3156
3237
|
}),
|
|
3157
3238
|
),
|
|
3158
3239
|
);
|
|
3159
|
-
const shellImports = shellFiles.map(
|
|
3240
|
+
const shellImports = shellFiles.map(
|
|
3241
|
+
(_, index) => `import * as shell${index} from "mreact:shell-${index}";`,
|
|
3242
|
+
);
|
|
3160
3243
|
const shellDefinitions = shellFiles.map(
|
|
3161
3244
|
(shell, index) =>
|
|
3162
3245
|
`{ component: selectComponent(shell${index}, ${JSON.stringify(shell.file)}), id: ${JSON.stringify(shell.id)}, kind: ${JSON.stringify(shell.kind)}, module: shell${index} }`,
|
|
@@ -3215,6 +3298,7 @@ ${cloudflareShellRuntimeSource()}`;
|
|
|
3215
3298
|
return bundleCloudflareVirtualModule({
|
|
3216
3299
|
entry,
|
|
3217
3300
|
cacheDir: options.cacheDir,
|
|
3301
|
+
define: options.define,
|
|
3218
3302
|
filename: `${options.filename}.mreact-cloudflare-string-route.js`,
|
|
3219
3303
|
modules: new Map([
|
|
3220
3304
|
["mreact:page", pageModule],
|
|
@@ -3229,6 +3313,7 @@ ${cloudflareShellRuntimeSource()}`;
|
|
|
3229
3313
|
|
|
3230
3314
|
async function buildCloudflareStreamRouteComponentModule(options: {
|
|
3231
3315
|
cacheDir?: string | undefined;
|
|
3316
|
+
define?: UserConfig["define"] | undefined;
|
|
3232
3317
|
filename: string;
|
|
3233
3318
|
projectRoot: string;
|
|
3234
3319
|
routesDir: string;
|
|
@@ -3238,6 +3323,7 @@ async function buildCloudflareStreamRouteComponentModule(options: {
|
|
|
3238
3323
|
}): Promise<string> {
|
|
3239
3324
|
const pageModule = await buildCloudflareComponentExportModule({
|
|
3240
3325
|
cacheDir: options.cacheDir,
|
|
3326
|
+
define: options.define,
|
|
3241
3327
|
filename: options.filename,
|
|
3242
3328
|
projectRoot: options.projectRoot,
|
|
3243
3329
|
serverModules: options.serverModules,
|
|
@@ -3250,6 +3336,7 @@ async function buildCloudflareStreamRouteComponentModule(options: {
|
|
|
3250
3336
|
shellFiles.map((shell) =>
|
|
3251
3337
|
buildCloudflareComponentExportModule({
|
|
3252
3338
|
cacheDir: options.cacheDir,
|
|
3339
|
+
define: options.define,
|
|
3253
3340
|
filename: shell.file,
|
|
3254
3341
|
projectRoot: options.projectRoot,
|
|
3255
3342
|
serverModules: options.serverModules,
|
|
@@ -3259,7 +3346,9 @@ async function buildCloudflareStreamRouteComponentModule(options: {
|
|
|
3259
3346
|
}),
|
|
3260
3347
|
),
|
|
3261
3348
|
);
|
|
3262
|
-
const shellImports = shellFiles.map(
|
|
3349
|
+
const shellImports = shellFiles.map(
|
|
3350
|
+
(_, index) => `import * as shell${index} from "mreact:shell-${index}";`,
|
|
3351
|
+
);
|
|
3263
3352
|
const shellDefinitions = shellFiles.map(
|
|
3264
3353
|
(shell, index) =>
|
|
3265
3354
|
`{ component: selectComponent(shell${index}, ${JSON.stringify(shell.file)}), id: ${JSON.stringify(shell.id)}, kind: ${JSON.stringify(shell.kind)}, module: shell${index} }`,
|
|
@@ -3336,6 +3425,7 @@ ${cloudflareShellRuntimeSource()}`;
|
|
|
3336
3425
|
return bundleCloudflareVirtualModule({
|
|
3337
3426
|
entry,
|
|
3338
3427
|
cacheDir: options.cacheDir,
|
|
3428
|
+
define: options.define,
|
|
3339
3429
|
filename: `${options.filename}.mreact-cloudflare-stream-route.js`,
|
|
3340
3430
|
modules: new Map([
|
|
3341
3431
|
["mreact:page", pageModule],
|
|
@@ -3646,6 +3736,7 @@ function escapeHtml(value) {
|
|
|
3646
3736
|
|
|
3647
3737
|
async function buildCloudflareComponentExportModule(options: {
|
|
3648
3738
|
cacheDir?: string | undefined;
|
|
3739
|
+
define?: UserConfig["define"] | undefined;
|
|
3649
3740
|
filename: string;
|
|
3650
3741
|
projectRoot: string;
|
|
3651
3742
|
serverModules: Record<string, BuiltServerModuleArtifact>;
|
|
@@ -3655,8 +3746,13 @@ async function buildCloudflareComponentExportModule(options: {
|
|
|
3655
3746
|
}): Promise<string> {
|
|
3656
3747
|
const metadataModule = await buildCloudflareRouteMetadataExportModule({
|
|
3657
3748
|
cacheDir: options.cacheDir,
|
|
3749
|
+
define: options.define,
|
|
3658
3750
|
filename: options.filename,
|
|
3659
|
-
hasMetadata: buildSourceAnalysisForFile(
|
|
3751
|
+
hasMetadata: buildSourceAnalysisForFile(
|
|
3752
|
+
options.sourceAnalysis,
|
|
3753
|
+
options.projectRoot,
|
|
3754
|
+
options.filename,
|
|
3755
|
+
)?.hasMetadata,
|
|
3660
3756
|
root: options.projectRoot,
|
|
3661
3757
|
vitePlugins: options.vitePlugins,
|
|
3662
3758
|
});
|
|
@@ -3673,10 +3769,10 @@ export const slots = routeModule.slots;`;
|
|
|
3673
3769
|
return bundleCloudflareVirtualModule({
|
|
3674
3770
|
entry,
|
|
3675
3771
|
cacheDir: options.cacheDir,
|
|
3772
|
+
define: options.define,
|
|
3676
3773
|
filename: `${options.filename}.mreact-cloudflare-${options.serverOutput}-component.js`,
|
|
3677
|
-
modules:
|
|
3678
|
-
? new Map()
|
|
3679
|
-
: new Map([["mreact:metadata", metadataModule]]),
|
|
3774
|
+
modules:
|
|
3775
|
+
metadataModule === undefined ? new Map() : new Map([["mreact:metadata", metadataModule]]),
|
|
3680
3776
|
plugins: [
|
|
3681
3777
|
cloudflareServerSourceTransformPlugin({
|
|
3682
3778
|
projectRoot: options.projectRoot,
|
|
@@ -3707,12 +3803,14 @@ async function writeCloudflareBatchedRouteModuleChunks(
|
|
|
3707
3803
|
|
|
3708
3804
|
async function buildCloudflareRouteLoaderModuleBatch(options: {
|
|
3709
3805
|
cacheDir?: string | undefined;
|
|
3806
|
+
define?: UserConfig["define"] | undefined;
|
|
3710
3807
|
routes: readonly { filename: string; routeId: string }[];
|
|
3711
3808
|
root: string;
|
|
3712
3809
|
vitePlugins?: readonly PluginOption[] | undefined;
|
|
3713
3810
|
}): Promise<CloudflareBatchedRouteModules> {
|
|
3714
3811
|
return await bundleCloudflareModuleBatch({
|
|
3715
3812
|
cacheDir: options.cacheDir,
|
|
3813
|
+
define: options.define,
|
|
3716
3814
|
entries: options.routes.map((route) => ({
|
|
3717
3815
|
code: cloudflareRouteLoaderModuleEntry(route.filename),
|
|
3718
3816
|
filename: `${route.filename}.mreact-cloudflare-loader.js`,
|
|
@@ -3726,12 +3824,14 @@ async function buildCloudflareRouteLoaderModuleBatch(options: {
|
|
|
3726
3824
|
|
|
3727
3825
|
export async function __buildCloudflareRouteLoaderModuleBatchForTests(options: {
|
|
3728
3826
|
cacheDir?: string | undefined;
|
|
3827
|
+
define?: UserConfig["define"] | undefined;
|
|
3729
3828
|
projectRoot: string;
|
|
3730
3829
|
routes: readonly { filename: string; routeId: string }[];
|
|
3731
3830
|
vitePlugins?: readonly PluginOption[] | undefined;
|
|
3732
3831
|
}): Promise<Record<string, string>> {
|
|
3733
3832
|
const output = await buildCloudflareRouteLoaderModuleBatch({
|
|
3734
3833
|
cacheDir: options.cacheDir,
|
|
3834
|
+
define: options.define,
|
|
3735
3835
|
root: options.projectRoot,
|
|
3736
3836
|
routes: options.routes,
|
|
3737
3837
|
vitePlugins: options.vitePlugins,
|
|
@@ -3744,12 +3844,14 @@ export async function __buildCloudflareRouteLoaderModuleBatchForTests(options: {
|
|
|
3744
3844
|
|
|
3745
3845
|
async function buildCloudflareServerRouteModuleBatch(options: {
|
|
3746
3846
|
cacheDir?: string | undefined;
|
|
3847
|
+
define?: UserConfig["define"] | undefined;
|
|
3747
3848
|
routes: readonly { filename: string; routeId: string }[];
|
|
3748
3849
|
root: string;
|
|
3749
3850
|
vitePlugins?: readonly PluginOption[] | undefined;
|
|
3750
3851
|
}): Promise<CloudflareBatchedRouteModules> {
|
|
3751
3852
|
return await bundleCloudflareModuleBatch({
|
|
3752
3853
|
cacheDir: options.cacheDir,
|
|
3854
|
+
define: options.define,
|
|
3753
3855
|
entries: options.routes.map((route) => ({
|
|
3754
3856
|
code: cloudflareServerRouteModuleEntry(route.filename),
|
|
3755
3857
|
filename: `${route.filename}.mreact-cloudflare-server-route.js`,
|
|
@@ -3763,6 +3865,7 @@ async function buildCloudflareServerRouteModuleBatch(options: {
|
|
|
3763
3865
|
|
|
3764
3866
|
async function bundleCloudflareModuleBatch(options: {
|
|
3765
3867
|
cacheDir?: string | undefined;
|
|
3868
|
+
define?: UserConfig["define"] | undefined;
|
|
3766
3869
|
entries: readonly {
|
|
3767
3870
|
code: string;
|
|
3768
3871
|
filename: string;
|
|
@@ -3779,6 +3882,7 @@ async function bundleCloudflareModuleBatch(options: {
|
|
|
3779
3882
|
const output = await bundleRouterModules({
|
|
3780
3883
|
cacheDir: options.cacheDir,
|
|
3781
3884
|
chunkFileNames: "routes/chunks/[name].[hash].mjs",
|
|
3885
|
+
define: options.define,
|
|
3782
3886
|
entries: options.entries,
|
|
3783
3887
|
entryFileNames: "routes/[name].[hash].mjs",
|
|
3784
3888
|
minify: true,
|
|
@@ -3817,6 +3921,7 @@ function cloudflareRouteLoaderModuleEntry(filename: string): string {
|
|
|
3817
3921
|
|
|
3818
3922
|
async function buildCloudflareRouteMetadataExportModule(options: {
|
|
3819
3923
|
cacheDir?: string | undefined;
|
|
3924
|
+
define?: UserConfig["define"] | undefined;
|
|
3820
3925
|
filename: string;
|
|
3821
3926
|
hasMetadata?: boolean | undefined;
|
|
3822
3927
|
root?: string | undefined;
|
|
@@ -3833,6 +3938,7 @@ export const metadata = routeMetadataModule.metadata;`;
|
|
|
3833
3938
|
return bundleCloudflareModule({
|
|
3834
3939
|
entry,
|
|
3835
3940
|
cacheDir: options.cacheDir,
|
|
3941
|
+
define: options.define,
|
|
3836
3942
|
filename: `${options.filename}.mreact-cloudflare-metadata.js`,
|
|
3837
3943
|
plugins: [cloudflareWorkspaceRuntimePlugin()],
|
|
3838
3944
|
resolveDir: dirname(options.filename),
|
|
@@ -3858,6 +3964,7 @@ export default defaultHandler;`;
|
|
|
3858
3964
|
|
|
3859
3965
|
async function bundleCloudflareModule(options: {
|
|
3860
3966
|
cacheDir?: string | undefined;
|
|
3967
|
+
define?: UserConfig["define"] | undefined;
|
|
3861
3968
|
entry: string;
|
|
3862
3969
|
filename: string;
|
|
3863
3970
|
plugins: RouterCompatPlugin[];
|
|
@@ -3868,6 +3975,7 @@ async function bundleCloudflareModule(options: {
|
|
|
3868
3975
|
const output = await bundleRouterModule({
|
|
3869
3976
|
cacheDir: options.cacheDir,
|
|
3870
3977
|
code: options.entry,
|
|
3978
|
+
define: options.define,
|
|
3871
3979
|
filename: options.filename,
|
|
3872
3980
|
minify: true,
|
|
3873
3981
|
platform: "node",
|
|
@@ -3888,6 +3996,7 @@ async function bundleCloudflareModule(options: {
|
|
|
3888
3996
|
|
|
3889
3997
|
async function bundleCloudflareVirtualModule(options: {
|
|
3890
3998
|
cacheDir?: string | undefined;
|
|
3999
|
+
define?: UserConfig["define"] | undefined;
|
|
3891
4000
|
entry: string;
|
|
3892
4001
|
filename: string;
|
|
3893
4002
|
modules: ReadonlyMap<string, string>;
|
|
@@ -3898,6 +4007,7 @@ async function bundleCloudflareVirtualModule(options: {
|
|
|
3898
4007
|
}): Promise<string> {
|
|
3899
4008
|
return bundleCloudflareModule({
|
|
3900
4009
|
cacheDir: options.cacheDir,
|
|
4010
|
+
define: options.define,
|
|
3901
4011
|
entry: options.entry,
|
|
3902
4012
|
filename: options.filename,
|
|
3903
4013
|
plugins: [
|
|
@@ -4047,6 +4157,7 @@ async function transformCloudflareServerSource(options: {
|
|
|
4047
4157
|
const output = transformCompilerModuleContext({
|
|
4048
4158
|
code: options.source,
|
|
4049
4159
|
clientBoundaryImports: clientInference.clientBoundaryImports,
|
|
4160
|
+
clientBoundaryFallbackImports: clientInference.clientBoundaryFallbackImports,
|
|
4050
4161
|
dev: false,
|
|
4051
4162
|
filename: options.filename,
|
|
4052
4163
|
moduleContext,
|
|
@@ -4060,7 +4171,9 @@ async function transformCloudflareServerSource(options: {
|
|
|
4060
4171
|
|
|
4061
4172
|
if (fatalDiagnostics.length > 0) {
|
|
4062
4173
|
throw new Error(
|
|
4063
|
-
fatalDiagnostics
|
|
4174
|
+
fatalDiagnostics
|
|
4175
|
+
.map((diagnostic) => formatDiagnostic(options.filename, diagnostic))
|
|
4176
|
+
.join("\n"),
|
|
4064
4177
|
);
|
|
4065
4178
|
}
|
|
4066
4179
|
|
|
@@ -4101,9 +4214,18 @@ function cloudflareWorkspaceRuntimePlugin(): RouterCompatPlugin {
|
|
|
4101
4214
|
"@reckona/mreact-compat/event-priority",
|
|
4102
4215
|
packageFile("react-compat", "@reckona/mreact-compat", "event-priority"),
|
|
4103
4216
|
],
|
|
4104
|
-
[
|
|
4105
|
-
|
|
4106
|
-
|
|
4217
|
+
[
|
|
4218
|
+
"@reckona/mreact-compat/flight",
|
|
4219
|
+
packageFile("react-compat", "@reckona/mreact-compat", "flight"),
|
|
4220
|
+
],
|
|
4221
|
+
[
|
|
4222
|
+
"@reckona/mreact-compat/hooks",
|
|
4223
|
+
packageFile("react-compat", "@reckona/mreact-compat", "hooks-entry"),
|
|
4224
|
+
],
|
|
4225
|
+
[
|
|
4226
|
+
"@reckona/mreact-compat/internal",
|
|
4227
|
+
packageFile("react-compat", "@reckona/mreact-compat", "internal"),
|
|
4228
|
+
],
|
|
4107
4229
|
[
|
|
4108
4230
|
"@reckona/mreact-compat/jsx-dev-runtime",
|
|
4109
4231
|
packageFile("react-compat", "@reckona/mreact-compat", "jsx-dev-runtime"),
|
|
@@ -4112,9 +4234,15 @@ function cloudflareWorkspaceRuntimePlugin(): RouterCompatPlugin {
|
|
|
4112
4234
|
"@reckona/mreact-compat/jsx-runtime",
|
|
4113
4235
|
packageFile("react-compat", "@reckona/mreact-compat", "jsx-runtime"),
|
|
4114
4236
|
],
|
|
4115
|
-
[
|
|
4237
|
+
[
|
|
4238
|
+
"@reckona/mreact-compat/scheduler",
|
|
4239
|
+
packageFile("react-compat", "@reckona/mreact-compat", "scheduler"),
|
|
4240
|
+
],
|
|
4116
4241
|
["@reckona/mreact-query", packageFile("query", "@reckona/mreact-query", "index")],
|
|
4117
|
-
[
|
|
4242
|
+
[
|
|
4243
|
+
"@reckona/mreact-reactive-core",
|
|
4244
|
+
packageFile("reactive-core", "@reckona/mreact-reactive-core", "index"),
|
|
4245
|
+
],
|
|
4118
4246
|
[
|
|
4119
4247
|
"@reckona/mreact-router/adapters/cloudflare",
|
|
4120
4248
|
packageFile("router", "@reckona/mreact-router", "adapters/cloudflare"),
|
|
@@ -4133,10 +4261,13 @@ function cloudflareWorkspaceRuntimePlugin(): RouterCompatPlugin {
|
|
|
4133
4261
|
return {
|
|
4134
4262
|
name: "mreact-cloudflare-workspace-runtime",
|
|
4135
4263
|
setup(buildApi) {
|
|
4136
|
-
buildApi.onResolve(
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
|
|
4264
|
+
buildApi.onResolve(
|
|
4265
|
+
{ filter: /^@reckona\/mreact-router\/(?:internal\/)?native-escape$/ },
|
|
4266
|
+
() => ({
|
|
4267
|
+
namespace: "mreact-cloudflare-native-escape",
|
|
4268
|
+
path: "native-escape",
|
|
4269
|
+
}),
|
|
4270
|
+
);
|
|
4140
4271
|
buildApi.onResolve({ filter: /^@reckona\/mreact-router$/ }, () => ({
|
|
4141
4272
|
namespace: "mreact-cloudflare-router-index",
|
|
4142
4273
|
path: "index",
|
|
@@ -4146,8 +4277,10 @@ function cloudflareWorkspaceRuntimePlugin(): RouterCompatPlugin {
|
|
|
4146
4277
|
|
|
4147
4278
|
return path === undefined ? undefined : { path };
|
|
4148
4279
|
});
|
|
4149
|
-
buildApi.onLoad(
|
|
4150
|
-
|
|
4280
|
+
buildApi.onLoad(
|
|
4281
|
+
{ filter: /^native-escape$/, namespace: "mreact-cloudflare-native-escape" },
|
|
4282
|
+
() => ({
|
|
4283
|
+
contents: `function escapeHtml(value) {
|
|
4151
4284
|
return String(value ?? "").replace(/[&<>"']/g, (char) =>
|
|
4152
4285
|
char === "&" ? "&" : char === "<" ? "<" : char === ">" ? ">" : char === '"' ? """ : "'"
|
|
4153
4286
|
);
|
|
@@ -4155,8 +4288,9 @@ function cloudflareWorkspaceRuntimePlugin(): RouterCompatPlugin {
|
|
|
4155
4288
|
export function escapeHtmlBatch(values) {
|
|
4156
4289
|
return values.map(escapeHtml);
|
|
4157
4290
|
}`,
|
|
4158
|
-
|
|
4159
|
-
|
|
4291
|
+
loader: "js",
|
|
4292
|
+
}),
|
|
4293
|
+
);
|
|
4160
4294
|
buildApi.onLoad({ filter: /^index$/, namespace: "mreact-cloudflare-router-index" }, () => ({
|
|
4161
4295
|
contents: `export { cacheControl, revalidatePath } from ${JSON.stringify(routerCachePath)};
|
|
4162
4296
|
export { deleteCookie, parseCookieHeader, serializeCookie, setCookie } from ${JSON.stringify(routerCookiesPath)};
|
|
@@ -4170,12 +4304,15 @@ export { getServerRuntimeState } from ${JSON.stringify(routerRuntimeStatePath)};
|
|
|
4170
4304
|
loader: "js",
|
|
4171
4305
|
resolveDir: dirname(routerNavigationPath),
|
|
4172
4306
|
}));
|
|
4173
|
-
buildApi.onLoad(
|
|
4174
|
-
|
|
4307
|
+
buildApi.onLoad(
|
|
4308
|
+
{ filter: /(?:^|[/\\])packages[/\\]server[/\\](?:src|dist)[/\\]native-flight\.[jt]s$/ },
|
|
4309
|
+
() => ({
|
|
4310
|
+
contents: `export function getNativeFlight() {
|
|
4175
4311
|
return undefined;
|
|
4176
4312
|
}`,
|
|
4177
|
-
|
|
4178
|
-
|
|
4313
|
+
loader: "js",
|
|
4314
|
+
}),
|
|
4315
|
+
);
|
|
4179
4316
|
},
|
|
4180
4317
|
};
|
|
4181
4318
|
}
|
|
@@ -4377,18 +4514,23 @@ async function writeClientRouteBundles(options: {
|
|
|
4377
4514
|
});
|
|
4378
4515
|
} catch (error) {
|
|
4379
4516
|
const routeContexts = clientEntries
|
|
4380
|
-
.map(
|
|
4517
|
+
.map(
|
|
4518
|
+
(entry) => `Failed to build client bundle for ${entry.route.path} (${entry.route.file}).`,
|
|
4519
|
+
)
|
|
4381
4520
|
.join("\n");
|
|
4382
4521
|
|
|
4383
|
-
throw new Error(
|
|
4384
|
-
|
|
4385
|
-
|
|
4522
|
+
throw new Error(
|
|
4523
|
+
`${routeContexts}\nFailed to build client route bundles.\n${errorMessage(error)}`,
|
|
4524
|
+
{
|
|
4525
|
+
cause: error,
|
|
4526
|
+
},
|
|
4527
|
+
);
|
|
4386
4528
|
}
|
|
4387
4529
|
|
|
4388
4530
|
const routeOutputs = new Map(output.routes.map((route) => [route.routePath, route]));
|
|
4389
4531
|
const mapAssets = new Map(
|
|
4390
4532
|
output.chunks.flatMap((chunk) =>
|
|
4391
|
-
chunk.map === undefined ? [] : [[`${chunk.fileName}.map`, chunk.map] as const]
|
|
4533
|
+
chunk.map === undefined ? [] : [[`${chunk.fileName}.map`, chunk.map] as const],
|
|
4392
4534
|
),
|
|
4393
4535
|
);
|
|
4394
4536
|
|
|
@@ -4413,9 +4555,7 @@ async function writeClientRouteBundles(options: {
|
|
|
4413
4555
|
|
|
4414
4556
|
for (const asset of output.assets ?? []) {
|
|
4415
4557
|
const source =
|
|
4416
|
-
typeof asset.source === "string"
|
|
4417
|
-
? asset.source
|
|
4418
|
-
: Buffer.from(asset.source).toString("utf8");
|
|
4558
|
+
typeof asset.source === "string" ? asset.source : Buffer.from(asset.source).toString("utf8");
|
|
4419
4559
|
|
|
4420
4560
|
await mkdir(dirname(join(options.clientDir, asset.fileName)), { recursive: true });
|
|
4421
4561
|
await writeFile(join(options.clientDir, asset.fileName), source);
|
|
@@ -4492,12 +4632,16 @@ async function writeRouteCssAssetBatches(options: {
|
|
|
4492
4632
|
appDir: options.appDir,
|
|
4493
4633
|
pageFile: route.file,
|
|
4494
4634
|
projectRoot: options.projectRoot,
|
|
4495
|
-
readSource: (file) =>
|
|
4635
|
+
readSource: (file) =>
|
|
4636
|
+
buildSourceAnalysisForFile(options.sourceAnalysis, options.projectRoot, file)?.source,
|
|
4496
4637
|
});
|
|
4497
4638
|
|
|
4498
4639
|
return { cssFiles, route };
|
|
4499
4640
|
});
|
|
4500
|
-
const groups = new Map<
|
|
4641
|
+
const groups = new Map<
|
|
4642
|
+
string,
|
|
4643
|
+
{ cssFiles: string[]; routeIds: string[]; routeFiles: string[] }
|
|
4644
|
+
>();
|
|
4501
4645
|
|
|
4502
4646
|
for (const { cssFiles, route } of cssInputs) {
|
|
4503
4647
|
if (cssFiles.length === 0) {
|
|
@@ -4511,18 +4655,22 @@ async function writeRouteCssAssetBatches(options: {
|
|
|
4511
4655
|
groups.set(key, group);
|
|
4512
4656
|
}
|
|
4513
4657
|
|
|
4514
|
-
const writtenGroups = await mapWithBuildConcurrency(
|
|
4515
|
-
|
|
4516
|
-
|
|
4517
|
-
|
|
4518
|
-
|
|
4519
|
-
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4524
|
-
|
|
4525
|
-
|
|
4658
|
+
const writtenGroups = await mapWithBuildConcurrency(
|
|
4659
|
+
[...groups.entries()],
|
|
4660
|
+
async ([key, group]) =>
|
|
4661
|
+
[
|
|
4662
|
+
key,
|
|
4663
|
+
await writeRouteCssAssetsForFiles({
|
|
4664
|
+
cacheDir: options.cacheDir,
|
|
4665
|
+
clientDir: options.clientDir,
|
|
4666
|
+
cssFiles: group.cssFiles,
|
|
4667
|
+
pageFile: group.routeFiles[0] ?? options.appDir,
|
|
4668
|
+
projectRoot: options.projectRoot,
|
|
4669
|
+
routeIds: group.routeIds,
|
|
4670
|
+
vitePlugins: options.vitePlugins,
|
|
4671
|
+
}),
|
|
4672
|
+
] as const,
|
|
4673
|
+
);
|
|
4526
4674
|
const cssByGroup = new Map(writtenGroups);
|
|
4527
4675
|
const cssByRoute = new Map<string, string[]>();
|
|
4528
4676
|
|
|
@@ -4566,15 +4714,14 @@ async function writeRouteCssAssetsForFiles(options: {
|
|
|
4566
4714
|
});
|
|
4567
4715
|
const cssAssets = (output.assets ?? []).filter((asset) => asset.fileName.endsWith(".css"));
|
|
4568
4716
|
const written: string[] = [];
|
|
4569
|
-
const routeStem =
|
|
4570
|
-
|
|
4571
|
-
|
|
4717
|
+
const routeStem =
|
|
4718
|
+
options.routeIds.length === 1
|
|
4719
|
+
? (options.routeIds[0] ?? "index")
|
|
4720
|
+
: `shared.${hashText(cssFiles.join("\0")).slice(0, 8)}`;
|
|
4572
4721
|
|
|
4573
4722
|
for (const [index, asset] of cssAssets.entries()) {
|
|
4574
4723
|
const source =
|
|
4575
|
-
typeof asset.source === "string"
|
|
4576
|
-
? asset.source
|
|
4577
|
-
: Buffer.from(asset.source).toString("utf8");
|
|
4724
|
+
typeof asset.source === "string" ? asset.source : Buffer.from(asset.source).toString("utf8");
|
|
4578
4725
|
const hash = createHash("sha256").update(source).digest("hex").slice(0, 8);
|
|
4579
4726
|
const cssFile = `assets/routes/${routeStem}${cssAssets.length === 1 ? "" : `.${index}`}.${hash}.css`;
|
|
4580
4727
|
|
|
@@ -4752,7 +4899,9 @@ function isBarePackageImport(specifier: string): boolean {
|
|
|
4752
4899
|
|
|
4753
4900
|
async function assertAwsLambdaRuntimeDependencies(outDir: string): Promise<void> {
|
|
4754
4901
|
try {
|
|
4755
|
-
const info = await stat(
|
|
4902
|
+
const info = await stat(
|
|
4903
|
+
join(outDir, "node_modules", "@reckona", "mreact-router", "package.json"),
|
|
4904
|
+
);
|
|
4756
4905
|
if (info.isFile()) {
|
|
4757
4906
|
return;
|
|
4758
4907
|
}
|
|
@@ -4845,7 +4994,9 @@ function assertPackageOutputDoesNotReplaceBuildOutput(options: {
|
|
|
4845
4994
|
outDir: string;
|
|
4846
4995
|
}): void {
|
|
4847
4996
|
if (resolve(options.fromDir) === resolve(options.outDir)) {
|
|
4848
|
-
throw new Error(
|
|
4997
|
+
throw new Error(
|
|
4998
|
+
"Package output directory must be different from the mreact build output directory.",
|
|
4999
|
+
);
|
|
4849
5000
|
}
|
|
4850
5001
|
}
|
|
4851
5002
|
|
|
@@ -4909,7 +5060,9 @@ async function collectArtifactFiles(
|
|
|
4909
5060
|
}
|
|
4910
5061
|
}
|
|
4911
5062
|
|
|
4912
|
-
return files.sort(
|
|
5063
|
+
return files.sort(
|
|
5064
|
+
(left, right) => right.bytes - left.bytes || left.path.localeCompare(right.path),
|
|
5065
|
+
);
|
|
4913
5066
|
}
|
|
4914
5067
|
|
|
4915
5068
|
function awsLambdaHandlerSource(outDirRelativeToHandler: string): string {
|
|
@@ -4954,6 +5107,7 @@ async function validateProductionRoutes(options: {
|
|
|
4954
5107
|
cache: options.serverTransformCache,
|
|
4955
5108
|
code: analysis.routeCode,
|
|
4956
5109
|
clientBoundaryImports: analysis.clientBoundaryImports,
|
|
5110
|
+
clientBoundaryFallbackImports: analysis.clientBoundaryFallbackImports,
|
|
4957
5111
|
filename: route.file,
|
|
4958
5112
|
moduleContextCache: options.clientRouteInferenceCache,
|
|
4959
5113
|
serverOutput: analysis.streamRoute ? "stream" : "string",
|
|
@@ -4993,10 +5147,10 @@ async function collectBuildFiles(
|
|
|
4993
5147
|
|
|
4994
5148
|
return [{ file, relativeFile }];
|
|
4995
5149
|
});
|
|
4996
|
-
const fileContents = await mapWithBuildConcurrency(
|
|
4997
|
-
|
|
4998
|
-
await readFile(file, "utf8"),
|
|
4999
|
-
|
|
5150
|
+
const fileContents = await mapWithBuildConcurrency(
|
|
5151
|
+
sourceFiles,
|
|
5152
|
+
async ({ file, relativeFile }) => [relativeFile, await readFile(file, "utf8")] as const,
|
|
5153
|
+
);
|
|
5000
5154
|
|
|
5001
5155
|
for (const [relativeFile, source] of fileContents) {
|
|
5002
5156
|
files[relativeFile] = source;
|