@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/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,
|
|
@@ -75,7 +73,7 @@ import {
|
|
|
75
73
|
type RouterBundleChunkOutput,
|
|
76
74
|
type RouterBundleOutput,
|
|
77
75
|
} from "./bundle-pipeline.js";
|
|
78
|
-
import { collectRouteCssFilesFromSources } from "./route-styles.js";
|
|
76
|
+
import { collectRouteCssFilesFromSources, collectSpecialBoundaryFiles } from "./route-styles.js";
|
|
79
77
|
import { existingRouteShellCandidates } from "./route-shells.js";
|
|
80
78
|
import { sourceModuleCandidates } from "./source-modules.js";
|
|
81
79
|
import { collectBuildInferredServerActions } from "./server-action-inference.js";
|
|
@@ -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" };
|
|
@@ -428,7 +428,11 @@ export async function buildApp(options: BuildAppOptions): Promise<BuildAppResult
|
|
|
428
428
|
}));
|
|
429
429
|
const [serverModuleArtifacts, clientBundle] = await Promise.all([
|
|
430
430
|
timingSink === undefined
|
|
431
|
-
? writeServerModuleArtifactFiles(
|
|
431
|
+
? writeServerModuleArtifactFiles(
|
|
432
|
+
serverDir,
|
|
433
|
+
serverModules,
|
|
434
|
+
generatedImportPolicy.runtimePackages,
|
|
435
|
+
)
|
|
432
436
|
: timeBuildPhase(timingSink, "serverModuleArtifacts", () =>
|
|
433
437
|
writeServerModuleArtifactFiles(
|
|
434
438
|
serverDir,
|
|
@@ -487,6 +491,7 @@ export async function buildApp(options: BuildAppOptions): Promise<BuildAppResult
|
|
|
487
491
|
const clientManifestAssets = Array.from(
|
|
488
492
|
new Set([
|
|
489
493
|
...clientBundle.assets,
|
|
494
|
+
...clientBundle.styles.flatMap((style) => style.css),
|
|
490
495
|
...(navigationRuntimeScript === undefined ? [] : [navigationRuntimeScript]),
|
|
491
496
|
]),
|
|
492
497
|
).sort();
|
|
@@ -584,6 +589,7 @@ export async function buildApp(options: BuildAppOptions): Promise<BuildAppResult
|
|
|
584
589
|
...(clientManifestAssets.length === 0 ? {} : { assets: clientManifestAssets }),
|
|
585
590
|
...(publicAssets.length === 0 ? {} : { publicAssets }),
|
|
586
591
|
routes: clientManifestRoutes,
|
|
592
|
+
...(clientBundle.styles.length === 0 ? {} : { styles: clientBundle.styles }),
|
|
587
593
|
};
|
|
588
594
|
const writeManifestFiles = async () => {
|
|
589
595
|
await Promise.all([
|
|
@@ -743,6 +749,7 @@ async function analyzeBuildRouteSources(options: {
|
|
|
743
749
|
{
|
|
744
750
|
...analyzeBuildSource(source, route.file),
|
|
745
751
|
clientBoundaryImports: clientInference.clientBoundaryImports,
|
|
752
|
+
clientBoundaryFallbackImports: clientInference.clientBoundaryFallbackImports,
|
|
746
753
|
clientRoute: clientInference.client,
|
|
747
754
|
file,
|
|
748
755
|
route,
|
|
@@ -1204,7 +1211,11 @@ async function collectRuntimeOptionalPackages(options: {
|
|
|
1204
1211
|
{ packageName: options.packageName, optional: false, startDir: options.projectRoot },
|
|
1205
1212
|
];
|
|
1206
1213
|
|
|
1207
|
-
for (
|
|
1214
|
+
for (
|
|
1215
|
+
let index = 0;
|
|
1216
|
+
index < queue.length && seenPackageJson.size < maxRuntimePackageManifestReads;
|
|
1217
|
+
index += 1
|
|
1218
|
+
) {
|
|
1208
1219
|
const item = queue[index];
|
|
1209
1220
|
if (item === undefined || !isValidRuntimePackageName(item.packageName)) {
|
|
1210
1221
|
continue;
|
|
@@ -1300,7 +1311,11 @@ async function findRuntimePackageJson(
|
|
|
1300
1311
|
}
|
|
1301
1312
|
|
|
1302
1313
|
function isRuntimePackageSpecifier(specifier: string): boolean {
|
|
1303
|
-
if (
|
|
1314
|
+
if (
|
|
1315
|
+
specifier.startsWith(".") ||
|
|
1316
|
+
specifier.startsWith("/") ||
|
|
1317
|
+
/^[A-Za-z][A-Za-z0-9+.-]*:/.test(specifier)
|
|
1318
|
+
) {
|
|
1304
1319
|
return false;
|
|
1305
1320
|
}
|
|
1306
1321
|
|
|
@@ -1428,7 +1443,11 @@ function isSourceModuleFile(file: string): boolean {
|
|
|
1428
1443
|
}
|
|
1429
1444
|
|
|
1430
1445
|
function isAppRelativeFile(file: string, relativeRoutesDir: string): boolean {
|
|
1431
|
-
return
|
|
1446
|
+
return (
|
|
1447
|
+
relativeRoutesDir === "" ||
|
|
1448
|
+
file === relativeRoutesDir ||
|
|
1449
|
+
file.startsWith(`${relativeRoutesDir}/`)
|
|
1450
|
+
);
|
|
1432
1451
|
}
|
|
1433
1452
|
|
|
1434
1453
|
function moduleIdForBuildFile(file: string, relativeRoutesDir: string): string {
|
|
@@ -1468,10 +1487,7 @@ async function collectPublicAssetPaths(publicDir: string): Promise<string[]> {
|
|
|
1468
1487
|
return paths.sort();
|
|
1469
1488
|
}
|
|
1470
1489
|
|
|
1471
|
-
async function copyAppFileConventionAssets(
|
|
1472
|
-
appDir: string,
|
|
1473
|
-
outDir: string,
|
|
1474
|
-
): Promise<string[]> {
|
|
1490
|
+
async function copyAppFileConventionAssets(appDir: string, outDir: string): Promise<string[]> {
|
|
1475
1491
|
let entries: Dirent[];
|
|
1476
1492
|
try {
|
|
1477
1493
|
entries = await readdir(appDir, { withFileTypes: true });
|
|
@@ -1496,9 +1512,7 @@ async function copyAppFileConventionAssets(
|
|
|
1496
1512
|
continue;
|
|
1497
1513
|
}
|
|
1498
1514
|
|
|
1499
|
-
const outputPath = convention.path.startsWith("/")
|
|
1500
|
-
? convention.path.slice(1)
|
|
1501
|
-
: convention.path;
|
|
1515
|
+
const outputPath = convention.path.startsWith("/") ? convention.path.slice(1) : convention.path;
|
|
1502
1516
|
await copyFile(join(appDir, entry.name), join(outDir, outputPath));
|
|
1503
1517
|
paths.push(convention.path);
|
|
1504
1518
|
}
|
|
@@ -1748,205 +1762,219 @@ async function buildServerModuleArtifacts(options: {
|
|
|
1748
1762
|
}
|
|
1749
1763
|
}
|
|
1750
1764
|
|
|
1751
|
-
const requestBatchOutputs =
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
const artifactEntries = await mapWithBuildConcurrency(Object.entries(options.files), async ([file, source]) => {
|
|
1763
|
-
const absoluteFile = join(options.projectRoot, file);
|
|
1764
|
-
const route = routeByFile.get(file);
|
|
1765
|
-
const routeAnalysis = options.sourceAnalysis.byRouteFile.get(file);
|
|
1766
|
-
const artifact: BuiltServerModuleArtifact = {};
|
|
1765
|
+
const requestBatchOutputs =
|
|
1766
|
+
requestBatchEntries.length >= 3
|
|
1767
|
+
? await bundleRouteRequestModuleBatchCode({
|
|
1768
|
+
appDir: options.project.routesDir,
|
|
1769
|
+
bundleCache: options.bundleCache,
|
|
1770
|
+
cacheDir: options.cacheDir,
|
|
1771
|
+
entries: requestBatchEntries,
|
|
1772
|
+
importPolicy: requestModuleImportPolicy,
|
|
1773
|
+
vitePlugins: options.vitePlugins,
|
|
1774
|
+
})
|
|
1775
|
+
: new Map<string, string>();
|
|
1767
1776
|
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
await bundleRouteLoaderModuleCode({
|
|
1776
|
-
appDir: options.project.routesDir,
|
|
1777
|
-
bundleCache: options.bundleCache,
|
|
1778
|
-
cacheDir: options.cacheDir,
|
|
1779
|
-
code: stripRouteLoaderOnlyExports(source, absoluteFile),
|
|
1780
|
-
filename: absoluteFile,
|
|
1781
|
-
importPolicy: requestModuleImportPolicy,
|
|
1782
|
-
vitePlugins: options.vitePlugins,
|
|
1783
|
-
});
|
|
1784
|
-
artifact.loader = {
|
|
1785
|
-
code,
|
|
1786
|
-
sourceHash: hashText(source),
|
|
1787
|
-
};
|
|
1788
|
-
}
|
|
1777
|
+
const artifactEntries = await mapWithBuildConcurrency(
|
|
1778
|
+
Object.entries(options.files),
|
|
1779
|
+
async ([file, source]) => {
|
|
1780
|
+
const absoluteFile = join(options.projectRoot, file);
|
|
1781
|
+
const route = routeByFile.get(file);
|
|
1782
|
+
const routeAnalysis = options.sourceAnalysis.byRouteFile.get(file);
|
|
1783
|
+
const artifact: BuiltServerModuleArtifact = {};
|
|
1789
1784
|
|
|
1790
|
-
if (
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1785
|
+
if (
|
|
1786
|
+
requestArtifactFiles.has(file) ||
|
|
1787
|
+
loaderArtifactFiles.has(file) ||
|
|
1788
|
+
metadataArtifactFiles.has(file)
|
|
1789
|
+
) {
|
|
1790
|
+
if (loaderArtifactFiles.has(file)) {
|
|
1791
|
+
const code =
|
|
1792
|
+
requestBatchOutputs.get(routeRequestArtifactBatchKey(file, "loader")) ??
|
|
1793
|
+
(await bundleRouteLoaderModuleCode({
|
|
1794
|
+
appDir: options.project.routesDir,
|
|
1795
|
+
bundleCache: options.bundleCache,
|
|
1796
|
+
cacheDir: options.cacheDir,
|
|
1797
|
+
code: stripRouteLoaderOnlyExports(source, absoluteFile),
|
|
1798
|
+
filename: absoluteFile,
|
|
1799
|
+
importPolicy: requestModuleImportPolicy,
|
|
1800
|
+
vitePlugins: options.vitePlugins,
|
|
1801
|
+
}));
|
|
1802
|
+
artifact.loader = {
|
|
1803
|
+
code,
|
|
1804
|
+
sourceHash: hashText(source),
|
|
1805
|
+
};
|
|
1806
|
+
}
|
|
1807
1807
|
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
artifact.request = {
|
|
1813
|
-
code: batchedRequestCode ??
|
|
1814
|
-
await buildRequestModuleArtifactCode({
|
|
1808
|
+
if (metadataArtifactFiles.has(file)) {
|
|
1809
|
+
const code =
|
|
1810
|
+
requestBatchOutputs.get(routeRequestArtifactBatchKey(file, "metadata")) ??
|
|
1811
|
+
(await bundleRouteRequestModuleCode({
|
|
1815
1812
|
appDir: options.project.routesDir,
|
|
1816
1813
|
bundleCache: options.bundleCache,
|
|
1817
1814
|
cacheDir: options.cacheDir,
|
|
1815
|
+
code: stripRouteMetadataOnlyExports(source, absoluteFile),
|
|
1818
1816
|
filename: absoluteFile,
|
|
1819
1817
|
importPolicy: requestModuleImportPolicy,
|
|
1820
|
-
|
|
1821
|
-
source,
|
|
1818
|
+
label: "Metadata",
|
|
1822
1819
|
vitePlugins: options.vitePlugins,
|
|
1823
|
-
})
|
|
1824
|
-
|
|
1825
|
-
|
|
1820
|
+
}));
|
|
1821
|
+
artifact.routeMetadata = {
|
|
1822
|
+
code,
|
|
1823
|
+
sourceHash: hashText(source),
|
|
1824
|
+
};
|
|
1825
|
+
}
|
|
1826
|
+
|
|
1827
|
+
if (requestArtifactFiles.has(file)) {
|
|
1828
|
+
const batchedRequestCode = requestBatchOutputs.get(
|
|
1829
|
+
routeRequestArtifactBatchKey(file, "request"),
|
|
1830
|
+
);
|
|
1831
|
+
artifact.request = {
|
|
1832
|
+
code:
|
|
1833
|
+
batchedRequestCode ??
|
|
1834
|
+
(await buildRequestModuleArtifactCode({
|
|
1835
|
+
appDir: options.project.routesDir,
|
|
1836
|
+
bundleCache: options.bundleCache,
|
|
1837
|
+
cacheDir: options.cacheDir,
|
|
1838
|
+
filename: absoluteFile,
|
|
1839
|
+
importPolicy: requestModuleImportPolicy,
|
|
1840
|
+
routeKind: route?.kind,
|
|
1841
|
+
source,
|
|
1842
|
+
vitePlugins: options.vitePlugins,
|
|
1843
|
+
})),
|
|
1844
|
+
sourceHash: hashText(source),
|
|
1845
|
+
};
|
|
1846
|
+
}
|
|
1826
1847
|
}
|
|
1827
|
-
}
|
|
1828
1848
|
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1849
|
+
if (!isServerComponentFile(file)) {
|
|
1850
|
+
return Object.keys(artifact).length > 0 ? ([file, artifact] as const) : undefined;
|
|
1851
|
+
}
|
|
1832
1852
|
|
|
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
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1853
|
+
const closureUsesAwait =
|
|
1854
|
+
routeAnalysis?.streamRoute ??
|
|
1855
|
+
shouldBuildRouteAsStream({
|
|
1856
|
+
filename: file,
|
|
1857
|
+
files: options.files,
|
|
1858
|
+
projectRoot: options.projectRoot,
|
|
1859
|
+
source,
|
|
1860
|
+
});
|
|
1861
|
+
const streamRoute = route !== undefined && closureUsesAwait;
|
|
1862
|
+
const serverOutputs =
|
|
1863
|
+
streamRoute || (route === undefined && closureUsesAwait)
|
|
1864
|
+
? (["stream", "string"] as const)
|
|
1865
|
+
: (["string"] as const);
|
|
1866
|
+
const code =
|
|
1867
|
+
routeAnalysis?.routeCode ??
|
|
1868
|
+
(route === undefined ? source : stripRouteBuildExports(source, absoluteFile));
|
|
1869
|
+
const clientInference =
|
|
1870
|
+
routeAnalysis === undefined
|
|
1871
|
+
? await inferClientRouteModule({
|
|
1872
|
+
...(route === undefined ? {} : { appDir: options.project.routesDir }),
|
|
1873
|
+
cache: options.clientRouteInferenceCache,
|
|
1874
|
+
code:
|
|
1875
|
+
route === undefined
|
|
1876
|
+
? stripRouteClientOnlyExports(source, absoluteFile)
|
|
1877
|
+
: stripRouteClientSource({ code: source, filename: route.file }),
|
|
1878
|
+
filename: join(options.projectRoot, file),
|
|
1879
|
+
...(route === undefined ? {} : { routePath: route.path }),
|
|
1880
|
+
vitePlugins: options.vitePlugins,
|
|
1881
|
+
})
|
|
1882
|
+
: undefined;
|
|
1883
|
+
const clientBoundaryImports =
|
|
1884
|
+
routeAnalysis?.clientBoundaryImports ?? clientInference?.clientBoundaryImports ?? [];
|
|
1885
|
+
const clientBoundaryFallbackImports =
|
|
1886
|
+
routeAnalysis?.clientBoundaryFallbackImports ??
|
|
1887
|
+
clientInference?.clientBoundaryFallbackImports ??
|
|
1888
|
+
[];
|
|
1889
|
+
|
|
1890
|
+
for (const diagnostic of clientInference?.diagnostics ?? []) {
|
|
1891
|
+
console.warn(formatClientRouteInferenceDiagnostic(diagnostic));
|
|
1892
|
+
}
|
|
1863
1893
|
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1894
|
+
if (routeAnalysis !== undefined) {
|
|
1895
|
+
artifact.analysis = builtRouteSourceAnalysisSummary({
|
|
1896
|
+
analysis: routeAnalysis,
|
|
1897
|
+
});
|
|
1898
|
+
}
|
|
1867
1899
|
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1900
|
+
const serverOutputArtifacts = await mapWithBuildConcurrency(
|
|
1901
|
+
serverOutputs,
|
|
1902
|
+
async (serverOutput) => {
|
|
1903
|
+
const output = await transformServerRouteSource({
|
|
1904
|
+
cache: options.serverTransformCache,
|
|
1905
|
+
code,
|
|
1906
|
+
clientBoundaryImports,
|
|
1907
|
+
clientBoundaryFallbackImports,
|
|
1908
|
+
filename: join(options.projectRoot, file),
|
|
1909
|
+
moduleContextCache: options.clientRouteInferenceCache,
|
|
1910
|
+
serverOutput,
|
|
1911
|
+
});
|
|
1912
|
+
const fatalDiagnostics = output.diagnostics.filter(
|
|
1913
|
+
(diagnostic) => diagnostic.code !== "MR_UNSUPPORTED_SERVER_EVENT_HANDLER",
|
|
1914
|
+
);
|
|
1873
1915
|
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1916
|
+
if (fatalDiagnostics.length > 0) {
|
|
1917
|
+
if (
|
|
1918
|
+
serverOutput === "string" &&
|
|
1919
|
+
streamRoute &&
|
|
1920
|
+
route?.kind === "page" &&
|
|
1921
|
+
fatalDiagnostics.every(
|
|
1922
|
+
(diagnostic) => diagnostic.code === "MR_UNSUPPORTED_AWAIT_INNER_COMPONENT",
|
|
1923
|
+
)
|
|
1924
|
+
) {
|
|
1925
|
+
return undefined;
|
|
1926
|
+
}
|
|
1927
|
+
|
|
1928
|
+
throw new Error(
|
|
1929
|
+
fatalDiagnostics.map((diagnostic) => formatDiagnostic(file, diagnostic)).join("\n"),
|
|
1930
|
+
);
|
|
1931
|
+
}
|
|
1888
1932
|
|
|
1889
|
-
if (fatalDiagnostics.length > 0) {
|
|
1890
1933
|
if (
|
|
1891
1934
|
serverOutput === "string" &&
|
|
1892
1935
|
streamRoute &&
|
|
1893
1936
|
route?.kind === "page" &&
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
)
|
|
1937
|
+
source.includes("<Await") &&
|
|
1938
|
+
/\bLink\b/.test(source)
|
|
1897
1939
|
) {
|
|
1940
|
+
// Native Link renders pre-rendered children as HTML. Keep direct
|
|
1941
|
+
// Await renderers on the stream artifact so the string artifact
|
|
1942
|
+
// cannot drop deferred Link content before the boundary resolves.
|
|
1898
1943
|
return undefined;
|
|
1899
1944
|
}
|
|
1900
1945
|
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1946
|
+
return [
|
|
1947
|
+
serverOutput,
|
|
1948
|
+
{
|
|
1949
|
+
...(options.prebundleServerComponents
|
|
1950
|
+
? {
|
|
1951
|
+
bundleCode: await buildServerComponentBundleArtifactCode({
|
|
1952
|
+
clientRouteInferenceCache: options.clientRouteInferenceCache,
|
|
1953
|
+
code: output.code,
|
|
1954
|
+
filename: absoluteFile,
|
|
1955
|
+
root: options.projectRoot,
|
|
1956
|
+
serverOutput,
|
|
1957
|
+
vitePlugins: options.vitePlugins,
|
|
1958
|
+
}),
|
|
1959
|
+
}
|
|
1960
|
+
: {}),
|
|
1961
|
+
code: output.code,
|
|
1962
|
+
metadata: output.metadata,
|
|
1963
|
+
sourceHash: hashText(code),
|
|
1964
|
+
},
|
|
1965
|
+
] as const;
|
|
1966
|
+
},
|
|
1967
|
+
);
|
|
1905
1968
|
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
route?.kind === "page" &&
|
|
1910
|
-
source.includes("<Await") &&
|
|
1911
|
-
/\bLink\b/.test(source)
|
|
1912
|
-
) {
|
|
1913
|
-
// Native Link renders pre-rendered children as HTML. Keep direct
|
|
1914
|
-
// Await renderers on the stream artifact so the string artifact
|
|
1915
|
-
// cannot drop deferred Link content before the boundary resolves.
|
|
1916
|
-
return undefined;
|
|
1969
|
+
for (const entry of serverOutputArtifacts) {
|
|
1970
|
+
if (entry !== undefined) {
|
|
1971
|
+
artifact[entry[0]] = entry[1];
|
|
1917
1972
|
}
|
|
1918
|
-
|
|
1919
|
-
return [
|
|
1920
|
-
serverOutput,
|
|
1921
|
-
{
|
|
1922
|
-
...(options.prebundleServerComponents
|
|
1923
|
-
? {
|
|
1924
|
-
bundleCode: await buildServerComponentBundleArtifactCode({
|
|
1925
|
-
clientRouteInferenceCache: options.clientRouteInferenceCache,
|
|
1926
|
-
code: output.code,
|
|
1927
|
-
filename: absoluteFile,
|
|
1928
|
-
root: options.projectRoot,
|
|
1929
|
-
serverOutput,
|
|
1930
|
-
vitePlugins: options.vitePlugins,
|
|
1931
|
-
}),
|
|
1932
|
-
}
|
|
1933
|
-
: {}),
|
|
1934
|
-
code: output.code,
|
|
1935
|
-
metadata: output.metadata,
|
|
1936
|
-
sourceHash: hashText(code),
|
|
1937
|
-
},
|
|
1938
|
-
] as const;
|
|
1939
|
-
},
|
|
1940
|
-
);
|
|
1941
|
-
|
|
1942
|
-
for (const entry of serverOutputArtifacts) {
|
|
1943
|
-
if (entry !== undefined) {
|
|
1944
|
-
artifact[entry[0]] = entry[1];
|
|
1945
1973
|
}
|
|
1946
|
-
}
|
|
1947
1974
|
|
|
1948
|
-
|
|
1949
|
-
|
|
1975
|
+
return [file, artifact] as const;
|
|
1976
|
+
},
|
|
1977
|
+
);
|
|
1950
1978
|
|
|
1951
1979
|
for (const entry of artifactEntries) {
|
|
1952
1980
|
if (entry !== undefined) {
|
|
@@ -1984,6 +2012,7 @@ async function buildServerComponentBundleArtifactCode(options: {
|
|
|
1984
2012
|
async function transformServerRouteSource(options: {
|
|
1985
2013
|
cache: ServerTransformCache;
|
|
1986
2014
|
clientBoundaryImports: readonly string[];
|
|
2015
|
+
clientBoundaryFallbackImports?: readonly string[];
|
|
1987
2016
|
code: string;
|
|
1988
2017
|
filename: string;
|
|
1989
2018
|
moduleContextCache: ClientRouteInferenceCache;
|
|
@@ -1991,6 +2020,7 @@ async function transformServerRouteSource(options: {
|
|
|
1991
2020
|
}): Promise<ServerTransformOutput> {
|
|
1992
2021
|
const cacheKey = stableCacheKey({
|
|
1993
2022
|
clientBoundaryImports: options.clientBoundaryImports,
|
|
2023
|
+
clientBoundaryFallbackImports: options.clientBoundaryFallbackImports ?? [],
|
|
1994
2024
|
codeHash: hashText(options.code),
|
|
1995
2025
|
filename: resolve(options.filename),
|
|
1996
2026
|
serverOutput: options.serverOutput,
|
|
@@ -2012,6 +2042,7 @@ async function transformServerRouteSource(options: {
|
|
|
2012
2042
|
return transformCompilerModuleContext({
|
|
2013
2043
|
code: options.code,
|
|
2014
2044
|
clientBoundaryImports: options.clientBoundaryImports,
|
|
2045
|
+
clientBoundaryFallbackImports: options.clientBoundaryFallbackImports ?? [],
|
|
2015
2046
|
dev: false,
|
|
2016
2047
|
filename: options.filename,
|
|
2017
2048
|
moduleContext,
|
|
@@ -2029,8 +2060,11 @@ function builtRouteSourceAnalysisSummary(options: {
|
|
|
2029
2060
|
}): BuiltRouteSourceAnalysisSummary {
|
|
2030
2061
|
return {
|
|
2031
2062
|
authIncludesClaims: options.analysis.authIncludesClaims,
|
|
2032
|
-
...(options.analysis.cachePolicy === undefined
|
|
2063
|
+
...(options.analysis.cachePolicy === undefined
|
|
2064
|
+
? {}
|
|
2065
|
+
: { cachePolicy: options.analysis.cachePolicy }),
|
|
2033
2066
|
clientBoundaryImports: options.analysis.clientBoundaryImports,
|
|
2067
|
+
clientBoundaryFallbackImports: options.analysis.clientBoundaryFallbackImports,
|
|
2034
2068
|
clientRoute: options.analysis.clientRoute,
|
|
2035
2069
|
hasLoader: options.analysis.hasLoader,
|
|
2036
2070
|
routeCode: options.analysis.routeCode,
|
|
@@ -2089,7 +2123,10 @@ function usesRuntimeCacheControl(code: string): boolean {
|
|
|
2089
2123
|
return /\bcacheControl\s*\(/.test(code);
|
|
2090
2124
|
}
|
|
2091
2125
|
|
|
2092
|
-
function routeRequestArtifactBatchKey(
|
|
2126
|
+
function routeRequestArtifactBatchKey(
|
|
2127
|
+
file: string,
|
|
2128
|
+
kind: "loader" | "metadata" | "request",
|
|
2129
|
+
): string {
|
|
2093
2130
|
return `${kind}:${file}`;
|
|
2094
2131
|
}
|
|
2095
2132
|
|
|
@@ -2129,15 +2166,15 @@ async function buildRequestModuleArtifactCode(options: {
|
|
|
2129
2166
|
});
|
|
2130
2167
|
}
|
|
2131
2168
|
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2169
|
+
return await bundleRouteLoaderModuleCode({
|
|
2170
|
+
appDir: options.appDir,
|
|
2171
|
+
bundleCache: options.bundleCache,
|
|
2172
|
+
cacheDir: options.cacheDir,
|
|
2173
|
+
code: stripRouteRequestOnlyExports(options.source, options.filename),
|
|
2174
|
+
filename: options.filename,
|
|
2175
|
+
importPolicy: options.importPolicy,
|
|
2176
|
+
vitePlugins: options.vitePlugins,
|
|
2177
|
+
});
|
|
2141
2178
|
}
|
|
2142
2179
|
|
|
2143
2180
|
async function bundleRouteLoaderModuleCode(options: {
|
|
@@ -2214,24 +2251,29 @@ async function bundleRouteRequestModuleBatchCode(options: {
|
|
|
2214
2251
|
label: "Request artifact",
|
|
2215
2252
|
}),
|
|
2216
2253
|
],
|
|
2217
|
-
root:
|
|
2254
|
+
root:
|
|
2255
|
+
options.importPolicy?.projectRoot ?? dirname(options.entries[0]?.filename ?? options.appDir),
|
|
2218
2256
|
vitePlugins: options.vitePlugins,
|
|
2219
2257
|
});
|
|
2220
2258
|
|
|
2221
2259
|
if (output.chunks.some((chunk) => !chunk.isEntry)) {
|
|
2222
|
-
const fallbackEntries = await mapWithBuildConcurrency(
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2260
|
+
const fallbackEntries = await mapWithBuildConcurrency(
|
|
2261
|
+
options.entries,
|
|
2262
|
+
async (entry) =>
|
|
2263
|
+
[
|
|
2264
|
+
entry.key,
|
|
2265
|
+
await bundleRouteRequestModuleCode({
|
|
2266
|
+
appDir: options.appDir,
|
|
2267
|
+
bundleCache: options.bundleCache,
|
|
2268
|
+
cacheDir: options.cacheDir,
|
|
2269
|
+
code: entry.code,
|
|
2270
|
+
filename: entry.filename,
|
|
2271
|
+
importPolicy: options.importPolicy,
|
|
2272
|
+
label: entry.label,
|
|
2273
|
+
vitePlugins: options.vitePlugins,
|
|
2274
|
+
}),
|
|
2275
|
+
] as const,
|
|
2276
|
+
);
|
|
2235
2277
|
return new Map(fallbackEntries);
|
|
2236
2278
|
}
|
|
2237
2279
|
|
|
@@ -2346,9 +2388,11 @@ function isMiddlewareFile(appDir: string, file: string): boolean {
|
|
|
2346
2388
|
}
|
|
2347
2389
|
|
|
2348
2390
|
function hasMetadataExport(code: string): boolean {
|
|
2349
|
-
return
|
|
2391
|
+
return (
|
|
2392
|
+
/\bexport\s+const\s+metadata\s*=/.test(code) ||
|
|
2350
2393
|
/\bexport\s+(?:async\s+)?function\s+generateMetadata\b/.test(code) ||
|
|
2351
|
-
/\bexport\s*\{[^}]*\bgenerateMetadata\b[^}]*\}/.test(code)
|
|
2394
|
+
/\bexport\s*\{[^}]*\bgenerateMetadata\b[^}]*\}/.test(code)
|
|
2395
|
+
);
|
|
2352
2396
|
}
|
|
2353
2397
|
|
|
2354
2398
|
async function readDeclaredProjectPackages(projectRoot: string): Promise<string[]> {
|
|
@@ -2432,11 +2476,13 @@ async function writeCloudflareRouteModules(options: {
|
|
|
2432
2476
|
|
|
2433
2477
|
return analysis === undefined
|
|
2434
2478
|
? []
|
|
2435
|
-
: [
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2479
|
+
: [
|
|
2480
|
+
{
|
|
2481
|
+
route,
|
|
2482
|
+
routeFile,
|
|
2483
|
+
routeId: routeIdForPath(route.path),
|
|
2484
|
+
},
|
|
2485
|
+
];
|
|
2440
2486
|
}),
|
|
2441
2487
|
);
|
|
2442
2488
|
|
|
@@ -2455,8 +2501,10 @@ async function writeCloudflareRouteModules(options: {
|
|
|
2455
2501
|
cacheDir: options.cacheDir,
|
|
2456
2502
|
define: options.define,
|
|
2457
2503
|
routes: requiredRoutes
|
|
2458
|
-
.filter(
|
|
2459
|
-
route
|
|
2504
|
+
.filter(
|
|
2505
|
+
({ route, routeFile }) =>
|
|
2506
|
+
route.kind === "page" &&
|
|
2507
|
+
options.sourceAnalysis.byRouteFile.get(routeFile)?.hasLoader === true,
|
|
2460
2508
|
)
|
|
2461
2509
|
.map(({ route, routeId }) => ({ filename: route.file, routeId })),
|
|
2462
2510
|
root: options.projectRoot,
|
|
@@ -2504,114 +2552,120 @@ async function writeCloudflareRouteModules(options: {
|
|
|
2504
2552
|
writeCloudflareBatchedRouteModuleChunks(options.cloudflareDir, stringShellComponentModules),
|
|
2505
2553
|
]);
|
|
2506
2554
|
|
|
2507
|
-
const registryEntries = await mapWithBuildConcurrency(
|
|
2508
|
-
|
|
2509
|
-
|
|
2555
|
+
const registryEntries = await mapWithBuildConcurrency(
|
|
2556
|
+
requiredRoutes,
|
|
2557
|
+
async ({ route, routeFile, routeId }) => {
|
|
2558
|
+
const routeModuleFile = `routes/${routeId}.mjs`;
|
|
2559
|
+
let routeModuleExports: string[];
|
|
2510
2560
|
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2561
|
+
if (route.kind === "server" || route.kind === "metadata") {
|
|
2562
|
+
try {
|
|
2563
|
+
const serverRouteModule = serverRouteModules.entries.get(routeId);
|
|
2564
|
+
|
|
2565
|
+
if (serverRouteModule === undefined) {
|
|
2566
|
+
throw new Error(`Missing bundled Cloudflare ${route.kind} route module.`);
|
|
2567
|
+
}
|
|
2514
2568
|
|
|
2515
|
-
|
|
2516
|
-
|
|
2569
|
+
const serverRouteFile = serverRouteModule.fileName;
|
|
2570
|
+
const serverRouteImport = `./${serverRouteFile.split("/").pop() ?? serverRouteFile}`;
|
|
2571
|
+
routeModuleExports = [
|
|
2572
|
+
`export * from ${JSON.stringify(serverRouteImport)};`,
|
|
2573
|
+
...(route.kind === "metadata"
|
|
2574
|
+
? [`export { default } from ${JSON.stringify(serverRouteImport)};`]
|
|
2575
|
+
: []),
|
|
2576
|
+
];
|
|
2577
|
+
} catch (error) {
|
|
2578
|
+
throw new Error(
|
|
2579
|
+
`Failed to build Cloudflare ${route.kind} route module for ${routeFile}: ${errorMessage(error)}`,
|
|
2580
|
+
);
|
|
2517
2581
|
}
|
|
2518
2582
|
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
`export * from ${JSON.stringify(serverRouteImport)};`,
|
|
2523
|
-
...(route.kind === "metadata"
|
|
2524
|
-
? [`export { default } from ${JSON.stringify(serverRouteImport)};`]
|
|
2525
|
-
: []),
|
|
2526
|
-
];
|
|
2527
|
-
} catch (error) {
|
|
2528
|
-
throw new Error(
|
|
2529
|
-
`Failed to build Cloudflare ${route.kind} route module for ${routeFile}: ${errorMessage(error)}`,
|
|
2583
|
+
await writeFile(
|
|
2584
|
+
join(options.cloudflareDir, routeModuleFile),
|
|
2585
|
+
`${routeModuleExports.join("\n")}\n`,
|
|
2530
2586
|
);
|
|
2587
|
+
return `${JSON.stringify(routeFile)}: () => import(${JSON.stringify(`./${routeModuleFile}`)})`;
|
|
2531
2588
|
}
|
|
2532
2589
|
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
options.serverModules[routeFile]?.analysis?.streamRoute === true ||
|
|
2539
|
-
options.sourceAnalysis.byRouteFile.get(routeFile)?.streamRoute === true
|
|
2540
|
-
? "stream"
|
|
2541
|
-
: "string";
|
|
2590
|
+
const serverOutput =
|
|
2591
|
+
options.serverModules[routeFile]?.analysis?.streamRoute === true ||
|
|
2592
|
+
options.sourceAnalysis.byRouteFile.get(routeFile)?.streamRoute === true
|
|
2593
|
+
? "stream"
|
|
2594
|
+
: "string";
|
|
2542
2595
|
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
stringShellComponentRouteIds.has(routeId)
|
|
2596
|
+
try {
|
|
2597
|
+
const batchedComponent = stringShellComponentRouteIds.has(routeId)
|
|
2546
2598
|
? stringShellComponentModules.entries.get(routeId)
|
|
2547
2599
|
: directComponentRouteIds.has(routeId)
|
|
2548
2600
|
? directComponentModules.entries.get(routeId)
|
|
2549
2601
|
: undefined;
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2602
|
+
let componentFile = batchedComponent?.fileName;
|
|
2603
|
+
|
|
2604
|
+
if (batchedComponent === undefined) {
|
|
2605
|
+
const componentOutput =
|
|
2606
|
+
serverOutput === "stream"
|
|
2607
|
+
? await buildCloudflareStreamRouteComponentModule({
|
|
2608
|
+
cacheDir: options.cacheDir,
|
|
2609
|
+
define: options.define,
|
|
2610
|
+
filename: route.file,
|
|
2611
|
+
projectRoot: options.projectRoot,
|
|
2612
|
+
routesDir: options.routesDir,
|
|
2613
|
+
serverModules: options.serverModules,
|
|
2614
|
+
sourceAnalysis: options.sourceAnalysis,
|
|
2615
|
+
vitePlugins: options.vitePlugins,
|
|
2616
|
+
})
|
|
2617
|
+
: await buildCloudflareStringRouteComponentModule({
|
|
2618
|
+
cacheDir: options.cacheDir,
|
|
2619
|
+
define: options.define,
|
|
2620
|
+
filename: route.file,
|
|
2621
|
+
projectRoot: options.projectRoot,
|
|
2622
|
+
routesDir: options.routesDir,
|
|
2623
|
+
serverModules: options.serverModules,
|
|
2624
|
+
sourceAnalysis: options.sourceAnalysis,
|
|
2625
|
+
vitePlugins: options.vitePlugins,
|
|
2626
|
+
});
|
|
2627
|
+
|
|
2628
|
+
componentFile = `routes/${routeId}.${hashText(componentOutput).slice(0, 8)}.component.mjs`;
|
|
2629
|
+
await writeFile(join(options.cloudflareDir, componentFile), componentOutput);
|
|
2630
|
+
}
|
|
2575
2631
|
|
|
2576
|
-
componentFile
|
|
2577
|
-
|
|
2578
|
-
|
|
2632
|
+
if (componentFile === undefined) {
|
|
2633
|
+
throw new Error("Missing bundled Cloudflare component module.");
|
|
2634
|
+
}
|
|
2579
2635
|
|
|
2580
|
-
|
|
2581
|
-
|
|
2636
|
+
const componentImport = `./${componentFile.split("/").pop() ?? componentFile}`;
|
|
2637
|
+
routeModuleExports = [cloudflarePageRouteFacadeModuleSource(componentImport)];
|
|
2638
|
+
} catch (error) {
|
|
2639
|
+
throw new Error(
|
|
2640
|
+
`Failed to build Cloudflare route module for ${routeFile}: ${errorMessage(error)}`,
|
|
2641
|
+
);
|
|
2582
2642
|
}
|
|
2583
2643
|
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
];
|
|
2588
|
-
} catch (error) {
|
|
2589
|
-
throw new Error(
|
|
2590
|
-
`Failed to build Cloudflare route module for ${routeFile}: ${errorMessage(error)}`,
|
|
2591
|
-
);
|
|
2592
|
-
}
|
|
2644
|
+
if (options.sourceAnalysis.byRouteFile.get(routeFile)?.hasLoader === true) {
|
|
2645
|
+
try {
|
|
2646
|
+
const loaderModule = loaderRouteModules.entries.get(routeId);
|
|
2593
2647
|
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2648
|
+
if (loaderModule === undefined) {
|
|
2649
|
+
throw new Error("Missing bundled Cloudflare loader module.");
|
|
2650
|
+
}
|
|
2597
2651
|
|
|
2598
|
-
|
|
2599
|
-
|
|
2652
|
+
const loaderFile = loaderModule.fileName;
|
|
2653
|
+
const loaderImport = `./${loaderFile.split("/").pop() ?? loaderFile}`;
|
|
2654
|
+
routeModuleExports.push(`export { loader } from ${JSON.stringify(loaderImport)};`);
|
|
2655
|
+
} catch (error) {
|
|
2656
|
+
throw new Error(
|
|
2657
|
+
`Failed to build Cloudflare loader module for ${routeFile}: ${errorMessage(error)}`,
|
|
2658
|
+
);
|
|
2600
2659
|
}
|
|
2601
|
-
|
|
2602
|
-
const loaderFile = loaderModule.fileName;
|
|
2603
|
-
const loaderImport = `./${loaderFile.split("/").pop() ?? loaderFile}`;
|
|
2604
|
-
routeModuleExports.push(`export { loader } from ${JSON.stringify(loaderImport)};`);
|
|
2605
|
-
} catch (error) {
|
|
2606
|
-
throw new Error(
|
|
2607
|
-
`Failed to build Cloudflare loader module for ${routeFile}: ${errorMessage(error)}`,
|
|
2608
|
-
);
|
|
2609
2660
|
}
|
|
2610
|
-
}
|
|
2611
2661
|
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2662
|
+
await writeFile(
|
|
2663
|
+
join(options.cloudflareDir, routeModuleFile),
|
|
2664
|
+
`${routeModuleExports.join("\n")}\n`,
|
|
2665
|
+
);
|
|
2666
|
+
return `${JSON.stringify(routeFile)}: () => import(${JSON.stringify(`./${routeModuleFile}`)})`;
|
|
2667
|
+
},
|
|
2668
|
+
);
|
|
2615
2669
|
|
|
2616
2670
|
const registrySource = [
|
|
2617
2671
|
`export const routeModules = {`,
|
|
@@ -2893,7 +2947,9 @@ async function buildCloudflareStringRouteComponentModuleBatch(options: {
|
|
|
2893
2947
|
contents: pageMetadataModule,
|
|
2894
2948
|
resolveDir: dirname(route.filename),
|
|
2895
2949
|
});
|
|
2896
|
-
metadataImports.push(
|
|
2950
|
+
metadataImports.push(
|
|
2951
|
+
`import * as pageMetadataModule from ${JSON.stringify(pageMetadataId)};`,
|
|
2952
|
+
);
|
|
2897
2953
|
}
|
|
2898
2954
|
|
|
2899
2955
|
const shellMetadataImports = await Promise.all(
|
|
@@ -3084,7 +3140,11 @@ async function buildCloudflareServerComponentModule(options: {
|
|
|
3084
3140
|
cacheDir: options.cacheDir,
|
|
3085
3141
|
define: options.define,
|
|
3086
3142
|
filename: options.filename,
|
|
3087
|
-
hasMetadata: buildSourceAnalysisForFile(
|
|
3143
|
+
hasMetadata: buildSourceAnalysisForFile(
|
|
3144
|
+
options.sourceAnalysis,
|
|
3145
|
+
options.projectRoot,
|
|
3146
|
+
options.filename,
|
|
3147
|
+
)?.hasMetadata,
|
|
3088
3148
|
root: options.projectRoot,
|
|
3089
3149
|
vitePlugins: options.vitePlugins,
|
|
3090
3150
|
});
|
|
@@ -3098,9 +3158,8 @@ async function buildCloudflareServerComponentModule(options: {
|
|
|
3098
3158
|
filename: `${options.filename}.mreact-cloudflare-component.js`,
|
|
3099
3159
|
cacheDir: options.cacheDir,
|
|
3100
3160
|
define: options.define,
|
|
3101
|
-
modules:
|
|
3102
|
-
? new Map()
|
|
3103
|
-
: new Map([["mreact:metadata", metadataModule]]),
|
|
3161
|
+
modules:
|
|
3162
|
+
metadataModule === undefined ? new Map() : new Map([["mreact:metadata", metadataModule]]),
|
|
3104
3163
|
plugins: [
|
|
3105
3164
|
cloudflareServerSourceTransformPlugin({
|
|
3106
3165
|
projectRoot: options.projectRoot,
|
|
@@ -3180,7 +3239,9 @@ async function buildCloudflareStringRouteComponentModule(options: {
|
|
|
3180
3239
|
}),
|
|
3181
3240
|
),
|
|
3182
3241
|
);
|
|
3183
|
-
const shellImports = shellFiles.map(
|
|
3242
|
+
const shellImports = shellFiles.map(
|
|
3243
|
+
(_, index) => `import * as shell${index} from "mreact:shell-${index}";`,
|
|
3244
|
+
);
|
|
3184
3245
|
const shellDefinitions = shellFiles.map(
|
|
3185
3246
|
(shell, index) =>
|
|
3186
3247
|
`{ component: selectComponent(shell${index}, ${JSON.stringify(shell.file)}), id: ${JSON.stringify(shell.id)}, kind: ${JSON.stringify(shell.kind)}, module: shell${index} }`,
|
|
@@ -3287,7 +3348,9 @@ async function buildCloudflareStreamRouteComponentModule(options: {
|
|
|
3287
3348
|
}),
|
|
3288
3349
|
),
|
|
3289
3350
|
);
|
|
3290
|
-
const shellImports = shellFiles.map(
|
|
3351
|
+
const shellImports = shellFiles.map(
|
|
3352
|
+
(_, index) => `import * as shell${index} from "mreact:shell-${index}";`,
|
|
3353
|
+
);
|
|
3291
3354
|
const shellDefinitions = shellFiles.map(
|
|
3292
3355
|
(shell, index) =>
|
|
3293
3356
|
`{ component: selectComponent(shell${index}, ${JSON.stringify(shell.file)}), id: ${JSON.stringify(shell.id)}, kind: ${JSON.stringify(shell.kind)}, module: shell${index} }`,
|
|
@@ -3687,7 +3750,11 @@ async function buildCloudflareComponentExportModule(options: {
|
|
|
3687
3750
|
cacheDir: options.cacheDir,
|
|
3688
3751
|
define: options.define,
|
|
3689
3752
|
filename: options.filename,
|
|
3690
|
-
hasMetadata: buildSourceAnalysisForFile(
|
|
3753
|
+
hasMetadata: buildSourceAnalysisForFile(
|
|
3754
|
+
options.sourceAnalysis,
|
|
3755
|
+
options.projectRoot,
|
|
3756
|
+
options.filename,
|
|
3757
|
+
)?.hasMetadata,
|
|
3691
3758
|
root: options.projectRoot,
|
|
3692
3759
|
vitePlugins: options.vitePlugins,
|
|
3693
3760
|
});
|
|
@@ -3706,9 +3773,8 @@ export const slots = routeModule.slots;`;
|
|
|
3706
3773
|
cacheDir: options.cacheDir,
|
|
3707
3774
|
define: options.define,
|
|
3708
3775
|
filename: `${options.filename}.mreact-cloudflare-${options.serverOutput}-component.js`,
|
|
3709
|
-
modules:
|
|
3710
|
-
? new Map()
|
|
3711
|
-
: new Map([["mreact:metadata", metadataModule]]),
|
|
3776
|
+
modules:
|
|
3777
|
+
metadataModule === undefined ? new Map() : new Map([["mreact:metadata", metadataModule]]),
|
|
3712
3778
|
plugins: [
|
|
3713
3779
|
cloudflareServerSourceTransformPlugin({
|
|
3714
3780
|
projectRoot: options.projectRoot,
|
|
@@ -4093,6 +4159,7 @@ async function transformCloudflareServerSource(options: {
|
|
|
4093
4159
|
const output = transformCompilerModuleContext({
|
|
4094
4160
|
code: options.source,
|
|
4095
4161
|
clientBoundaryImports: clientInference.clientBoundaryImports,
|
|
4162
|
+
clientBoundaryFallbackImports: clientInference.clientBoundaryFallbackImports,
|
|
4096
4163
|
dev: false,
|
|
4097
4164
|
filename: options.filename,
|
|
4098
4165
|
moduleContext,
|
|
@@ -4106,7 +4173,9 @@ async function transformCloudflareServerSource(options: {
|
|
|
4106
4173
|
|
|
4107
4174
|
if (fatalDiagnostics.length > 0) {
|
|
4108
4175
|
throw new Error(
|
|
4109
|
-
fatalDiagnostics
|
|
4176
|
+
fatalDiagnostics
|
|
4177
|
+
.map((diagnostic) => formatDiagnostic(options.filename, diagnostic))
|
|
4178
|
+
.join("\n"),
|
|
4110
4179
|
);
|
|
4111
4180
|
}
|
|
4112
4181
|
|
|
@@ -4147,9 +4216,18 @@ function cloudflareWorkspaceRuntimePlugin(): RouterCompatPlugin {
|
|
|
4147
4216
|
"@reckona/mreact-compat/event-priority",
|
|
4148
4217
|
packageFile("react-compat", "@reckona/mreact-compat", "event-priority"),
|
|
4149
4218
|
],
|
|
4150
|
-
[
|
|
4151
|
-
|
|
4152
|
-
|
|
4219
|
+
[
|
|
4220
|
+
"@reckona/mreact-compat/flight",
|
|
4221
|
+
packageFile("react-compat", "@reckona/mreact-compat", "flight"),
|
|
4222
|
+
],
|
|
4223
|
+
[
|
|
4224
|
+
"@reckona/mreact-compat/hooks",
|
|
4225
|
+
packageFile("react-compat", "@reckona/mreact-compat", "hooks-entry"),
|
|
4226
|
+
],
|
|
4227
|
+
[
|
|
4228
|
+
"@reckona/mreact-compat/internal",
|
|
4229
|
+
packageFile("react-compat", "@reckona/mreact-compat", "internal"),
|
|
4230
|
+
],
|
|
4153
4231
|
[
|
|
4154
4232
|
"@reckona/mreact-compat/jsx-dev-runtime",
|
|
4155
4233
|
packageFile("react-compat", "@reckona/mreact-compat", "jsx-dev-runtime"),
|
|
@@ -4158,9 +4236,15 @@ function cloudflareWorkspaceRuntimePlugin(): RouterCompatPlugin {
|
|
|
4158
4236
|
"@reckona/mreact-compat/jsx-runtime",
|
|
4159
4237
|
packageFile("react-compat", "@reckona/mreact-compat", "jsx-runtime"),
|
|
4160
4238
|
],
|
|
4161
|
-
[
|
|
4239
|
+
[
|
|
4240
|
+
"@reckona/mreact-compat/scheduler",
|
|
4241
|
+
packageFile("react-compat", "@reckona/mreact-compat", "scheduler"),
|
|
4242
|
+
],
|
|
4162
4243
|
["@reckona/mreact-query", packageFile("query", "@reckona/mreact-query", "index")],
|
|
4163
|
-
[
|
|
4244
|
+
[
|
|
4245
|
+
"@reckona/mreact-reactive-core",
|
|
4246
|
+
packageFile("reactive-core", "@reckona/mreact-reactive-core", "index"),
|
|
4247
|
+
],
|
|
4164
4248
|
[
|
|
4165
4249
|
"@reckona/mreact-router/adapters/cloudflare",
|
|
4166
4250
|
packageFile("router", "@reckona/mreact-router", "adapters/cloudflare"),
|
|
@@ -4179,10 +4263,13 @@ function cloudflareWorkspaceRuntimePlugin(): RouterCompatPlugin {
|
|
|
4179
4263
|
return {
|
|
4180
4264
|
name: "mreact-cloudflare-workspace-runtime",
|
|
4181
4265
|
setup(buildApi) {
|
|
4182
|
-
buildApi.onResolve(
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4266
|
+
buildApi.onResolve(
|
|
4267
|
+
{ filter: /^@reckona\/mreact-router\/(?:internal\/)?native-escape$/ },
|
|
4268
|
+
() => ({
|
|
4269
|
+
namespace: "mreact-cloudflare-native-escape",
|
|
4270
|
+
path: "native-escape",
|
|
4271
|
+
}),
|
|
4272
|
+
);
|
|
4186
4273
|
buildApi.onResolve({ filter: /^@reckona\/mreact-router$/ }, () => ({
|
|
4187
4274
|
namespace: "mreact-cloudflare-router-index",
|
|
4188
4275
|
path: "index",
|
|
@@ -4192,8 +4279,10 @@ function cloudflareWorkspaceRuntimePlugin(): RouterCompatPlugin {
|
|
|
4192
4279
|
|
|
4193
4280
|
return path === undefined ? undefined : { path };
|
|
4194
4281
|
});
|
|
4195
|
-
buildApi.onLoad(
|
|
4196
|
-
|
|
4282
|
+
buildApi.onLoad(
|
|
4283
|
+
{ filter: /^native-escape$/, namespace: "mreact-cloudflare-native-escape" },
|
|
4284
|
+
() => ({
|
|
4285
|
+
contents: `function escapeHtml(value) {
|
|
4197
4286
|
return String(value ?? "").replace(/[&<>"']/g, (char) =>
|
|
4198
4287
|
char === "&" ? "&" : char === "<" ? "<" : char === ">" ? ">" : char === '"' ? """ : "'"
|
|
4199
4288
|
);
|
|
@@ -4201,8 +4290,9 @@ function cloudflareWorkspaceRuntimePlugin(): RouterCompatPlugin {
|
|
|
4201
4290
|
export function escapeHtmlBatch(values) {
|
|
4202
4291
|
return values.map(escapeHtml);
|
|
4203
4292
|
}`,
|
|
4204
|
-
|
|
4205
|
-
|
|
4293
|
+
loader: "js",
|
|
4294
|
+
}),
|
|
4295
|
+
);
|
|
4206
4296
|
buildApi.onLoad({ filter: /^index$/, namespace: "mreact-cloudflare-router-index" }, () => ({
|
|
4207
4297
|
contents: `export { cacheControl, revalidatePath } from ${JSON.stringify(routerCachePath)};
|
|
4208
4298
|
export { deleteCookie, parseCookieHeader, serializeCookie, setCookie } from ${JSON.stringify(routerCookiesPath)};
|
|
@@ -4216,12 +4306,15 @@ export { getServerRuntimeState } from ${JSON.stringify(routerRuntimeStatePath)};
|
|
|
4216
4306
|
loader: "js",
|
|
4217
4307
|
resolveDir: dirname(routerNavigationPath),
|
|
4218
4308
|
}));
|
|
4219
|
-
buildApi.onLoad(
|
|
4220
|
-
|
|
4309
|
+
buildApi.onLoad(
|
|
4310
|
+
{ filter: /(?:^|[/\\])packages[/\\]server[/\\](?:src|dist)[/\\]native-flight\.[jt]s$/ },
|
|
4311
|
+
() => ({
|
|
4312
|
+
contents: `export function getNativeFlight() {
|
|
4221
4313
|
return undefined;
|
|
4222
4314
|
}`,
|
|
4223
|
-
|
|
4224
|
-
|
|
4315
|
+
loader: "js",
|
|
4316
|
+
}),
|
|
4317
|
+
);
|
|
4225
4318
|
},
|
|
4226
4319
|
};
|
|
4227
4320
|
}
|
|
@@ -4286,6 +4379,12 @@ function viteManifestFromClientRoutes(routes: ClientRouteManifestEntry[]): Recor
|
|
|
4286
4379
|
interface ClientRouteBundleManifest {
|
|
4287
4380
|
assets: string[];
|
|
4288
4381
|
routes: ClientRouteManifestEntry[];
|
|
4382
|
+
styles: ClientStyleManifestEntry[];
|
|
4383
|
+
}
|
|
4384
|
+
|
|
4385
|
+
interface ClientStyleManifestEntry {
|
|
4386
|
+
css: string[];
|
|
4387
|
+
file: string;
|
|
4289
4388
|
}
|
|
4290
4389
|
|
|
4291
4390
|
async function writeClientRouteBundles(options: {
|
|
@@ -4322,6 +4421,14 @@ async function writeClientRouteBundles(options: {
|
|
|
4322
4421
|
sourceAnalysis: options.sourceAnalysis,
|
|
4323
4422
|
vitePlugins: options.vitePlugins,
|
|
4324
4423
|
});
|
|
4424
|
+
const specialCssAssets = await writeSpecialRouteCssAssetBatches({
|
|
4425
|
+
appDir: options.appDir,
|
|
4426
|
+
cacheDir: options.cacheDir,
|
|
4427
|
+
clientDir: options.clientDir,
|
|
4428
|
+
projectRoot: options.projectRoot,
|
|
4429
|
+
sourceAnalysis: options.sourceAnalysis,
|
|
4430
|
+
vitePlugins: options.vitePlugins,
|
|
4431
|
+
});
|
|
4325
4432
|
const entries: PreparedRouteEntry[] = await Promise.all(
|
|
4326
4433
|
options.routes.map(async (route) => {
|
|
4327
4434
|
if (route.kind !== "page") {
|
|
@@ -4405,6 +4512,7 @@ async function writeClientRouteBundles(options: {
|
|
|
4405
4512
|
return {
|
|
4406
4513
|
assets: [],
|
|
4407
4514
|
routes: entries.flatMap((entry) => ("manifest" in entry ? [entry.manifest] : [])),
|
|
4515
|
+
styles: specialCssAssets,
|
|
4408
4516
|
};
|
|
4409
4517
|
}
|
|
4410
4518
|
|
|
@@ -4423,18 +4531,23 @@ async function writeClientRouteBundles(options: {
|
|
|
4423
4531
|
});
|
|
4424
4532
|
} catch (error) {
|
|
4425
4533
|
const routeContexts = clientEntries
|
|
4426
|
-
.map(
|
|
4534
|
+
.map(
|
|
4535
|
+
(entry) => `Failed to build client bundle for ${entry.route.path} (${entry.route.file}).`,
|
|
4536
|
+
)
|
|
4427
4537
|
.join("\n");
|
|
4428
4538
|
|
|
4429
|
-
throw new Error(
|
|
4430
|
-
|
|
4431
|
-
|
|
4539
|
+
throw new Error(
|
|
4540
|
+
`${routeContexts}\nFailed to build client route bundles.\n${errorMessage(error)}`,
|
|
4541
|
+
{
|
|
4542
|
+
cause: error,
|
|
4543
|
+
},
|
|
4544
|
+
);
|
|
4432
4545
|
}
|
|
4433
4546
|
|
|
4434
4547
|
const routeOutputs = new Map(output.routes.map((route) => [route.routePath, route]));
|
|
4435
4548
|
const mapAssets = new Map(
|
|
4436
4549
|
output.chunks.flatMap((chunk) =>
|
|
4437
|
-
chunk.map === undefined ? [] : [[`${chunk.fileName}.map`, chunk.map] as const]
|
|
4550
|
+
chunk.map === undefined ? [] : [[`${chunk.fileName}.map`, chunk.map] as const],
|
|
4438
4551
|
),
|
|
4439
4552
|
);
|
|
4440
4553
|
|
|
@@ -4459,9 +4572,7 @@ async function writeClientRouteBundles(options: {
|
|
|
4459
4572
|
|
|
4460
4573
|
for (const asset of output.assets ?? []) {
|
|
4461
4574
|
const source =
|
|
4462
|
-
typeof asset.source === "string"
|
|
4463
|
-
? asset.source
|
|
4464
|
-
: Buffer.from(asset.source).toString("utf8");
|
|
4575
|
+
typeof asset.source === "string" ? asset.source : Buffer.from(asset.source).toString("utf8");
|
|
4465
4576
|
|
|
4466
4577
|
await mkdir(dirname(join(options.clientDir, asset.fileName)), { recursive: true });
|
|
4467
4578
|
await writeFile(join(options.clientDir, asset.fileName), source);
|
|
@@ -4521,9 +4632,65 @@ async function writeClientRouteBundles(options: {
|
|
|
4521
4632
|
return {
|
|
4522
4633
|
assets: Array.from(generatedAssets).sort(),
|
|
4523
4634
|
routes,
|
|
4635
|
+
styles: specialCssAssets,
|
|
4524
4636
|
};
|
|
4525
4637
|
}
|
|
4526
4638
|
|
|
4639
|
+
async function writeSpecialRouteCssAssetBatches(options: {
|
|
4640
|
+
appDir: string;
|
|
4641
|
+
cacheDir?: string | undefined;
|
|
4642
|
+
clientDir: string;
|
|
4643
|
+
projectRoot: string;
|
|
4644
|
+
sourceAnalysis: BuildSourceAnalysisScope;
|
|
4645
|
+
vitePlugins?: readonly PluginOption[] | undefined;
|
|
4646
|
+
}): Promise<ClientStyleManifestEntry[]> {
|
|
4647
|
+
const boundaryFiles = await collectSpecialBoundaryFiles(options.appDir);
|
|
4648
|
+
const entries = await mapWithBuildConcurrency(boundaryFiles, async (file) => {
|
|
4649
|
+
const cssFiles = await collectRouteCssFilesFromSources({
|
|
4650
|
+
appDir: options.appDir,
|
|
4651
|
+
pageFile: file,
|
|
4652
|
+
projectRoot: options.projectRoot,
|
|
4653
|
+
readSource: (sourceFile) =>
|
|
4654
|
+
buildSourceAnalysisForFile(options.sourceAnalysis, options.projectRoot, sourceFile)?.source,
|
|
4655
|
+
});
|
|
4656
|
+
|
|
4657
|
+
if (cssFiles.length === 0) {
|
|
4658
|
+
return undefined;
|
|
4659
|
+
}
|
|
4660
|
+
|
|
4661
|
+
const css = await writeRouteCssAssetsForFiles({
|
|
4662
|
+
cacheDir: options.cacheDir,
|
|
4663
|
+
clientDir: options.clientDir,
|
|
4664
|
+
cssFiles,
|
|
4665
|
+
pageFile: file,
|
|
4666
|
+
projectRoot: options.projectRoot,
|
|
4667
|
+
routeIds: [specialBoundaryRouteId(options.appDir, file)],
|
|
4668
|
+
vitePlugins: options.vitePlugins,
|
|
4669
|
+
});
|
|
4670
|
+
|
|
4671
|
+
return css.length === 0
|
|
4672
|
+
? undefined
|
|
4673
|
+
: ({
|
|
4674
|
+
css,
|
|
4675
|
+
file: relative(options.appDir, file).split(sep).join("/"),
|
|
4676
|
+
} satisfies ClientStyleManifestEntry);
|
|
4677
|
+
});
|
|
4678
|
+
|
|
4679
|
+
return entries
|
|
4680
|
+
.filter((entry): entry is ClientStyleManifestEntry => entry !== undefined)
|
|
4681
|
+
.sort((left, right) => left.file.localeCompare(right.file));
|
|
4682
|
+
}
|
|
4683
|
+
|
|
4684
|
+
function specialBoundaryRouteId(appDir: string, file: string): string {
|
|
4685
|
+
const relativeFile = relative(appDir, file).split(sep);
|
|
4686
|
+
const filename = relativeFile.pop() ?? "boundary.tsx";
|
|
4687
|
+
const boundaryName = filename.replace(/(?:\.mreact)?\.tsx$/u, "");
|
|
4688
|
+
const routeParts = relativeFile.filter((part) => !part.startsWith("(") || !part.endsWith(")"));
|
|
4689
|
+
const path = `/${[...routeParts, boundaryName].join("/")}`;
|
|
4690
|
+
|
|
4691
|
+
return routeIdForPath(path);
|
|
4692
|
+
}
|
|
4693
|
+
|
|
4527
4694
|
async function writeRouteCssAssetBatches(options: {
|
|
4528
4695
|
appDir: string;
|
|
4529
4696
|
cacheDir?: string | undefined;
|
|
@@ -4538,12 +4705,16 @@ async function writeRouteCssAssetBatches(options: {
|
|
|
4538
4705
|
appDir: options.appDir,
|
|
4539
4706
|
pageFile: route.file,
|
|
4540
4707
|
projectRoot: options.projectRoot,
|
|
4541
|
-
readSource: (file) =>
|
|
4708
|
+
readSource: (file) =>
|
|
4709
|
+
buildSourceAnalysisForFile(options.sourceAnalysis, options.projectRoot, file)?.source,
|
|
4542
4710
|
});
|
|
4543
4711
|
|
|
4544
4712
|
return { cssFiles, route };
|
|
4545
4713
|
});
|
|
4546
|
-
const groups = new Map<
|
|
4714
|
+
const groups = new Map<
|
|
4715
|
+
string,
|
|
4716
|
+
{ cssFiles: string[]; routeIds: string[]; routeFiles: string[] }
|
|
4717
|
+
>();
|
|
4547
4718
|
|
|
4548
4719
|
for (const { cssFiles, route } of cssInputs) {
|
|
4549
4720
|
if (cssFiles.length === 0) {
|
|
@@ -4557,18 +4728,22 @@ async function writeRouteCssAssetBatches(options: {
|
|
|
4557
4728
|
groups.set(key, group);
|
|
4558
4729
|
}
|
|
4559
4730
|
|
|
4560
|
-
const writtenGroups = await mapWithBuildConcurrency(
|
|
4561
|
-
|
|
4562
|
-
|
|
4563
|
-
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
|
|
4731
|
+
const writtenGroups = await mapWithBuildConcurrency(
|
|
4732
|
+
[...groups.entries()],
|
|
4733
|
+
async ([key, group]) =>
|
|
4734
|
+
[
|
|
4735
|
+
key,
|
|
4736
|
+
await writeRouteCssAssetsForFiles({
|
|
4737
|
+
cacheDir: options.cacheDir,
|
|
4738
|
+
clientDir: options.clientDir,
|
|
4739
|
+
cssFiles: group.cssFiles,
|
|
4740
|
+
pageFile: group.routeFiles[0] ?? options.appDir,
|
|
4741
|
+
projectRoot: options.projectRoot,
|
|
4742
|
+
routeIds: group.routeIds,
|
|
4743
|
+
vitePlugins: options.vitePlugins,
|
|
4744
|
+
}),
|
|
4745
|
+
] as const,
|
|
4746
|
+
);
|
|
4572
4747
|
const cssByGroup = new Map(writtenGroups);
|
|
4573
4748
|
const cssByRoute = new Map<string, string[]>();
|
|
4574
4749
|
|
|
@@ -4612,15 +4787,14 @@ async function writeRouteCssAssetsForFiles(options: {
|
|
|
4612
4787
|
});
|
|
4613
4788
|
const cssAssets = (output.assets ?? []).filter((asset) => asset.fileName.endsWith(".css"));
|
|
4614
4789
|
const written: string[] = [];
|
|
4615
|
-
const routeStem =
|
|
4616
|
-
|
|
4617
|
-
|
|
4790
|
+
const routeStem =
|
|
4791
|
+
options.routeIds.length === 1
|
|
4792
|
+
? (options.routeIds[0] ?? "index")
|
|
4793
|
+
: `shared.${hashText(cssFiles.join("\0")).slice(0, 8)}`;
|
|
4618
4794
|
|
|
4619
4795
|
for (const [index, asset] of cssAssets.entries()) {
|
|
4620
4796
|
const source =
|
|
4621
|
-
typeof asset.source === "string"
|
|
4622
|
-
? asset.source
|
|
4623
|
-
: Buffer.from(asset.source).toString("utf8");
|
|
4797
|
+
typeof asset.source === "string" ? asset.source : Buffer.from(asset.source).toString("utf8");
|
|
4624
4798
|
const hash = createHash("sha256").update(source).digest("hex").slice(0, 8);
|
|
4625
4799
|
const cssFile = `assets/routes/${routeStem}${cssAssets.length === 1 ? "" : `.${index}`}.${hash}.css`;
|
|
4626
4800
|
|
|
@@ -4798,7 +4972,9 @@ function isBarePackageImport(specifier: string): boolean {
|
|
|
4798
4972
|
|
|
4799
4973
|
async function assertAwsLambdaRuntimeDependencies(outDir: string): Promise<void> {
|
|
4800
4974
|
try {
|
|
4801
|
-
const info = await stat(
|
|
4975
|
+
const info = await stat(
|
|
4976
|
+
join(outDir, "node_modules", "@reckona", "mreact-router", "package.json"),
|
|
4977
|
+
);
|
|
4802
4978
|
if (info.isFile()) {
|
|
4803
4979
|
return;
|
|
4804
4980
|
}
|
|
@@ -4891,7 +5067,9 @@ function assertPackageOutputDoesNotReplaceBuildOutput(options: {
|
|
|
4891
5067
|
outDir: string;
|
|
4892
5068
|
}): void {
|
|
4893
5069
|
if (resolve(options.fromDir) === resolve(options.outDir)) {
|
|
4894
|
-
throw new Error(
|
|
5070
|
+
throw new Error(
|
|
5071
|
+
"Package output directory must be different from the mreact build output directory.",
|
|
5072
|
+
);
|
|
4895
5073
|
}
|
|
4896
5074
|
}
|
|
4897
5075
|
|
|
@@ -4955,7 +5133,9 @@ async function collectArtifactFiles(
|
|
|
4955
5133
|
}
|
|
4956
5134
|
}
|
|
4957
5135
|
|
|
4958
|
-
return files.sort(
|
|
5136
|
+
return files.sort(
|
|
5137
|
+
(left, right) => right.bytes - left.bytes || left.path.localeCompare(right.path),
|
|
5138
|
+
);
|
|
4959
5139
|
}
|
|
4960
5140
|
|
|
4961
5141
|
function awsLambdaHandlerSource(outDirRelativeToHandler: string): string {
|
|
@@ -5000,6 +5180,7 @@ async function validateProductionRoutes(options: {
|
|
|
5000
5180
|
cache: options.serverTransformCache,
|
|
5001
5181
|
code: analysis.routeCode,
|
|
5002
5182
|
clientBoundaryImports: analysis.clientBoundaryImports,
|
|
5183
|
+
clientBoundaryFallbackImports: analysis.clientBoundaryFallbackImports,
|
|
5003
5184
|
filename: route.file,
|
|
5004
5185
|
moduleContextCache: options.clientRouteInferenceCache,
|
|
5005
5186
|
serverOutput: analysis.streamRoute ? "stream" : "string",
|
|
@@ -5039,10 +5220,10 @@ async function collectBuildFiles(
|
|
|
5039
5220
|
|
|
5040
5221
|
return [{ file, relativeFile }];
|
|
5041
5222
|
});
|
|
5042
|
-
const fileContents = await mapWithBuildConcurrency(
|
|
5043
|
-
|
|
5044
|
-
await readFile(file, "utf8"),
|
|
5045
|
-
|
|
5223
|
+
const fileContents = await mapWithBuildConcurrency(
|
|
5224
|
+
sourceFiles,
|
|
5225
|
+
async ({ file, relativeFile }) => [relativeFile, await readFile(file, "utf8")] as const,
|
|
5226
|
+
);
|
|
5046
5227
|
|
|
5047
5228
|
for (const [relativeFile, source] of fileContents) {
|
|
5048
5229
|
files[relativeFile] = source;
|