@remix-run/assets 0.5.0 → 0.7.0
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 +185 -104
- package/dist/assets.d.ts +4 -1
- package/dist/assets.d.ts.map +1 -1
- package/dist/lib/access.d.ts +29 -2
- package/dist/lib/access.d.ts.map +1 -1
- package/dist/lib/access.js +52 -26
- package/dist/lib/asset-server.d.ts +61 -25
- package/dist/lib/asset-server.d.ts.map +1 -1
- package/dist/lib/asset-server.js +127 -55
- package/dist/lib/compilation-error.d.ts +1 -1
- package/dist/lib/compilation-error.d.ts.map +1 -1
- package/dist/lib/files/compiler.d.ts +1 -1
- package/dist/lib/files/compiler.d.ts.map +1 -1
- package/dist/lib/files/compiler.js +28 -31
- package/dist/lib/files/config.d.ts +6 -0
- package/dist/lib/files/config.d.ts.map +1 -1
- package/dist/lib/files/config.js +9 -0
- package/dist/lib/fingerprint.d.ts +0 -4
- package/dist/lib/fingerprint.d.ts.map +1 -1
- package/dist/lib/fingerprint.js +0 -4
- package/dist/lib/hmr.d.ts +7 -0
- package/dist/lib/hmr.d.ts.map +1 -1
- package/dist/lib/hmr.js +198 -25
- package/dist/lib/injected-packages.d.ts +3 -2
- package/dist/lib/injected-packages.d.ts.map +1 -1
- package/dist/lib/injected-packages.js +11 -8
- package/dist/lib/inspection.d.ts +39 -0
- package/dist/lib/inspection.d.ts.map +1 -0
- package/dist/lib/inspection.js +160 -0
- package/dist/lib/routes.d.ts +12 -3
- package/dist/lib/routes.d.ts.map +1 -1
- package/dist/lib/routes.js +124 -80
- package/dist/lib/scripts/compiler.d.ts +8 -2
- package/dist/lib/scripts/compiler.d.ts.map +1 -1
- package/dist/lib/scripts/compiler.js +188 -38
- package/dist/lib/scripts/emit.d.ts +2 -1
- package/dist/lib/scripts/emit.d.ts.map +1 -1
- package/dist/lib/scripts/emit.js +25 -16
- package/dist/lib/scripts/resolve.d.ts +7 -1
- package/dist/lib/scripts/resolve.d.ts.map +1 -1
- package/dist/lib/scripts/resolve.js +119 -12
- package/dist/lib/scripts/specifiers.d.ts +2 -0
- package/dist/lib/scripts/specifiers.d.ts.map +1 -0
- package/dist/lib/scripts/specifiers.js +9 -0
- package/dist/lib/scripts/transform.d.ts +2 -3
- package/dist/lib/scripts/transform.d.ts.map +1 -1
- package/dist/lib/scripts/transform.js +4 -18
- package/dist/lib/styles/compiler.d.ts +0 -1
- package/dist/lib/styles/compiler.d.ts.map +1 -1
- package/dist/lib/styles/compiler.js +105 -25
- package/dist/lib/styles/emit.d.ts +2 -1
- package/dist/lib/styles/emit.d.ts.map +1 -1
- package/dist/lib/styles/emit.js +12 -10
- package/dist/lib/styles/resolve.d.ts +0 -1
- package/dist/lib/styles/resolve.d.ts.map +1 -1
- package/dist/lib/styles/resolve.js +8 -9
- package/dist/lib/styles/transform.d.ts +0 -2
- package/dist/lib/styles/transform.d.ts.map +1 -1
- package/dist/lib/styles/transform.js +2 -9
- package/dist/lib/virtual-store.d.ts +8 -0
- package/dist/lib/virtual-store.d.ts.map +1 -0
- package/dist/lib/virtual-store.js +100 -0
- package/package.json +6 -6
- package/src/assets.ts +9 -1
- package/src/lib/access.ts +83 -30
- package/src/lib/asset-server.ts +224 -94
- package/src/lib/compilation-error.ts +4 -3
- package/src/lib/files/compiler.ts +32 -42
- package/src/lib/files/config.ts +17 -0
- package/src/lib/fingerprint.ts +0 -9
- package/src/lib/hmr.ts +210 -26
- package/src/lib/injected-packages.ts +16 -10
- package/src/lib/inspection.ts +229 -0
- package/src/lib/routes.ts +158 -126
- package/src/lib/scripts/compiler.ts +240 -54
- package/src/lib/scripts/emit.ts +34 -19
- package/src/lib/scripts/resolve.ts +175 -13
- package/src/lib/scripts/specifiers.ts +11 -0
- package/src/lib/scripts/transform.ts +6 -25
- package/src/lib/styles/compiler.ts +137 -39
- package/src/lib/styles/emit.ts +18 -13
- package/src/lib/styles/resolve.ts +8 -10
- package/src/lib/styles/transform.ts +2 -12
- package/src/lib/virtual-store.ts +124 -0
|
@@ -3,6 +3,7 @@ import * as path from 'node:path';
|
|
|
3
3
|
import { createAssetServerCompilationError, isAssetServerCompilationError, } from '../compilation-error.js';
|
|
4
4
|
import { getInjectedPackageNameForSpecifier, getInjectedPackageImporterPath, restoreAuthoredInjectedPackageSpecifier, } from '../injected-packages.js';
|
|
5
5
|
import { normalizeFilePath } from '../paths.js';
|
|
6
|
+
import { isBareImportSpecifier } from './specifiers.js';
|
|
6
7
|
export const resolverExtensionAlias = {
|
|
7
8
|
'.js': ['.js', '.ts', '.tsx', '.jsx'],
|
|
8
9
|
'.jsx': ['.jsx', '.tsx'],
|
|
@@ -27,15 +28,17 @@ export async function resolveModule(record, transformed, args) {
|
|
|
27
28
|
});
|
|
28
29
|
}
|
|
29
30
|
let importsWithPaths = [];
|
|
31
|
+
let pendingBareImportScopes = [];
|
|
30
32
|
let acceptedDepsWithPaths = [];
|
|
31
33
|
let deps = new Set();
|
|
34
|
+
let staticDeps = new Set();
|
|
32
35
|
for (let unresolved of transformed.unresolvedImports) {
|
|
33
36
|
let displaySpecifier = getDisplayImportSpecifier(unresolved.specifier);
|
|
34
37
|
let trackedResolution = getTrackedRelativeImportResolution(transformed.importerDir, displaySpecifier, args.isWatchIgnored);
|
|
35
38
|
let resolvedSpec = resolvedImports.get(unresolved.specifier);
|
|
36
39
|
if (!resolvedSpec?.absolutePath) {
|
|
37
40
|
return failResolve(createAssetServerCompilationError(`Failed to resolve import "${displaySpecifier}" in ${transformed.resolvedPath}. ` +
|
|
38
|
-
`Ensure it resolves to a file within
|
|
41
|
+
`Ensure it resolves to a file within a configured asset server mount, or mark it as external.`, {
|
|
39
42
|
code: 'IMPORT_RESOLUTION_FAILED',
|
|
40
43
|
}), trackedFiles, trackedResolutions, transformed.resolvedPath, { isWatchIgnored: args.isWatchIgnored, trackedResolution });
|
|
41
44
|
}
|
|
@@ -54,12 +57,14 @@ export async function resolveModule(record, transformed, args) {
|
|
|
54
57
|
}
|
|
55
58
|
let stableUrlPathname = args.routes.toUrlPathname(resolvedImport.identityPath);
|
|
56
59
|
if (!stableUrlPathname) {
|
|
57
|
-
return failResolve(createAssetServerCompilationError(`Import "${displaySpecifier}" in ${transformed.resolvedPath}, resolved to "${resolvedImport.identityPath}", is outside all configured
|
|
58
|
-
`Add a matching
|
|
59
|
-
code: '
|
|
60
|
+
return failResolve(createAssetServerCompilationError(`Import "${displaySpecifier}" in ${transformed.resolvedPath}, resolved to "${resolvedImport.identityPath}", is outside all configured mounts. ` +
|
|
61
|
+
`Add a matching mount for this file path, or mark this import as external.`, {
|
|
62
|
+
code: 'IMPORT_OUTSIDE_MOUNTS',
|
|
60
63
|
}), trackedFiles, trackedResolutions, transformed.resolvedPath, { isWatchIgnored: args.isWatchIgnored, trackedResolution });
|
|
61
64
|
}
|
|
62
65
|
deps.add(resolvedImport.identityPath);
|
|
66
|
+
if (!unresolved.dynamic)
|
|
67
|
+
staticDeps.add(resolvedImport.identityPath);
|
|
63
68
|
if (transformed.packageSpecifiers.includes(unresolved.specifier)) {
|
|
64
69
|
let packageJsonPath = resolvedSpec.packageJsonPath ?? findNearestPackageJsonPath(resolvedImport.resolvedPath);
|
|
65
70
|
if (packageJsonPath && !args.isWatchIgnored(packageJsonPath)) {
|
|
@@ -72,12 +77,38 @@ export async function resolveModule(record, transformed, args) {
|
|
|
72
77
|
resolvedIdentityPath: resolvedImport.identityPath,
|
|
73
78
|
});
|
|
74
79
|
}
|
|
75
|
-
|
|
80
|
+
let imported = {
|
|
81
|
+
compiledSpecifier: unresolved.specifier,
|
|
76
82
|
depPath: resolvedImport.identityPath,
|
|
77
83
|
end: unresolved.end,
|
|
78
84
|
quote: unresolved.quote,
|
|
85
|
+
specifier: displaySpecifier,
|
|
79
86
|
start: unresolved.start,
|
|
80
|
-
}
|
|
87
|
+
};
|
|
88
|
+
importsWithPaths.push(imported);
|
|
89
|
+
if (isBareImportSpecifier(displaySpecifier)) {
|
|
90
|
+
pendingBareImportScopes.push({
|
|
91
|
+
imported,
|
|
92
|
+
resolvedIdentityPath: resolvedImport.identityPath,
|
|
93
|
+
specifier: normalizeSpecifierResolution(unresolved.specifier, transformed.resolvedPath)
|
|
94
|
+
.specifier,
|
|
95
|
+
trackedResolution,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (pendingBareImportScopes.length > 0) {
|
|
100
|
+
let scopeResults = await resolveBareImportScopes(pendingBareImportScopes, transformed.resolvedPath, args);
|
|
101
|
+
for (let index = 0; index < scopeResults.length; index++) {
|
|
102
|
+
let result = scopeResults[index];
|
|
103
|
+
let pending = pendingBareImportScopes[index];
|
|
104
|
+
if (!result.ok) {
|
|
105
|
+
return failResolve(result.error, trackedFiles, trackedResolutions, transformed.resolvedPath, {
|
|
106
|
+
isWatchIgnored: args.isWatchIgnored,
|
|
107
|
+
trackedResolution: pending.trackedResolution,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
pending.imported.scopePathname = result.scopePathname;
|
|
111
|
+
}
|
|
81
112
|
}
|
|
82
113
|
for (let unresolved of transformed.hmr.acceptedDeps) {
|
|
83
114
|
if (isBrowserExternalModuleUrl(unresolved.specifier))
|
|
@@ -98,7 +129,7 @@ export async function resolveModule(record, transformed, args) {
|
|
|
98
129
|
}
|
|
99
130
|
if (!resolvedSpec?.absolutePath) {
|
|
100
131
|
return failResolve(createAssetServerCompilationError(`Failed to resolve accepted HMR dependency "${displaySpecifier}" in ${transformed.resolvedPath}. ` +
|
|
101
|
-
`Ensure it resolves to a file within
|
|
132
|
+
`Ensure it resolves to a file within a configured asset server mount, or mark it as external.`, {
|
|
102
133
|
code: 'IMPORT_RESOLUTION_FAILED',
|
|
103
134
|
}), trackedFiles, trackedResolutions, transformed.resolvedPath, { isWatchIgnored: args.isWatchIgnored, trackedResolution });
|
|
104
135
|
}
|
|
@@ -117,9 +148,9 @@ export async function resolveModule(record, transformed, args) {
|
|
|
117
148
|
}
|
|
118
149
|
let stableUrlPathname = args.routes.toUrlPathname(resolvedImport.identityPath);
|
|
119
150
|
if (!stableUrlPathname) {
|
|
120
|
-
return failResolve(createAssetServerCompilationError(`Accepted HMR dependency "${displaySpecifier}" in ${transformed.resolvedPath}, resolved to "${resolvedImport.identityPath}", is outside all configured
|
|
121
|
-
`Add a matching
|
|
122
|
-
code: '
|
|
151
|
+
return failResolve(createAssetServerCompilationError(`Accepted HMR dependency "${displaySpecifier}" in ${transformed.resolvedPath}, resolved to "${resolvedImport.identityPath}", is outside all configured mounts. ` +
|
|
152
|
+
`Add a matching mount for this file path, or mark this import as external.`, {
|
|
153
|
+
code: 'IMPORT_OUTSIDE_MOUNTS',
|
|
123
154
|
}), trackedFiles, trackedResolutions, transformed.resolvedPath, { isWatchIgnored: args.isWatchIgnored, trackedResolution });
|
|
124
155
|
}
|
|
125
156
|
if (trackedResolution) {
|
|
@@ -129,9 +160,11 @@ export async function resolveModule(record, transformed, args) {
|
|
|
129
160
|
});
|
|
130
161
|
}
|
|
131
162
|
acceptedDepsWithPaths.push({
|
|
163
|
+
compiledSpecifier: unresolved.specifier,
|
|
132
164
|
depPath: resolvedImport.identityPath,
|
|
133
165
|
end: unresolved.end,
|
|
134
166
|
quote: unresolved.quote,
|
|
167
|
+
specifier: displaySpecifier,
|
|
135
168
|
start: unresolved.start,
|
|
136
169
|
});
|
|
137
170
|
}
|
|
@@ -140,7 +173,6 @@ export async function resolveModule(record, transformed, args) {
|
|
|
140
173
|
tracking: toResolveTracking(trackedFiles, trackedResolutions),
|
|
141
174
|
value: {
|
|
142
175
|
deps: [...deps],
|
|
143
|
-
fingerprint: transformed.fingerprint,
|
|
144
176
|
hmr: {
|
|
145
177
|
acceptedDeps: acceptedDepsWithPaths,
|
|
146
178
|
selfAccepting: transformed.hmr.selfAccepting,
|
|
@@ -152,10 +184,85 @@ export async function resolveModule(record, transformed, args) {
|
|
|
152
184
|
rawCode: transformed.rawCode,
|
|
153
185
|
resolvedPath: transformed.resolvedPath,
|
|
154
186
|
sourceMap: transformed.sourceMap,
|
|
187
|
+
staticDeps: [...staticDeps],
|
|
155
188
|
stableUrlPathname: transformed.stableUrlPathname,
|
|
156
189
|
},
|
|
157
190
|
};
|
|
158
191
|
}
|
|
192
|
+
async function resolveBareImportScopes(pendingScopes, importerPath, args) {
|
|
193
|
+
let results = new Array(pendingScopes.length);
|
|
194
|
+
let nextIndex = 0;
|
|
195
|
+
async function worker() {
|
|
196
|
+
while (nextIndex < pendingScopes.length) {
|
|
197
|
+
let index = nextIndex++;
|
|
198
|
+
let pending = pendingScopes[index];
|
|
199
|
+
try {
|
|
200
|
+
results[index] = {
|
|
201
|
+
ok: true,
|
|
202
|
+
scopePathname: await getBareImportScopePathname({
|
|
203
|
+
importerPath,
|
|
204
|
+
resolvedIdentityPath: pending.resolvedIdentityPath,
|
|
205
|
+
specifier: pending.specifier,
|
|
206
|
+
...args,
|
|
207
|
+
}),
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
results[index] = {
|
|
212
|
+
ok: false,
|
|
213
|
+
error: isAssetServerCompilationError(error)
|
|
214
|
+
? error
|
|
215
|
+
: createAssetServerCompilationError(`Failed to determine an import map scope for "${pending.imported.specifier}" in ${importerPath}. ${formatUnknownError(error)}`, { cause: error, code: 'IMPORT_RESOLUTION_FAILED' }),
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
if (pendingScopes.length === 1) {
|
|
221
|
+
await worker();
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
await Promise.all(Array.from({ length: Math.min(args.concurrency, pendingScopes.length) }, () => worker()));
|
|
225
|
+
}
|
|
226
|
+
return results;
|
|
227
|
+
}
|
|
228
|
+
async function getBareImportScopePathname(args) {
|
|
229
|
+
let importerDirectory = normalizeFilePath(path.dirname(args.importerPath));
|
|
230
|
+
let importerScopePathname = args.routes.toUrlPathname(importerDirectory);
|
|
231
|
+
if (!importerScopePathname) {
|
|
232
|
+
throw new Error(`Expected a URL pathname for ${importerDirectory}`);
|
|
233
|
+
}
|
|
234
|
+
let importerDirectoryResolution = args.resolvedIdentityPath;
|
|
235
|
+
if (!args.isDirectoryResolutionFileIndependent(importerDirectory)) {
|
|
236
|
+
importerDirectoryResolution = await args.resolveDirectorySpecifierIdentity(importerDirectory, args.specifier);
|
|
237
|
+
if (importerDirectoryResolution !== args.resolvedIdentityPath) {
|
|
238
|
+
throw createAssetServerCompilationError(`Bare import "${args.specifier}" in ${args.importerPath} resolves differently based on the importer file. ` +
|
|
239
|
+
`Browser module resolution must be uniform for all files in the same directory.`, { code: 'IMPORT_RESOLUTION_NOT_DIRECTORY_UNIFORM' });
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
let directory = importerDirectory;
|
|
243
|
+
let scopePathname = importerScopePathname;
|
|
244
|
+
let broadestScopePathname = importerScopePathname;
|
|
245
|
+
while (true) {
|
|
246
|
+
let resolvedIdentityPath = directory === importerDirectory
|
|
247
|
+
? importerDirectoryResolution
|
|
248
|
+
: await args.resolveDirectorySpecifierIdentity(directory, args.specifier);
|
|
249
|
+
if (resolvedIdentityPath !== args.resolvedIdentityPath)
|
|
250
|
+
break;
|
|
251
|
+
broadestScopePathname = scopePathname;
|
|
252
|
+
let parentDirectory = normalizeFilePath(path.dirname(directory));
|
|
253
|
+
if (parentDirectory === directory)
|
|
254
|
+
break;
|
|
255
|
+
let parentScopePathname = args.routes.toUrlPathname(parentDirectory);
|
|
256
|
+
if (!parentScopePathname)
|
|
257
|
+
break;
|
|
258
|
+
directory = parentDirectory;
|
|
259
|
+
scopePathname = parentScopePathname;
|
|
260
|
+
}
|
|
261
|
+
return ensureTrailingSlash(broadestScopePathname);
|
|
262
|
+
}
|
|
263
|
+
function ensureTrailingSlash(value) {
|
|
264
|
+
return value.endsWith('/') ? value : `${value}/`;
|
|
265
|
+
}
|
|
159
266
|
function findNearestPackageJsonPath(filePath) {
|
|
160
267
|
let directory = path.dirname(filePath);
|
|
161
268
|
while (true) {
|
|
@@ -234,7 +341,7 @@ async function batchResolveSpecifiers(specifiers, importerPath, resolverFactory)
|
|
|
234
341
|
throw createAssetServerCompilationError(normalizedResolution.importerPath === getInjectedPackageImporterPath()
|
|
235
342
|
? `Failed to resolve injected import "${specifier}" from asset server.`
|
|
236
343
|
: `Failed to resolve import "${normalizedResolution.specifier}" in ${normalizedResolution.importerPath}. ` +
|
|
237
|
-
`Ensure it resolves to a file within
|
|
344
|
+
`Ensure it resolves to a file within a configured asset server mount, or mark it as external.`, {
|
|
238
345
|
code: 'IMPORT_RESOLUTION_FAILED',
|
|
239
346
|
});
|
|
240
347
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"specifiers.d.ts","sourceRoot":"","sources":["../../../src/lib/scripts/specifiers.ts"],"names":[],"mappings":"AAAA,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAUhE"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export function isBareImportSpecifier(specifier) {
|
|
2
|
+
return (!specifier.startsWith('./') &&
|
|
3
|
+
!specifier.startsWith('../') &&
|
|
4
|
+
!specifier.startsWith('/') &&
|
|
5
|
+
!specifier.startsWith('file:') &&
|
|
6
|
+
!specifier.startsWith('data:') &&
|
|
7
|
+
!specifier.startsWith('http://') &&
|
|
8
|
+
!specifier.startsWith('https://'));
|
|
9
|
+
}
|
|
@@ -12,14 +12,14 @@ export type ResolveModuleResult = {
|
|
|
12
12
|
resolvedPath: string;
|
|
13
13
|
};
|
|
14
14
|
type UnresolvedImport = {
|
|
15
|
+
dynamic: boolean;
|
|
15
16
|
end: number;
|
|
16
17
|
quote?: '"' | "'" | '`';
|
|
17
18
|
specifier: string;
|
|
18
19
|
start: number;
|
|
19
20
|
};
|
|
20
|
-
type HmrAcceptedDependency = UnresolvedImport
|
|
21
|
+
type HmrAcceptedDependency = Omit<UnresolvedImport, 'dynamic'>;
|
|
21
22
|
export type TransformedModule = {
|
|
22
|
-
fingerprint: string | null;
|
|
23
23
|
hmr: {
|
|
24
24
|
acceptedDeps: HmrAcceptedDependency[];
|
|
25
25
|
selfAccepting: boolean;
|
|
@@ -50,7 +50,6 @@ type TsconfigTransformOptions = {
|
|
|
50
50
|
};
|
|
51
51
|
type TsconfigTransformOptionsResolver = ReturnType<typeof createTsconfigTransformOptionsResolver>;
|
|
52
52
|
export type TransformArgs = {
|
|
53
|
-
buildId: string | null;
|
|
54
53
|
define: Record<string, string> | null;
|
|
55
54
|
externalSet: ReadonlySet<string>;
|
|
56
55
|
isWatchIgnored(filePath: string): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../../src/lib/scripts/transform.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAS,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAS/D,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAA;
|
|
1
|
+
{"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../../src/lib/scripts/transform.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAS,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAS/D,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAA;AAM1E,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACtE,OAAO,KAAK,EAEV,YAAY,EAGb,MAAM,eAAe,CAAA;AAEtB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAElD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAC9C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAIlD,KAAK,YAAY,GAAG,YAAY,CAAC,iBAAiB,EAAE,cAAc,EAAE,aAAa,CAAC,CAAA;AA6BlF,MAAM,MAAM,mBAAmB,GAAG;IAChC,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,KAAK,gBAAgB,GAAG;IACtB,OAAO,EAAE,OAAO,CAAA;IAChB,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,CAAC,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;IACvB,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,KAAK,qBAAqB,GAAG,IAAI,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAAA;AAE9D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,GAAG,EAAE;QACH,YAAY,EAAE,qBAAqB,EAAE,CAAA;QACrC,aAAa,EAAE,OAAO,CAAA;QACtB,iBAAiB,EAAE,OAAO,CAAA;KAC3B,CAAA;IACD,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,iBAAiB,EAAE,MAAM,EAAE,CAAA;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,iBAAiB,EAAE,MAAM,CAAA;IACzB,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,iBAAiB,EAAE,gBAAgB,EAAE,CAAA;CACtC,CAAA;AAED,KAAK,eAAe,GAAG;IACrB,QAAQ,EAAE,cAAc,CAAA;CACzB,GAAG,CACA;IACE,EAAE,EAAE,IAAI,CAAA;IACR,KAAK,EAAE,iBAAiB,CAAA;CACzB,GACD;IACE,EAAE,EAAE,KAAK,CAAA;IACT,KAAK,EAAE,2BAA2B,CAAA;CACnC,CACJ,CAAA;AAED,KAAK,wBAAwB,GAAG;IAC9B,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,WAAW,CAAC,EAAE,oBAAoB,CAAA;CACnC,CAAA;AAED,KAAK,gCAAgC,GAAG,UAAU,CAAC,OAAO,sCAAsC,CAAC,CAAA;AAEjG,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAA;IACrC,WAAW,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;IAChC,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAA;IACzC,MAAM,EAAE,OAAO,CAAA;IACf,OAAO,EAAE,SAAS,YAAY,EAAE,CAAA;IAChC,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IACtD,MAAM,EAAE,cAAc,CAAA;IACtB,oBAAoB,EAAE,UAAU,GAAG,KAAK,CAAA;IACxC,UAAU,EAAE,UAAU,GAAG,QAAQ,GAAG,IAAI,CAAA;IACxC,MAAM,EAAE,oBAAoB,GAAG,IAAI,CAAA;IACnC,gCAAgC,EAAE,gCAAgC,CAAA;CACnE,CAAA;AAED,wBAAgB,sCAAsC;IAKlD,KAAK;IAIL,mBAAmB,WACP,MAAM,kBACA,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,GAC5C,wBAAwB;EAsB9B;AAED,wBAAsB,eAAe,CACnC,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,eAAe,CAAC,CAyH1B;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAuDxE"}
|
|
@@ -10,11 +10,11 @@ import { transform as oxcTransform } from 'oxc-transform';
|
|
|
10
10
|
import { init as esModuleLexerInit, parse as esModuleLexer } from 'es-module-lexer';
|
|
11
11
|
import { isCommonJS, mayContainCommonJSModuleGlobals } from './cjs-check.js';
|
|
12
12
|
import { createAssetServerCompilationError, isAssetServerCompilationError, } from '../compilation-error.js';
|
|
13
|
-
import { generateFingerprint } from '../fingerprint.js';
|
|
14
13
|
import { maskAuthoredInjectedPackageSpecifier, mayContainInjectedPackageSpecifier, restoreAuthoredInjectedPackageSpecifier, } from '../injected-packages.js';
|
|
15
14
|
import { normalizeFilePath } from '../paths.js';
|
|
16
15
|
import { composeSourceMaps, rewriteSourceMapSources, stringifySourceMap } from '../source-maps.js';
|
|
17
16
|
import { scriptLoaderConditions } from './conditions.js';
|
|
17
|
+
import { isBareImportSpecifier } from './specifiers.js';
|
|
18
18
|
const scriptModuleTypes = [
|
|
19
19
|
{ extension: '.js', lang: 'js' },
|
|
20
20
|
{ extension: '.jsx', lang: 'jsx' },
|
|
@@ -109,8 +109,8 @@ export async function transformModule(record, args) {
|
|
|
109
109
|
try {
|
|
110
110
|
let stableUrlPathname = args.routes.toUrlPathname(record.identityPath);
|
|
111
111
|
if (!stableUrlPathname) {
|
|
112
|
-
throw createAssetServerCompilationError(`File ${record.identityPath} is outside all configured
|
|
113
|
-
code: '
|
|
112
|
+
throw createAssetServerCompilationError(`File ${record.identityPath} is outside all configured mounts.`, {
|
|
113
|
+
code: 'FILE_OUTSIDE_MOUNTS',
|
|
114
114
|
});
|
|
115
115
|
}
|
|
116
116
|
let analysis = await analyzeModuleSource(sourceText, resolvedPath, transformOptions, {
|
|
@@ -138,12 +138,6 @@ export async function transformModule(record, args) {
|
|
|
138
138
|
trackedFiles,
|
|
139
139
|
},
|
|
140
140
|
value: {
|
|
141
|
-
fingerprint: args.buildId === null
|
|
142
|
-
? null
|
|
143
|
-
: await generateFingerprint({
|
|
144
|
-
buildId: args.buildId,
|
|
145
|
-
content: sourceText,
|
|
146
|
-
}),
|
|
147
141
|
hmr: getHmrAnalysis(analysis.rawCode),
|
|
148
142
|
identityPath: record.identityPath,
|
|
149
143
|
importerDir: path.dirname(resolvedPath),
|
|
@@ -281,15 +275,6 @@ function findNearestTsconfigPath(directory) {
|
|
|
281
275
|
currentDirectory = parentDirectory;
|
|
282
276
|
}
|
|
283
277
|
}
|
|
284
|
-
function isBareImportSpecifier(specifier) {
|
|
285
|
-
return (!specifier.startsWith('./') &&
|
|
286
|
-
!specifier.startsWith('../') &&
|
|
287
|
-
!specifier.startsWith('/') &&
|
|
288
|
-
!specifier.startsWith('file:') &&
|
|
289
|
-
!specifier.startsWith('data:') &&
|
|
290
|
-
!specifier.startsWith('http://') &&
|
|
291
|
-
!specifier.startsWith('https://'));
|
|
292
|
-
}
|
|
293
278
|
async function analyzeModuleSource(sourceText, resolvedPath, transformOptions, options) {
|
|
294
279
|
let maskedSourceText = maskAuthoredInjectedPackageImports(sourceText, resolvedPath);
|
|
295
280
|
let transformResult;
|
|
@@ -533,6 +518,7 @@ async function getUnresolvedImportsFromLexer(rawCode) {
|
|
|
533
518
|
if (specifier == null || isBrowserExternalModuleUrl(specifier))
|
|
534
519
|
continue;
|
|
535
520
|
unresolvedImports.push({
|
|
521
|
+
dynamic: imported.d !== -1,
|
|
536
522
|
specifier,
|
|
537
523
|
start: imported.s,
|
|
538
524
|
end: imported.e,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../../../src/lib/styles/compiler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../../../src/lib/styles/compiler.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@ import * as os from 'node:os';
|
|
|
2
2
|
import * as path from 'node:path';
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
4
|
import { IfNoneMatch } from '@remix-run/headers/if-none-match';
|
|
5
|
+
import { createAssetServerCompilationError } from '../compilation-error.js';
|
|
5
6
|
import { createFileMatcher } from '../file-matcher.js';
|
|
6
7
|
import { formatFingerprintedPathname } from '../fingerprint.js';
|
|
7
8
|
import { createModuleStore } from '../module-store.js';
|
|
@@ -32,7 +33,6 @@ export function createStyleCompiler(options) {
|
|
|
32
33
|
routes: resolvedOptions.routes,
|
|
33
34
|
};
|
|
34
35
|
let transformArgs = {
|
|
35
|
-
buildId: resolvedOptions.buildId ?? null,
|
|
36
36
|
isWatchIgnored,
|
|
37
37
|
minify: resolvedOptions.minify,
|
|
38
38
|
routes: resolvedOptions.routes,
|
|
@@ -43,7 +43,8 @@ export function createStyleCompiler(options) {
|
|
|
43
43
|
return {
|
|
44
44
|
async getHref(filePath) {
|
|
45
45
|
let resolvedStyle = resolveServedStyleOrThrow(resolveInputFilePath(filePath), resolveArgs);
|
|
46
|
-
|
|
46
|
+
let graph = await resolveStyleGraph(resolvedStyle.identityPath);
|
|
47
|
+
return getServedUrlFromGraph(resolvedStyle.identityPath, graph);
|
|
47
48
|
},
|
|
48
49
|
async getPreloadLayers(filePath) {
|
|
49
50
|
let resolvedEntries = [];
|
|
@@ -57,13 +58,17 @@ export function createStyleCompiler(options) {
|
|
|
57
58
|
let visited = new Set(resolvedEntries);
|
|
58
59
|
let queue = [...resolvedEntries];
|
|
59
60
|
let layers = [];
|
|
61
|
+
let graph = await resolveStyleGraph(resolvedEntries);
|
|
60
62
|
while (queue.length > 0) {
|
|
61
63
|
let frontier = queue;
|
|
62
64
|
queue = [];
|
|
63
|
-
let resolvedStyles = await getOrCreateResolvedStyles(frontier.map((identityPath) => styleStore.get(identityPath)));
|
|
64
65
|
let layer = [];
|
|
65
|
-
for (let
|
|
66
|
-
|
|
66
|
+
for (let identityPath of frontier) {
|
|
67
|
+
let graphEntry = graph.get(identityPath);
|
|
68
|
+
if (!graphEntry)
|
|
69
|
+
throw new Error(`Missing resolved style ${identityPath}`);
|
|
70
|
+
let resolvedStyle = graphEntry.resolvedStyle;
|
|
71
|
+
layer.push(await getServedUrlFromGraph(identityPath, graph));
|
|
67
72
|
for (let dep of resolvedStyle.deps) {
|
|
68
73
|
if (visited.has(dep))
|
|
69
74
|
continue;
|
|
@@ -119,9 +124,6 @@ export function createStyleCompiler(options) {
|
|
|
119
124
|
}
|
|
120
125
|
return resolveFilePath(resolvedOptions.rootDir, filePath);
|
|
121
126
|
}
|
|
122
|
-
async function getOrCreateResolvedStyles(records) {
|
|
123
|
-
return mapWithConcurrency(records, preloadConcurrency, (record) => getOrCreateResolvedStyle(record));
|
|
124
|
-
}
|
|
125
127
|
async function getOrCreateResolvedStyle(record) {
|
|
126
128
|
if (record.resolved && styleStore.isResolvedFresh(record))
|
|
127
129
|
return record.resolved;
|
|
@@ -180,22 +182,37 @@ export function createStyleCompiler(options) {
|
|
|
180
182
|
!hasHmrTimestampedDependency(record.resolved)) {
|
|
181
183
|
return record.emitted;
|
|
182
184
|
}
|
|
183
|
-
let
|
|
185
|
+
let graph = await resolveStyleGraph(record.identityPath);
|
|
186
|
+
return getOrCreateEmittedStyleFromGraph(record, graph);
|
|
187
|
+
}
|
|
188
|
+
async function getOrCreateEmittedStyleFromGraph(record, graph) {
|
|
189
|
+
let graphEntry = graph.get(record.identityPath);
|
|
190
|
+
if (!graphEntry) {
|
|
191
|
+
throw new Error(`Missing resolved style ${record.identityPath}`);
|
|
192
|
+
}
|
|
193
|
+
if (record.invalidationVersion === graphEntry.invalidationVersion &&
|
|
194
|
+
record.emitted &&
|
|
195
|
+
styleStore.isEmittedFresh(record) &&
|
|
196
|
+
!hasHmrTimestampedDependency(record.resolved)) {
|
|
197
|
+
return record.emitted;
|
|
198
|
+
}
|
|
199
|
+
let cacheKey = getCacheKey(record.identityPath, graphEntry.invalidationVersion);
|
|
184
200
|
let existing = emitInFlightByCacheKey.get(cacheKey);
|
|
185
201
|
if (existing)
|
|
186
202
|
return existing;
|
|
187
203
|
let promise = (async () => {
|
|
188
|
-
let
|
|
189
|
-
|
|
190
|
-
let emitResolvedStyleResult = await emitResolvedStyle(resolvedStyle, {
|
|
204
|
+
let emitResolvedStyleResult = await emitResolvedStyle(graphEntry.resolvedStyle, {
|
|
205
|
+
fingerprintAssets: resolvedOptions.fingerprintAssets,
|
|
191
206
|
getServedFileUrl: resolvedOptions.getServedFileUrl,
|
|
192
|
-
getServedUrl
|
|
207
|
+
getServedUrl(identityPath) {
|
|
208
|
+
return getServedUrlFromGraph(identityPath, graph);
|
|
209
|
+
},
|
|
193
210
|
sourceMaps: resolvedOptions.sourceMaps,
|
|
194
211
|
});
|
|
195
212
|
if (!emitResolvedStyleResult.ok) {
|
|
196
213
|
throw emitResolvedStyleResult.error;
|
|
197
214
|
}
|
|
198
|
-
if (isFresh(record,
|
|
215
|
+
if (isFresh(record, graphEntry.invalidationVersion)) {
|
|
199
216
|
styleStore.setEmitted(record.identityPath, emitResolvedStyleResult.value, null);
|
|
200
217
|
}
|
|
201
218
|
return emitResolvedStyleResult.value;
|
|
@@ -210,14 +227,75 @@ export function createStyleCompiler(options) {
|
|
|
210
227
|
}
|
|
211
228
|
}
|
|
212
229
|
}
|
|
213
|
-
async function
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
let pathname =
|
|
218
|
-
|
|
230
|
+
async function getServedUrlFromGraph(identityPath, graph) {
|
|
231
|
+
let graphEntry = graph.get(identityPath);
|
|
232
|
+
if (!graphEntry)
|
|
233
|
+
throw new Error(`Missing resolved style ${identityPath}`);
|
|
234
|
+
let pathname = graphEntry.resolvedStyle.stableUrlPathname;
|
|
235
|
+
if (resolvedOptions.fingerprintAssets) {
|
|
236
|
+
let emittedStyle = await getOrCreateEmittedStyleFromGraph(styleStore.get(identityPath), graph);
|
|
237
|
+
pathname = formatFingerprintedPathname(graphEntry.resolvedStyle.stableUrlPathname, emittedStyle.fingerprint);
|
|
238
|
+
}
|
|
239
|
+
let timestamp = styleStore.getHmrUpdateTimestamp(graphEntry.resolvedStyle.identityPath);
|
|
219
240
|
return timestamp ? appendTimestamp(pathname, timestamp) : pathname;
|
|
220
241
|
}
|
|
242
|
+
async function resolveStyleGraph(rootPath) {
|
|
243
|
+
let resolvedByPath = new Map();
|
|
244
|
+
let rootPaths = Array.isArray(rootPath) ? rootPath : [rootPath];
|
|
245
|
+
let discovered = new Set(rootPaths);
|
|
246
|
+
let queue = [...rootPaths];
|
|
247
|
+
while (queue.length > 0) {
|
|
248
|
+
let frontier = queue;
|
|
249
|
+
queue = [];
|
|
250
|
+
let graphEntries = await mapWithConcurrency(frontier, preloadConcurrency, async (identityPath) => {
|
|
251
|
+
let record = styleStore.get(identityPath);
|
|
252
|
+
let invalidationVersion = record.invalidationVersion;
|
|
253
|
+
let resolvedStyle = await getOrCreateResolvedStyle(record);
|
|
254
|
+
return {
|
|
255
|
+
invalidationVersion,
|
|
256
|
+
resolvedStyle,
|
|
257
|
+
};
|
|
258
|
+
});
|
|
259
|
+
for (let [index, identityPath] of frontier.entries()) {
|
|
260
|
+
let graphEntry = graphEntries[index];
|
|
261
|
+
resolvedByPath.set(identityPath, graphEntry);
|
|
262
|
+
for (let depPath of graphEntry.resolvedStyle.deps) {
|
|
263
|
+
if (discovered.has(depPath))
|
|
264
|
+
continue;
|
|
265
|
+
discovered.add(depPath);
|
|
266
|
+
queue.push(depPath);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
assertNoCircularImports(resolvedByPath, rootPaths);
|
|
271
|
+
return resolvedByPath;
|
|
272
|
+
}
|
|
273
|
+
function assertNoCircularImports(graph, rootPaths) {
|
|
274
|
+
let visited = new Set();
|
|
275
|
+
let path = [];
|
|
276
|
+
let pathIndexByIdentity = new Map();
|
|
277
|
+
function visit(identityPath) {
|
|
278
|
+
let cycleStart = pathIndexByIdentity.get(identityPath);
|
|
279
|
+
if (cycleStart !== undefined) {
|
|
280
|
+
let cycle = [...path.slice(cycleStart), identityPath];
|
|
281
|
+
throw createAssetServerCompilationError(`Circular CSS imports are not supported: ${cycle.join(' -> ')}`, { code: 'EMIT_FAILED' });
|
|
282
|
+
}
|
|
283
|
+
if (visited.has(identityPath))
|
|
284
|
+
return;
|
|
285
|
+
let graphEntry = graph.get(identityPath);
|
|
286
|
+
if (!graphEntry)
|
|
287
|
+
throw new Error(`Missing resolved style ${identityPath}`);
|
|
288
|
+
pathIndexByIdentity.set(identityPath, path.length);
|
|
289
|
+
path.push(identityPath);
|
|
290
|
+
for (let depPath of graphEntry.resolvedStyle.deps)
|
|
291
|
+
visit(depPath);
|
|
292
|
+
path.pop();
|
|
293
|
+
pathIndexByIdentity.delete(identityPath);
|
|
294
|
+
visited.add(identityPath);
|
|
295
|
+
}
|
|
296
|
+
for (let identityPath of rootPaths)
|
|
297
|
+
visit(identityPath);
|
|
298
|
+
}
|
|
221
299
|
function getHmrUpdatePathnames(identityPath, timestamp) {
|
|
222
300
|
let resolvedStyles = findHmrUpdateStyles(identityPath, new Set());
|
|
223
301
|
// Mark update timestamps before invalidating so re-emitted importer stylesheets
|
|
@@ -251,7 +329,10 @@ export function createStyleCompiler(options) {
|
|
|
251
329
|
}
|
|
252
330
|
}
|
|
253
331
|
function getRecordCacheKey(record) {
|
|
254
|
-
return
|
|
332
|
+
return getCacheKey(record.identityPath, record.invalidationVersion);
|
|
333
|
+
}
|
|
334
|
+
function getCacheKey(identityPath, version) {
|
|
335
|
+
return `${identityPath}\0${version}`;
|
|
255
336
|
}
|
|
256
337
|
function isFresh(record, version) {
|
|
257
338
|
return record.invalidationVersion === version;
|
|
@@ -264,13 +345,12 @@ function getNotModifiedStyle(record, styleStore, options, hasHmrTimestampedDepen
|
|
|
264
345
|
let emittedStyle = record.emitted;
|
|
265
346
|
if (!emittedStyle || options.ifNoneMatch === null)
|
|
266
347
|
return null;
|
|
267
|
-
if (options.requestedFingerprint !== null &&
|
|
268
|
-
emittedStyle.fingerprint !== options.requestedFingerprint) {
|
|
269
|
-
return null;
|
|
270
|
-
}
|
|
271
348
|
let asset = getEmittedAssetForRequest(emittedStyle, options.isSourceMapRequest);
|
|
272
349
|
if (!asset)
|
|
273
350
|
return null;
|
|
351
|
+
if (options.requestedFingerprint !== null && asset.fingerprint !== options.requestedFingerprint) {
|
|
352
|
+
return null;
|
|
353
|
+
}
|
|
274
354
|
if (!IfNoneMatch.from(options.ifNoneMatch).matches(asset.etag))
|
|
275
355
|
return null;
|
|
276
356
|
return { etag: asset.etag, type: 'not-modified' };
|
|
@@ -3,11 +3,11 @@ import type { ResolvedStyle } from './resolve.ts';
|
|
|
3
3
|
export type EmittedAsset = {
|
|
4
4
|
content: string;
|
|
5
5
|
etag: string;
|
|
6
|
+
fingerprint: string;
|
|
6
7
|
};
|
|
7
8
|
export type EmittedStyle = {
|
|
8
9
|
code: EmittedAsset;
|
|
9
10
|
fingerprint: string | null;
|
|
10
|
-
importUrls: string[];
|
|
11
11
|
sourceMap: EmittedAsset | null;
|
|
12
12
|
};
|
|
13
13
|
type EmitResult = {
|
|
@@ -18,6 +18,7 @@ type EmitResult = {
|
|
|
18
18
|
ok: false;
|
|
19
19
|
};
|
|
20
20
|
export declare function emitResolvedStyle(resolvedStyle: ResolvedStyle, options: {
|
|
21
|
+
fingerprintAssets: boolean;
|
|
21
22
|
getServedFileUrl?(identityPath: string, options: {
|
|
22
23
|
transform: readonly string[] | null;
|
|
23
24
|
}): Promise<string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../../../src/lib/styles/emit.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAA;AAC1E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAEjD,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../../../src/lib/styles/emit.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAA;AAC1E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAEjD,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,YAAY,CAAA;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,SAAS,EAAE,YAAY,GAAG,IAAI,CAAA;CAC/B,CAAA;AAED,KAAK,UAAU,GACX;IACE,EAAE,EAAE,IAAI,CAAA;IACR,KAAK,EAAE,YAAY,CAAA;CACpB,GACD;IACE,KAAK,EAAE,2BAA2B,CAAA;IAClC,EAAE,EAAE,KAAK,CAAA;CACV,CAAA;AAEL,wBAAsB,iBAAiB,CACrC,aAAa,EAAE,aAAa,EAC5B,OAAO,EAAE;IACP,iBAAiB,EAAE,OAAO,CAAA;IAC1B,gBAAgB,CAAC,CACf,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE;QACP,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAA;KACpC,GACA,OAAO,CAAC,MAAM,CAAC,CAAA;IAClB,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IACnD,UAAU,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAA;CACnC,GACA,OAAO,CAAC,UAAU,CAAC,CAoCrB"}
|
package/dist/lib/styles/emit.js
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
import MagicString from 'magic-string';
|
|
2
2
|
import { createAssetServerCompilationError, isAssetServerCompilationError, } from '../compilation-error.js';
|
|
3
|
-
import { hashContent } from '../fingerprint.js';
|
|
3
|
+
import { formatFingerprintedPathname, hashContent } from '../fingerprint.js';
|
|
4
4
|
import { composeSourceMaps } from '../source-maps.js';
|
|
5
5
|
export async function emitResolvedStyle(resolvedStyle, options) {
|
|
6
6
|
try {
|
|
7
|
-
let importUrls = await Promise.all(resolvedStyle.deps.map((depPath) => options.getServedUrl(depPath)));
|
|
8
7
|
let rewriteResult = await rewriteDependencies(resolvedStyle, options);
|
|
9
8
|
let finalCode = rewriteResult.code;
|
|
9
|
+
let sourceMap = rewriteResult.sourceMap
|
|
10
|
+
? await createEmittedAsset(rewriteResult.sourceMap)
|
|
11
|
+
: null;
|
|
10
12
|
if (rewriteResult.sourceMap) {
|
|
11
13
|
if (options.sourceMaps === 'inline') {
|
|
12
14
|
let encoded = Buffer.from(rewriteResult.sourceMap).toString('base64');
|
|
13
15
|
finalCode += `\n/*# sourceMappingURL=data:application/json;base64,${encoded} */`;
|
|
14
16
|
}
|
|
15
17
|
else if (options.sourceMaps === 'external') {
|
|
16
|
-
finalCode += `\n/*# sourceMappingURL=${
|
|
18
|
+
finalCode += `\n/*# sourceMappingURL=${formatFingerprintedPathname(resolvedStyle.stableUrlPathname, options.fingerprintAssets && sourceMap ? sourceMap.fingerprint : null)}.map */`;
|
|
17
19
|
}
|
|
18
20
|
}
|
|
21
|
+
let code = await createEmittedAsset(finalCode);
|
|
19
22
|
return {
|
|
20
23
|
ok: true,
|
|
21
24
|
value: {
|
|
22
|
-
code
|
|
23
|
-
fingerprint:
|
|
24
|
-
|
|
25
|
-
sourceMap: rewriteResult.sourceMap
|
|
26
|
-
? await createEmittedAsset(rewriteResult.sourceMap)
|
|
27
|
-
: null,
|
|
25
|
+
code,
|
|
26
|
+
fingerprint: options.fingerprintAssets ? code.fingerprint : null,
|
|
27
|
+
sourceMap,
|
|
28
28
|
},
|
|
29
29
|
};
|
|
30
30
|
}
|
|
@@ -98,9 +98,11 @@ async function getServedFileUrl(options, importerPath, identityPath, request) {
|
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
100
|
async function createEmittedAsset(content) {
|
|
101
|
+
let fingerprint = await hashContent(content);
|
|
101
102
|
return {
|
|
102
103
|
content,
|
|
103
|
-
etag: `W/"${
|
|
104
|
+
etag: `W/"${fingerprint}"`,
|
|
105
|
+
fingerprint,
|
|
104
106
|
};
|
|
105
107
|
}
|
|
106
108
|
function toEmitError(error, identityPath) {
|