evolit 0.1.0-alpha.2 → 0.1.0-alpha.21
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 +73 -3
- package/package.json +13 -6
- package/src/build.js +37 -9
- package/src/cli.js +16 -9
- package/src/client-assets.js +326 -70
- package/src/compiler.js +176 -9
- package/src/deployment-runtime.js +246 -43
- package/src/development-events.js +96 -0
- package/src/navigation-client.js +519 -0
- package/src/navigation-server.js +3 -0
- package/src/navigation-url.js +28 -0
- package/src/render.js +328 -19
- package/src/route-config.js +3 -1
- package/src/route-segments.js +272 -0
- package/src/scaffold.js +4 -0
- package/src/server.js +156 -13
- package/src/ssr-adapter.js +127 -12
- package/src/terminal.js +32 -0
- package/templates/default/yarnrc.yml.template +1 -0
package/src/client-assets.js
CHANGED
|
@@ -3,6 +3,7 @@ import { existsSync, realpathSync } from "node:fs";
|
|
|
3
3
|
import crypto from "node:crypto";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { createRequire } from "node:module";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
6
7
|
import MagicString from "magic-string";
|
|
7
8
|
import { rollup } from "rollup";
|
|
8
9
|
import { nodeResolve } from "@rollup/plugin-node-resolve";
|
|
@@ -24,10 +25,12 @@ const MODULE_SPECIFIER_PATTERN =
|
|
|
24
25
|
/\b(?:import|export)\s*[^"']*?from\s*["']([^"']+)["']|\bimport\s*["']([^"']+)["']|\bimport\s*\(\s*["']([^"']+)["']\s*\)/g;
|
|
25
26
|
|
|
26
27
|
const requireFromHere = createRequire(import.meta.url);
|
|
28
|
+
const EVOLIT_NAVIGATION_BROWSER_ENTRY = fileURLToPath(new URL("./navigation-client.js", import.meta.url));
|
|
27
29
|
const SHARED_VENDOR_SPECIFIERS = [
|
|
28
30
|
"@litsx/core",
|
|
29
31
|
"@litsx/core/elements",
|
|
30
32
|
"@litsx/ssr/hydration",
|
|
33
|
+
"evolit/navigation",
|
|
31
34
|
"lit",
|
|
32
35
|
];
|
|
33
36
|
const browserSpecifierFilePathCache = new Map();
|
|
@@ -36,6 +39,23 @@ const sharedRuntimeBuildCache = new Map();
|
|
|
36
39
|
const clientVendorSpecifierCache = new Map();
|
|
37
40
|
const clientModuleMetadataCache = new Map();
|
|
38
41
|
|
|
42
|
+
export function resetDevelopmentAssetCaches(projectRoot) {
|
|
43
|
+
const normalizedProjectRoot = path.resolve(projectRoot);
|
|
44
|
+
const developmentPrefix = `${normalizedProjectRoot}::development::`;
|
|
45
|
+
|
|
46
|
+
for (const cache of [
|
|
47
|
+
sharedRuntimeBuildCache,
|
|
48
|
+
clientVendorSpecifierCache,
|
|
49
|
+
clientModuleMetadataCache,
|
|
50
|
+
]) {
|
|
51
|
+
for (const key of cache.keys()) {
|
|
52
|
+
if (key.startsWith(developmentPrefix)) {
|
|
53
|
+
cache.delete(key);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
39
59
|
function isBareSpecifier(specifier) {
|
|
40
60
|
return (
|
|
41
61
|
typeof specifier === "string" &&
|
|
@@ -57,6 +77,31 @@ function isRelativeSpecifier(specifier) {
|
|
|
57
77
|
);
|
|
58
78
|
}
|
|
59
79
|
|
|
80
|
+
function stripImportSearchAndHash(specifier) {
|
|
81
|
+
return String(specifier).split("?")[0].split("#")[0];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function resolveRelativeClientImportPath(fromClientModule, specifier) {
|
|
85
|
+
const normalizedSpecifier = stripImportSearchAndHash(specifier);
|
|
86
|
+
return path
|
|
87
|
+
.normalize(path.join(path.dirname(fromClientModule), normalizedSpecifier))
|
|
88
|
+
.split(path.sep)
|
|
89
|
+
.join("/");
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function normalizeClientMetadataAssetPath(fromClientModule, importedAsset) {
|
|
93
|
+
if (typeof importedAsset !== "string") {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const normalizedAsset = stripImportSearchAndHash(importedAsset);
|
|
98
|
+
if (isRelativeSpecifier(normalizedAsset)) {
|
|
99
|
+
return resolveRelativeClientImportPath(fromClientModule, normalizedAsset);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return path.normalize(normalizedAsset).split(path.sep).join("/");
|
|
103
|
+
}
|
|
104
|
+
|
|
60
105
|
function parsePackageSpecifier(specifier) {
|
|
61
106
|
if (!isBareSpecifier(specifier)) {
|
|
62
107
|
return null;
|
|
@@ -217,9 +262,12 @@ function createSharedEntrySource(specifier) {
|
|
|
217
262
|
].join("\n");
|
|
218
263
|
}
|
|
219
264
|
|
|
220
|
-
export async function collectSharedVendorSpecifiers(
|
|
265
|
+
export async function collectSharedVendorSpecifiers(
|
|
266
|
+
additionalEntrySpecifiers = [],
|
|
267
|
+
options = {},
|
|
268
|
+
) {
|
|
221
269
|
return [...new Set([
|
|
222
|
-
...SHARED_VENDOR_SPECIFIERS,
|
|
270
|
+
...(options.includeBase === false ? [] : SHARED_VENDOR_SPECIFIERS),
|
|
223
271
|
...additionalEntrySpecifiers.filter((specifier) => isBareSpecifier(specifier)),
|
|
224
272
|
])].sort();
|
|
225
273
|
}
|
|
@@ -414,20 +462,52 @@ export async function buildSharedVendorRuntime(
|
|
|
414
462
|
? options.additionalEntrySpecifiers.filter((specifier) => isBareSpecifier(specifier))
|
|
415
463
|
: [],
|
|
416
464
|
)].sort();
|
|
417
|
-
|
|
465
|
+
if (mode === "development" && !options.vendorGroup) {
|
|
466
|
+
const baseRuntime = await buildSharedVendorRuntime(projectRoot, mode, {
|
|
467
|
+
...options,
|
|
468
|
+
additionalEntrySpecifiers: [],
|
|
469
|
+
vendorGroup: "base",
|
|
470
|
+
includeBase: true,
|
|
471
|
+
});
|
|
472
|
+
const additionalRuntimes = await Promise.all(
|
|
473
|
+
additionalEntrySpecifiers
|
|
474
|
+
.filter((specifier) => !SHARED_VENDOR_SPECIFIERS.includes(specifier))
|
|
475
|
+
.map((specifier) => buildSharedVendorRuntime(projectRoot, mode, {
|
|
476
|
+
...options,
|
|
477
|
+
additionalEntrySpecifiers: [specifier],
|
|
478
|
+
vendorGroup: `vendor-${crypto.createHash("sha1").update(specifier).digest("hex").slice(0, 10)}`,
|
|
479
|
+
includeBase: false,
|
|
480
|
+
})),
|
|
481
|
+
);
|
|
482
|
+
return {
|
|
483
|
+
imports: Object.assign(
|
|
484
|
+
{},
|
|
485
|
+
baseRuntime.imports,
|
|
486
|
+
...additionalRuntimes.map((runtime) => runtime.imports),
|
|
487
|
+
),
|
|
488
|
+
outputRoot: getSharedOutputRoot(projectRoot, mode),
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
const vendorGroup = options.vendorGroup ?? null;
|
|
493
|
+
const cacheKey = `${projectRoot}::${mode}::${vendorGroup ?? "all"}::${additionalEntrySpecifiers.join("|")}`;
|
|
418
494
|
if (sharedRuntimeBuildCache.has(cacheKey)) {
|
|
419
495
|
return sharedRuntimeBuildCache.get(cacheKey);
|
|
420
496
|
}
|
|
421
497
|
|
|
422
498
|
const pendingBuild = (async () => {
|
|
423
|
-
const
|
|
499
|
+
const sharedRootBase = getSharedOutputRoot(projectRoot, mode);
|
|
500
|
+
const sharedRoot = vendorGroup ? path.join(sharedRootBase, vendorGroup) : sharedRootBase;
|
|
424
501
|
const entriesRoot = path.join(
|
|
425
502
|
projectRoot,
|
|
426
503
|
INTERNAL_DIRECTORY,
|
|
427
504
|
mode === "development" ? DEV_DIRECTORY : BUILD_DIRECTORY,
|
|
428
505
|
"__shared_entries__",
|
|
506
|
+
...(vendorGroup ? [vendorGroup] : []),
|
|
429
507
|
);
|
|
430
|
-
const specifiers = await collectSharedVendorSpecifiers(additionalEntrySpecifiers
|
|
508
|
+
const specifiers = await collectSharedVendorSpecifiers(additionalEntrySpecifiers, {
|
|
509
|
+
includeBase: options.includeBase !== false,
|
|
510
|
+
});
|
|
431
511
|
const inputEntries = await writeSharedRuntimeEntrySources(entriesRoot, specifiers);
|
|
432
512
|
|
|
433
513
|
await fs.rm(sharedRoot, { recursive: true, force: true });
|
|
@@ -439,6 +519,15 @@ export async function buildSharedVendorRuntime(
|
|
|
439
519
|
const bundle = await rollup({
|
|
440
520
|
input: inputEntries,
|
|
441
521
|
plugins: [
|
|
522
|
+
{
|
|
523
|
+
name: "evolit-browser-exports",
|
|
524
|
+
resolveId(source) {
|
|
525
|
+
// A consuming application does not normally have an `evolit`
|
|
526
|
+
// package nested in its node_modules. Resolve Evolit's own
|
|
527
|
+
// browser-only public entry before node-resolve marks it external.
|
|
528
|
+
return source === "evolit/navigation" ? EVOLIT_NAVIGATION_BROWSER_ENTRY : null;
|
|
529
|
+
},
|
|
530
|
+
},
|
|
442
531
|
nodeResolve({
|
|
443
532
|
browser: true,
|
|
444
533
|
exportConditions: ["browser", "import", "default"],
|
|
@@ -482,7 +571,7 @@ export async function buildSharedVendorRuntime(
|
|
|
482
571
|
continue;
|
|
483
572
|
}
|
|
484
573
|
|
|
485
|
-
imports[specifier] = `/_evolit/shared/${chunk.fileName}`;
|
|
574
|
+
imports[specifier] = `/_evolit/shared/${vendorGroup ? `${vendorGroup}/` : ""}${chunk.fileName}`;
|
|
486
575
|
}
|
|
487
576
|
|
|
488
577
|
return {
|
|
@@ -561,7 +650,10 @@ async function resolveRelativeImportFilePath(fromFilePath, specifier) {
|
|
|
561
650
|
return null;
|
|
562
651
|
}
|
|
563
652
|
|
|
564
|
-
const candidatePath = path.resolve(
|
|
653
|
+
const candidatePath = path.resolve(
|
|
654
|
+
path.dirname(stripImportSearchAndHash(fromFilePath)),
|
|
655
|
+
stripImportSearchAndHash(specifier),
|
|
656
|
+
);
|
|
565
657
|
const candidatePaths = [
|
|
566
658
|
candidatePath,
|
|
567
659
|
`${candidatePath}.js`,
|
|
@@ -688,10 +780,16 @@ async function collectTransitiveClientModuleMetadata(projectRoot, mode, clientMo
|
|
|
688
780
|
}
|
|
689
781
|
|
|
690
782
|
for (const styleImport of metadata.styleImports) {
|
|
691
|
-
|
|
783
|
+
const normalizedStyleImport = normalizeClientMetadataAssetPath(currentModule, styleImport);
|
|
784
|
+
if (normalizedStyleImport) {
|
|
785
|
+
styleImports.add(normalizedStyleImport);
|
|
786
|
+
}
|
|
692
787
|
}
|
|
693
788
|
for (const assetImport of metadata.assetImports) {
|
|
694
|
-
|
|
789
|
+
const normalizedAssetImport = normalizeClientMetadataAssetPath(currentModule, assetImport);
|
|
790
|
+
if (normalizedAssetImport) {
|
|
791
|
+
assetImports.add(normalizedAssetImport);
|
|
792
|
+
}
|
|
695
793
|
}
|
|
696
794
|
for (const importedModule of metadata.moduleImports) {
|
|
697
795
|
pendingModules.push(importedModule);
|
|
@@ -837,10 +935,25 @@ export function getClientOutputRoot(projectRoot, mode) {
|
|
|
837
935
|
}
|
|
838
936
|
|
|
839
937
|
export function toClientModuleRelativePath(projectRoot, sourcePath) {
|
|
840
|
-
const relativePath =
|
|
938
|
+
const relativePath = toClientSourceRelativePath(projectRoot, sourcePath);
|
|
841
939
|
return toCompiledClientModuleRelativePath(relativePath);
|
|
842
940
|
}
|
|
843
941
|
|
|
942
|
+
function toClientSourceRelativePath(projectRoot, sourcePath) {
|
|
943
|
+
const relativePath = path.relative(projectRoot, sourcePath);
|
|
944
|
+
const isOutsideProject = relativePath === ".."
|
|
945
|
+
|| relativePath.startsWith(`..${path.sep}`)
|
|
946
|
+
|| path.isAbsolute(relativePath);
|
|
947
|
+
if (!isOutsideProject) {
|
|
948
|
+
return relativePath;
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
return path.join(
|
|
952
|
+
"__unmanaged__",
|
|
953
|
+
...relativePath.split(path.sep).map((segment) => segment === ".." ? "__up__" : segment),
|
|
954
|
+
);
|
|
955
|
+
}
|
|
956
|
+
|
|
844
957
|
function toCompiledClientModuleRelativePath(relativePath) {
|
|
845
958
|
const extension = path.extname(relativePath);
|
|
846
959
|
return extension
|
|
@@ -848,17 +961,66 @@ function toCompiledClientModuleRelativePath(relativePath) {
|
|
|
848
961
|
: `${relativePath}.mjs`;
|
|
849
962
|
}
|
|
850
963
|
|
|
964
|
+
function toCatchAllClientModuleRelativePath(clientModule) {
|
|
965
|
+
return clientModule
|
|
966
|
+
.split(/[\\/]/)
|
|
967
|
+
.map((segment) => {
|
|
968
|
+
if (segment.startsWith("[[...") && segment.endsWith("]]")) {
|
|
969
|
+
return `**...${segment.slice(5, -2)}**`;
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
if (segment.startsWith("[...") && segment.endsWith("]")) {
|
|
973
|
+
return `*...${segment.slice(4, -1)}*`;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
return segment;
|
|
977
|
+
})
|
|
978
|
+
.join("/");
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
function toRollupSafeClientModuleRelativePath(clientModule) {
|
|
982
|
+
return clientModule.replaceAll(/[\[\]]/g, "_");
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
function getClientModuleCandidates(clientModule) {
|
|
986
|
+
const normalizedClientModule = clientModule.split(path.sep).join("/");
|
|
987
|
+
return [...new Set([
|
|
988
|
+
normalizedClientModule,
|
|
989
|
+
toCatchAllClientModuleRelativePath(normalizedClientModule),
|
|
990
|
+
toRollupSafeClientModuleRelativePath(normalizedClientModule),
|
|
991
|
+
])];
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
function getClientModulePublicUrl(assetManifest, clientModule) {
|
|
995
|
+
for (const candidate of getClientModuleCandidates(clientModule)) {
|
|
996
|
+
const publicUrl = assetManifest.byClientModule[candidate];
|
|
997
|
+
if (typeof publicUrl === "string" && publicUrl.length > 0) {
|
|
998
|
+
return publicUrl;
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
const candidates = new Set(getClientModuleCandidates(clientModule));
|
|
1003
|
+
const asset = assetManifest.assets.find((entry) =>
|
|
1004
|
+
candidates.has(entry?.clientModule) && typeof entry?.publicUrl === "string",
|
|
1005
|
+
);
|
|
1006
|
+
if (asset) {
|
|
1007
|
+
return asset.publicUrl;
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
return null;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
function isVirtualClientModuleId(moduleId) {
|
|
1014
|
+
return moduleId.startsWith("/app/") || moduleId.startsWith("/__unmanaged__/");
|
|
1015
|
+
}
|
|
1016
|
+
|
|
851
1017
|
function toPublicHydrationModuleId(projectRoot, moduleId) {
|
|
852
1018
|
if (typeof moduleId !== "string" || moduleId.length === 0) {
|
|
853
1019
|
return null;
|
|
854
1020
|
}
|
|
855
1021
|
|
|
856
1022
|
if (path.isAbsolute(moduleId)) {
|
|
857
|
-
|
|
858
|
-
return null;
|
|
859
|
-
}
|
|
860
|
-
|
|
861
|
-
const relativePath = path.relative(projectRoot, moduleId).split(path.sep).join("/");
|
|
1023
|
+
const relativePath = toClientSourceRelativePath(projectRoot, moduleId).split(path.sep).join("/");
|
|
862
1024
|
return `/${relativePath}`;
|
|
863
1025
|
}
|
|
864
1026
|
|
|
@@ -900,14 +1062,10 @@ export function createAssetResolver(projectRoot, options = {}) {
|
|
|
900
1062
|
}
|
|
901
1063
|
|
|
902
1064
|
let relativeClientModule = null;
|
|
903
|
-
if (
|
|
904
|
-
relativeClientModule = toCompiledClientModuleRelativePath(moduleId.slice(1));
|
|
905
|
-
} else if (path.isAbsolute(moduleId)) {
|
|
906
|
-
if (!moduleId.startsWith(projectRoot)) {
|
|
907
|
-
return null;
|
|
908
|
-
}
|
|
909
|
-
|
|
1065
|
+
if (path.isAbsolute(moduleId) && !isVirtualClientModuleId(moduleId)) {
|
|
910
1066
|
relativeClientModule = toClientModuleRelativePath(projectRoot, moduleId);
|
|
1067
|
+
} else if (moduleId.startsWith("/")) {
|
|
1068
|
+
relativeClientModule = toCompiledClientModuleRelativePath(moduleId.slice(1));
|
|
911
1069
|
}
|
|
912
1070
|
|
|
913
1071
|
if (!relativeClientModule) {
|
|
@@ -915,10 +1073,7 @@ export function createAssetResolver(projectRoot, options = {}) {
|
|
|
915
1073
|
}
|
|
916
1074
|
|
|
917
1075
|
if (assetManifest) {
|
|
918
|
-
return
|
|
919
|
-
assetManifest,
|
|
920
|
-
relativeClientModule,
|
|
921
|
-
)?.publicUrl ?? null;
|
|
1076
|
+
return getClientModulePublicUrl(assetManifest, relativeClientModule);
|
|
922
1077
|
}
|
|
923
1078
|
|
|
924
1079
|
return null;
|
|
@@ -941,10 +1096,11 @@ export function createHydrationBootstrap({
|
|
|
941
1096
|
hydrationData,
|
|
942
1097
|
assetResolver,
|
|
943
1098
|
hydrationModuleUrl = "@litsx/ssr/hydration",
|
|
1099
|
+
navigationModuleUrl = null,
|
|
944
1100
|
}) {
|
|
945
1101
|
const normalizedHydrationData = normalizeHydrationDataForClient(hydrationData);
|
|
946
|
-
const
|
|
947
|
-
(normalizedHydrationData?.roots ?? [])
|
|
1102
|
+
const rootModuleUrls = [...new Set([
|
|
1103
|
+
...(normalizedHydrationData?.roots ?? [])
|
|
948
1104
|
.map((root) => {
|
|
949
1105
|
if (typeof root?.moduleId !== "string" || root.moduleId.length === 0) {
|
|
950
1106
|
return null;
|
|
@@ -953,31 +1109,42 @@ export function createHydrationBootstrap({
|
|
|
953
1109
|
return assetResolver?.(root.moduleId) ?? null;
|
|
954
1110
|
})
|
|
955
1111
|
.filter((moduleUrl) => typeof moduleUrl === "string" && moduleUrl.length > 0),
|
|
1112
|
+
])];
|
|
1113
|
+
const clientImports = [...new Set(
|
|
1114
|
+
(Array.isArray(normalizedHydrationData?.clientImports)
|
|
1115
|
+
? normalizedHydrationData.clientImports
|
|
1116
|
+
: []).filter((moduleUrl) => typeof moduleUrl === "string" && moduleUrl.length > 0),
|
|
956
1117
|
)];
|
|
957
1118
|
|
|
958
|
-
if (
|
|
1119
|
+
if (rootModuleUrls.length === 0 && clientImports.length === 0) {
|
|
959
1120
|
return "";
|
|
960
1121
|
}
|
|
961
1122
|
|
|
962
|
-
const moduleLoaders =
|
|
1123
|
+
const moduleLoaders = rootModuleUrls
|
|
963
1124
|
.map((moduleUrl) => ` () => import(${JSON.stringify(moduleUrl)})`)
|
|
964
1125
|
.join(",\n");
|
|
965
1126
|
|
|
966
1127
|
const source = `
|
|
967
1128
|
import { hydratePage, registerHydrationModules } from ${JSON.stringify(hydrationModuleUrl)};
|
|
1129
|
+
${navigationModuleUrl ? `import { getNavigation } from ${JSON.stringify(navigationModuleUrl)};` : ""}
|
|
968
1130
|
|
|
969
1131
|
await hydratePage({
|
|
970
|
-
clientImports:
|
|
1132
|
+
clientImports: ${JSON.stringify(clientImports)},
|
|
971
1133
|
register: () => registerHydrationModules([
|
|
972
1134
|
${moduleLoaders}
|
|
973
1135
|
])
|
|
974
1136
|
});
|
|
1137
|
+
${navigationModuleUrl ? "getNavigation();" : ""}
|
|
975
1138
|
`;
|
|
976
1139
|
|
|
977
1140
|
return escapeInlineScriptText(source);
|
|
978
1141
|
}
|
|
979
1142
|
|
|
980
|
-
export function normalizeHydrationDataForClient(
|
|
1143
|
+
export function normalizeHydrationDataForClient(
|
|
1144
|
+
hydrationData,
|
|
1145
|
+
projectRoot = null,
|
|
1146
|
+
additionalClientImports = [],
|
|
1147
|
+
) {
|
|
981
1148
|
if (!hydrationData || typeof hydrationData !== "object") {
|
|
982
1149
|
return hydrationData ?? null;
|
|
983
1150
|
}
|
|
@@ -1010,7 +1177,10 @@ export function normalizeHydrationDataForClient(hydrationData, projectRoot = nul
|
|
|
1010
1177
|
roots,
|
|
1011
1178
|
};
|
|
1012
1179
|
const payload = hydrationData.payload;
|
|
1013
|
-
const clientImports =
|
|
1180
|
+
const clientImports = [...new Set([
|
|
1181
|
+
...(Array.isArray(hydrationData.clientImports) ? hydrationData.clientImports : []),
|
|
1182
|
+
...(Array.isArray(additionalClientImports) ? additionalClientImports : []),
|
|
1183
|
+
].filter((value) => typeof value === "string" && value.length > 0))];
|
|
1014
1184
|
|
|
1015
1185
|
Object.defineProperties(normalizedHydrationData, {
|
|
1016
1186
|
payload: {
|
|
@@ -1119,7 +1289,32 @@ function rewriteStaticAssetPlaceholdersWithMap(source, publicPathByRelativePath)
|
|
|
1119
1289
|
}
|
|
1120
1290
|
|
|
1121
1291
|
function rewriteRelativeCssAssetUrls(source, fileRelativePath, publicPathByRelativePath) {
|
|
1122
|
-
|
|
1292
|
+
const rewrittenImports = source.replaceAll(
|
|
1293
|
+
/@import(\s+)(url\(\s*)?(?:(["'])([^"']+)\3|([^\s;)]+))(\s*\))?/g,
|
|
1294
|
+
(match, whitespace, urlPrefix = "", quote = "", quotedSpecifier, unquotedSpecifier, closing = "") => {
|
|
1295
|
+
const specifier = quotedSpecifier ?? unquotedSpecifier;
|
|
1296
|
+
if (!isRelativeSpecifier(specifier)) {
|
|
1297
|
+
return match;
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
const resolvedRelativePath = resolveRelativeClientImportPath(fileRelativePath, specifier);
|
|
1301
|
+
const rewrittenTarget = publicPathByRelativePath.get(resolvedRelativePath);
|
|
1302
|
+
if (!rewrittenTarget) {
|
|
1303
|
+
return match;
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
const cleanSpecifier = stripImportSearchAndHash(specifier);
|
|
1307
|
+
const rewrittenSpecifier = `${normalizeRelativeImportPath(
|
|
1308
|
+
path.relative(
|
|
1309
|
+
path.dirname(publicPathByRelativePath.get(fileRelativePath)),
|
|
1310
|
+
rewrittenTarget,
|
|
1311
|
+
),
|
|
1312
|
+
)}${specifier.slice(cleanSpecifier.length)}`;
|
|
1313
|
+
return `@import${whitespace}${urlPrefix}${quote}${rewrittenSpecifier}${quote}${closing}`;
|
|
1314
|
+
},
|
|
1315
|
+
);
|
|
1316
|
+
|
|
1317
|
+
return rewrittenImports.replaceAll(
|
|
1123
1318
|
/url\(\s*(['"]?)([^"'()]+)\1\s*\)/g,
|
|
1124
1319
|
(match, quote = "", rawSpecifier) => {
|
|
1125
1320
|
const specifier = String(rawSpecifier).trim();
|
|
@@ -1191,9 +1386,7 @@ function collectRelativeClientImportPaths(source, fileRelativePath, publicPathBy
|
|
|
1191
1386
|
continue;
|
|
1192
1387
|
}
|
|
1193
1388
|
|
|
1194
|
-
const resolvedRelativePath =
|
|
1195
|
-
path.join(path.dirname(fileRelativePath), specifier),
|
|
1196
|
-
);
|
|
1389
|
+
const resolvedRelativePath = resolveRelativeClientImportPath(fileRelativePath, specifier);
|
|
1197
1390
|
if (!publicPathByRelativePath.has(resolvedRelativePath)) {
|
|
1198
1391
|
continue;
|
|
1199
1392
|
}
|
|
@@ -1217,9 +1410,7 @@ function rewriteRelativeClientImports(source, fileRelativePath, publicPathByRela
|
|
|
1217
1410
|
continue;
|
|
1218
1411
|
}
|
|
1219
1412
|
|
|
1220
|
-
const resolvedRelativePath =
|
|
1221
|
-
path.join(path.dirname(fileRelativePath), specifier),
|
|
1222
|
-
);
|
|
1413
|
+
const resolvedRelativePath = resolveRelativeClientImportPath(fileRelativePath, specifier);
|
|
1223
1414
|
const rewrittenTarget = publicPathByRelativePath.get(resolvedRelativePath);
|
|
1224
1415
|
if (!rewrittenTarget) {
|
|
1225
1416
|
continue;
|
|
@@ -1324,8 +1515,12 @@ export async function emitHashedClientAssets(projectRoot, options = {}) {
|
|
|
1324
1515
|
if (entry.type === "script") {
|
|
1325
1516
|
try {
|
|
1326
1517
|
const metadata = JSON.parse(await fs.readFile(`${entry.filePath}.meta.json`, "utf8"));
|
|
1327
|
-
styleImports = Array.isArray(metadata?.styleImports) ? metadata.styleImports : []
|
|
1328
|
-
|
|
1518
|
+
styleImports = (Array.isArray(metadata?.styleImports) ? metadata.styleImports : [])
|
|
1519
|
+
.map((importedStyle) => normalizeClientMetadataAssetPath(entry.relativePath, importedStyle))
|
|
1520
|
+
.filter((importedStyle) => typeof importedStyle === "string");
|
|
1521
|
+
assetImports = (Array.isArray(metadata?.assetImports) ? metadata.assetImports : [])
|
|
1522
|
+
.map((importedAsset) => normalizeClientMetadataAssetPath(entry.relativePath, importedAsset))
|
|
1523
|
+
.filter((importedAsset) => typeof importedAsset === "string");
|
|
1329
1524
|
} catch {
|
|
1330
1525
|
styleImports = [];
|
|
1331
1526
|
assetImports = [];
|
|
@@ -1449,7 +1644,9 @@ async function bundleClientAssets(projectRoot, options = {}) {
|
|
|
1449
1644
|
publicPathByRelativePath.set(entry.relativePath, hashedRelativePath);
|
|
1450
1645
|
}
|
|
1451
1646
|
|
|
1452
|
-
|
|
1647
|
+
if (mode !== "development") {
|
|
1648
|
+
await fs.rm(staticRoot, { recursive: true, force: true });
|
|
1649
|
+
}
|
|
1453
1650
|
await ensureDirectory(staticRoot);
|
|
1454
1651
|
|
|
1455
1652
|
const nonScriptAssets = [];
|
|
@@ -1528,17 +1725,36 @@ async function bundleClientAssets(projectRoot, options = {}) {
|
|
|
1528
1725
|
return isBareSpecifier(id);
|
|
1529
1726
|
},
|
|
1530
1727
|
plugins: [
|
|
1728
|
+
{
|
|
1729
|
+
name: "evolit-client-relative-imports",
|
|
1730
|
+
resolveId(source, importer) {
|
|
1731
|
+
if (!importer || !isRelativeSpecifier(source)) {
|
|
1732
|
+
return null;
|
|
1733
|
+
}
|
|
1734
|
+
|
|
1735
|
+
const cleanSource = stripImportSearchAndHash(source);
|
|
1736
|
+
if (cleanSource === source) {
|
|
1737
|
+
return null;
|
|
1738
|
+
}
|
|
1739
|
+
|
|
1740
|
+
return path.resolve(
|
|
1741
|
+
path.dirname(stripImportSearchAndHash(importer)),
|
|
1742
|
+
cleanSource,
|
|
1743
|
+
);
|
|
1744
|
+
},
|
|
1745
|
+
},
|
|
1531
1746
|
{
|
|
1532
1747
|
name: "evolit-client-input-sourcemaps",
|
|
1533
1748
|
async load(id) {
|
|
1534
|
-
|
|
1749
|
+
const filePath = stripImportSearchAndHash(id);
|
|
1750
|
+
if (!filePath.startsWith(clientRoot) || !filePath.endsWith(".mjs")) {
|
|
1535
1751
|
return null;
|
|
1536
1752
|
}
|
|
1537
1753
|
|
|
1538
1754
|
try {
|
|
1539
1755
|
const [code, map] = await Promise.all([
|
|
1540
|
-
fs.readFile(
|
|
1541
|
-
fs.readFile(`${
|
|
1756
|
+
fs.readFile(filePath, "utf8"),
|
|
1757
|
+
fs.readFile(`${filePath}.map`, "utf8"),
|
|
1542
1758
|
]);
|
|
1543
1759
|
return { code, map: JSON.parse(map) };
|
|
1544
1760
|
} catch {
|
|
@@ -1596,9 +1812,14 @@ async function bundleClientAssets(projectRoot, options = {}) {
|
|
|
1596
1812
|
|
|
1597
1813
|
const outputPath = path.join(staticRoot, chunk.fileName);
|
|
1598
1814
|
const publicUrl = toStaticPublicUrl(chunk.fileName);
|
|
1599
|
-
const
|
|
1815
|
+
const entryClientModule = clientModuleByEntryName.get(chunk.name)
|
|
1816
|
+
?? [...clientModuleByEntryName.entries()].find(([entryName]) =>
|
|
1817
|
+
toRollupSafeClientModuleRelativePath(entryName) === chunk.name,
|
|
1818
|
+
)?.[1]
|
|
1819
|
+
?? null;
|
|
1820
|
+
const isNamedEntry = chunk.isEntry && entryClientModule != null;
|
|
1600
1821
|
const clientModule = isNamedEntry
|
|
1601
|
-
?
|
|
1822
|
+
? entryClientModule
|
|
1602
1823
|
: chunk.fileName;
|
|
1603
1824
|
const transitiveMetadata = isNamedEntry
|
|
1604
1825
|
? await collectTransitiveClientModuleMetadata(projectRoot, mode, clientModule)
|
|
@@ -1640,30 +1861,43 @@ async function bundleClientAssets(projectRoot, options = {}) {
|
|
|
1640
1861
|
}
|
|
1641
1862
|
|
|
1642
1863
|
const mapAssets = [];
|
|
1643
|
-
const
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1864
|
+
for (const asset of scriptAssetRecords) {
|
|
1865
|
+
const mapPath = `${asset.outputPath}.map`;
|
|
1866
|
+
try {
|
|
1867
|
+
const stat = await fs.stat(mapPath);
|
|
1868
|
+
const relativePath = path.relative(staticRoot, mapPath).split(path.sep).join("/");
|
|
1869
|
+
const publicUrl = toStaticPublicUrl(relativePath);
|
|
1870
|
+
byPublicPath[publicUrl] = mapPath;
|
|
1871
|
+
mapAssets.push({
|
|
1872
|
+
clientModule: relativePath,
|
|
1873
|
+
type: "asset",
|
|
1874
|
+
kind: "asset",
|
|
1875
|
+
publicUrl,
|
|
1876
|
+
outputPath: mapPath,
|
|
1877
|
+
hash: null,
|
|
1878
|
+
size: stat.size,
|
|
1879
|
+
imports: [],
|
|
1880
|
+
importUrls: [],
|
|
1881
|
+
styleImports: [],
|
|
1882
|
+
styleUrls: [],
|
|
1883
|
+
assetImports: [],
|
|
1884
|
+
assetUrls: [],
|
|
1885
|
+
});
|
|
1886
|
+
} catch {
|
|
1887
|
+
// Source maps are optional in non-development builds.
|
|
1647
1888
|
}
|
|
1889
|
+
}
|
|
1648
1890
|
|
|
1649
|
-
|
|
1650
|
-
const
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
size: (await fs.stat(filePath)).size,
|
|
1660
|
-
imports: [],
|
|
1661
|
-
importUrls: [],
|
|
1662
|
-
styleImports: [],
|
|
1663
|
-
styleUrls: [],
|
|
1664
|
-
assetImports: [],
|
|
1665
|
-
assetUrls: [],
|
|
1666
|
-
});
|
|
1891
|
+
if (mode === "development") {
|
|
1892
|
+
const retainedOutputPaths = new Set(
|
|
1893
|
+
[...scriptAssetRecords, ...nonScriptAssets, ...mapAssets]
|
|
1894
|
+
.map((asset) => asset.outputPath),
|
|
1895
|
+
);
|
|
1896
|
+
for (const filePath of await walkFiles(staticRoot)) {
|
|
1897
|
+
if (!retainedOutputPaths.has(filePath)) {
|
|
1898
|
+
await fs.rm(filePath, { force: true });
|
|
1899
|
+
}
|
|
1900
|
+
}
|
|
1667
1901
|
}
|
|
1668
1902
|
|
|
1669
1903
|
const assets = [...scriptAssetRecords, ...nonScriptAssets, ...mapAssets]
|
|
@@ -1776,6 +2010,28 @@ export function collectTransitiveAssetPreloads(publicUrls, assetManifest) {
|
|
|
1776
2010
|
return discovered;
|
|
1777
2011
|
}
|
|
1778
2012
|
|
|
2013
|
+
export function resolveRouteClientImports(routeResult, projectRoot, assetManifest) {
|
|
2014
|
+
const normalizedManifest = normalizeClientAssetManifest(assetManifest);
|
|
2015
|
+
if (!normalizedManifest) {
|
|
2016
|
+
return [];
|
|
2017
|
+
}
|
|
2018
|
+
|
|
2019
|
+
const routeModules = [
|
|
2020
|
+
routeResult?.route?.page,
|
|
2021
|
+
...(routeResult?.route?.layouts ?? []),
|
|
2022
|
+
routeResult?.boundaryModule,
|
|
2023
|
+
].filter((modulePath) => typeof modulePath === "string");
|
|
2024
|
+
|
|
2025
|
+
return [...new Set(routeModules.map((modulePath) => {
|
|
2026
|
+
const relativePath = path.relative(projectRoot, modulePath).split(path.sep).join("/");
|
|
2027
|
+
const extension = path.extname(relativePath);
|
|
2028
|
+
const clientModule = extension
|
|
2029
|
+
? `${relativePath.slice(0, -extension.length)}.mjs`
|
|
2030
|
+
: `${relativePath}.mjs`;
|
|
2031
|
+
return getClientModulePublicUrl(normalizedManifest, clientModule);
|
|
2032
|
+
}).filter((publicUrl) => typeof publicUrl === "string"))];
|
|
2033
|
+
}
|
|
2034
|
+
|
|
1779
2035
|
export function collectTransitiveStyleUrls(publicUrls, assetManifest) {
|
|
1780
2036
|
const normalizedManifest = normalizeClientAssetManifest(assetManifest);
|
|
1781
2037
|
if (!normalizedManifest) {
|