@remix-run/assets 0.6.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 +101 -13
- package/dist/assets.d.ts +2 -1
- package/dist/assets.d.ts.map +1 -1
- package/dist/lib/asset-server.d.ts +41 -19
- package/dist/lib/asset-server.d.ts.map +1 -1
- package/dist/lib/asset-server.js +98 -41
- 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 +26 -29
- 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/routes.d.ts +1 -0
- package/dist/lib/routes.d.ts.map +1 -1
- package/dist/lib/routes.js +1 -1
- 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 +186 -36
- 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 +110 -3
- 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 +2 -16
- 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 +0 -1
- 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 +0 -7
- 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 -5
- package/src/assets.ts +7 -1
- package/src/lib/asset-server.ts +175 -73
- package/src/lib/compilation-error.ts +1 -0
- package/src/lib/files/compiler.ts +30 -40
- 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/routes.ts +1 -1
- package/src/lib/scripts/compiler.ts +238 -52
- package/src/lib/scripts/emit.ts +34 -19
- package/src/lib/scripts/resolve.ts +166 -4
- package/src/lib/scripts/specifiers.ts +11 -0
- package/src/lib/scripts/transform.ts +4 -23
- package/src/lib/styles/compiler.ts +137 -39
- package/src/lib/styles/emit.ts +18 -13
- package/src/lib/styles/resolve.ts +0 -2
- package/src/lib/styles/transform.ts +0 -10
- package/src/lib/virtual-store.ts +124 -0
|
@@ -3,17 +3,19 @@ import * as os from 'node:os';
|
|
|
3
3
|
import * as path from 'node:path';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
5
|
import { IfNoneMatch } from '@remix-run/headers/if-none-match';
|
|
6
|
+
import { getTsconfig } from 'get-tsconfig';
|
|
6
7
|
import { createAssetServerCompilationError } from '../compilation-error.js';
|
|
7
8
|
import { createFileMatcher } from '../file-matcher.js';
|
|
8
9
|
import { formatFingerprintedPathname, getFingerprintRequestCacheControl, parseFingerprintSuffix, } from '../fingerprint.js';
|
|
9
10
|
import { emitResolvedModule } from './emit.js';
|
|
10
11
|
import { normalizeFilePath, resolveFilePath } from '../paths.js';
|
|
11
12
|
import { resolveModule, resolverExtensionAlias, resolverExtensions, supportedScriptExtensions, } from './resolve.js';
|
|
13
|
+
import { isBareImportSpecifier } from './specifiers.js';
|
|
12
14
|
import { createModuleStore } from '../module-store.js';
|
|
13
15
|
import { createTsconfigTransformOptionsResolver, transformModule } from './transform.js';
|
|
14
16
|
import { ResolverFactory } from 'oxc-resolver';
|
|
15
17
|
const supportedScriptExtensionSet = new Set(supportedScriptExtensions);
|
|
16
|
-
const
|
|
18
|
+
const scriptConcurrency = Math.max(1, Math.min(8, os.availableParallelism() - 1));
|
|
17
19
|
export function createScriptCompiler(options) {
|
|
18
20
|
let resolvedOptions = {
|
|
19
21
|
...options,
|
|
@@ -31,18 +33,21 @@ export function createScriptCompiler(options) {
|
|
|
31
33
|
onWatchFilesChange: options.onWatchFilesChange,
|
|
32
34
|
});
|
|
33
35
|
let tsconfigTransformOptionsResolver = createTsconfigTransformOptionsResolver();
|
|
34
|
-
let
|
|
36
|
+
let resolverOptions = {
|
|
35
37
|
aliasFields: [['browser']],
|
|
36
38
|
conditionNames: ['browser', 'import', 'module', 'default'],
|
|
37
39
|
extensionAlias: resolverExtensionAlias,
|
|
38
40
|
extensions: resolverExtensions,
|
|
39
41
|
mainFields: ['browser', 'module', 'main'],
|
|
40
|
-
|
|
41
|
-
});
|
|
42
|
+
};
|
|
43
|
+
let resolverFactory = new ResolverFactory({ ...resolverOptions, tsconfig: 'auto' });
|
|
44
|
+
let directoryResolverByTsconfig = new Map();
|
|
45
|
+
let tsconfigByDirectory = new Map();
|
|
46
|
+
let directoryResolutionIdentityByCacheKey = new Map();
|
|
42
47
|
let resolveInFlightByCacheKey = new Map();
|
|
43
48
|
let emitInFlightByCacheKey = new Map();
|
|
49
|
+
let hasResolvedScripts = false;
|
|
44
50
|
let transformArgs = {
|
|
45
|
-
buildId: resolvedOptions.buildId ?? null,
|
|
46
51
|
define: resolvedOptions.define ?? null,
|
|
47
52
|
externalSet: resolvedOptions.externalSet,
|
|
48
53
|
isWatchIgnored,
|
|
@@ -56,10 +61,13 @@ export function createScriptCompiler(options) {
|
|
|
56
61
|
tsconfigTransformOptionsResolver,
|
|
57
62
|
};
|
|
58
63
|
let resolveArgs = {
|
|
64
|
+
concurrency: scriptConcurrency,
|
|
65
|
+
isDirectoryResolutionFileIndependent,
|
|
59
66
|
isAllowed: resolvedOptions.isAllowed,
|
|
60
67
|
isWatchIgnored,
|
|
61
68
|
resolveModulePath,
|
|
62
69
|
resolverFactory,
|
|
70
|
+
resolveDirectorySpecifierIdentity,
|
|
63
71
|
routes: resolvedOptions.routes,
|
|
64
72
|
};
|
|
65
73
|
return {
|
|
@@ -76,14 +84,7 @@ export function createScriptCompiler(options) {
|
|
|
76
84
|
};
|
|
77
85
|
},
|
|
78
86
|
async getPreloadLayers(filePath) {
|
|
79
|
-
let resolvedEntries =
|
|
80
|
-
let seen = new Set();
|
|
81
|
-
for (let resolvedModule of (Array.isArray(filePath) ? filePath : [filePath]).map((nextPath) => resolveServedScriptOrThrow(resolveInputFilePath(nextPath)))) {
|
|
82
|
-
if (seen.has(resolvedModule.identityPath))
|
|
83
|
-
continue;
|
|
84
|
-
seen.add(resolvedModule.identityPath);
|
|
85
|
-
resolvedEntries.push(resolvedModule.identityPath);
|
|
86
|
-
}
|
|
87
|
+
let resolvedEntries = resolveInputScriptRoots(filePath);
|
|
87
88
|
let visited = new Set(resolvedEntries);
|
|
88
89
|
let queue = [...resolvedEntries];
|
|
89
90
|
let layers = [];
|
|
@@ -93,8 +94,8 @@ export function createScriptCompiler(options) {
|
|
|
93
94
|
let resolvedModules = await getOrCreateResolvedScripts(frontier.map((identityPath) => scriptStore.get(identityPath)));
|
|
94
95
|
let layer = [];
|
|
95
96
|
for (let resolvedModule of resolvedModules) {
|
|
96
|
-
layer.push(
|
|
97
|
-
for (let dep of resolvedModule.
|
|
97
|
+
layer.push(await getServedUrl(resolvedModule.identityPath));
|
|
98
|
+
for (let dep of resolvedModule.staticDeps) {
|
|
98
99
|
if (visited.has(dep))
|
|
99
100
|
continue;
|
|
100
101
|
visited.add(dep);
|
|
@@ -105,10 +106,66 @@ export function createScriptCompiler(options) {
|
|
|
105
106
|
}
|
|
106
107
|
return layers;
|
|
107
108
|
},
|
|
109
|
+
async getImportMap(filePath) {
|
|
110
|
+
let resolvedEntries = resolveInputScriptRoots(filePath);
|
|
111
|
+
let resolvedEntrySet = new Set(resolvedEntries);
|
|
112
|
+
let visited = new Set();
|
|
113
|
+
let queue = [...resolvedEntries];
|
|
114
|
+
let imports = {};
|
|
115
|
+
let scopes = {};
|
|
116
|
+
while (queue.length > 0) {
|
|
117
|
+
let frontier = queue;
|
|
118
|
+
queue = [];
|
|
119
|
+
let resolvedModules = await getOrCreateResolvedScripts(frontier.map((identityPath) => scriptStore.get(identityPath)));
|
|
120
|
+
for (let resolvedModule of resolvedModules) {
|
|
121
|
+
if (visited.has(resolvedModule.identityPath))
|
|
122
|
+
continue;
|
|
123
|
+
visited.add(resolvedModule.identityPath);
|
|
124
|
+
if (!resolvedEntrySet.has(resolvedModule.identityPath)) {
|
|
125
|
+
addImportMapEntry(imports, resolvedModule.stableUrlPathname, await getServedUrl(resolvedModule.identityPath));
|
|
126
|
+
}
|
|
127
|
+
for (let imported of resolvedModule.imports) {
|
|
128
|
+
let depUrl = await getServedUrl(imported.depPath);
|
|
129
|
+
if (isBareImportSpecifier(imported.specifier)) {
|
|
130
|
+
let scopePathname = imported.scopePathname;
|
|
131
|
+
if (!scopePathname) {
|
|
132
|
+
throw new Error(`Expected import map scope for bare import "${imported.specifier}" in ${resolvedModule.identityPath}`);
|
|
133
|
+
}
|
|
134
|
+
let scopeImports = (scopes[scopePathname] ??= {});
|
|
135
|
+
addImportMapEntry(scopeImports, imported.specifier, depUrl);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
let browserResolvedSpecifier = resolveImportMapUrlSpecifier(imported.specifier, resolvedModule.stableUrlPathname);
|
|
139
|
+
addImportMapEntry(imports, browserResolvedSpecifier, depUrl);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
for (let dep of resolvedModule.deps) {
|
|
143
|
+
if (!visited.has(dep)) {
|
|
144
|
+
queue.push(dep);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
for (let [scopePathname, scopeImports] of Object.entries(scopes)) {
|
|
150
|
+
if (Object.keys(scopeImports).length === 0) {
|
|
151
|
+
delete scopes[scopePathname];
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return Object.keys(scopes).length > 0 ? { imports, scopes } : { imports };
|
|
155
|
+
},
|
|
108
156
|
async getHref(filePath) {
|
|
109
157
|
let resolvedModule = resolveServedScriptOrThrow(resolveInputFilePath(filePath));
|
|
110
158
|
return getServedUrl(resolvedModule.identityPath);
|
|
111
159
|
},
|
|
160
|
+
async resolveSpecifierFromRoot(specifier) {
|
|
161
|
+
let importerPath = path.join(resolvedOptions.rootDir, '__remix_virtual_entry__.js');
|
|
162
|
+
let resolutionResult = await resolverFactory.resolveFileAsync(importerPath, specifier);
|
|
163
|
+
if (resolutionResult.error || !resolutionResult.path) {
|
|
164
|
+
throw createAssetServerCompilationError(`Failed to resolve browser module "${specifier}" from asset server root.`, { code: 'IMPORT_RESOLUTION_FAILED' });
|
|
165
|
+
}
|
|
166
|
+
let resolvedModule = resolveServedScriptOrThrow(resolutionResult.path);
|
|
167
|
+
return getServedUrl(resolvedModule.identityPath);
|
|
168
|
+
},
|
|
112
169
|
async classifyHmrFileEvent(filePath, event) {
|
|
113
170
|
let normalizedFilePath = normalizeFilePath(filePath);
|
|
114
171
|
if (isWatchIgnored(normalizedFilePath))
|
|
@@ -116,7 +173,20 @@ export function createScriptCompiler(options) {
|
|
|
116
173
|
let timestamp = Date.now();
|
|
117
174
|
let previousResolvedModule = scriptStore.getLastResolved(normalizedFilePath);
|
|
118
175
|
let updatePathname = previousResolvedModule?.stableUrlPathname;
|
|
176
|
+
let resolutionMetadataChanged = isPackageJsonPath(normalizedFilePath) || isTsconfigPath(normalizedFilePath);
|
|
119
177
|
invalidateScriptFileEvent(normalizedFilePath, event);
|
|
178
|
+
if (resolutionMetadataChanged && hasResolvedScripts) {
|
|
179
|
+
let hmrUpdate = [
|
|
180
|
+
{
|
|
181
|
+
accepted: false,
|
|
182
|
+
filePath: normalizedFilePath,
|
|
183
|
+
path: normalizedFilePath,
|
|
184
|
+
timestamp,
|
|
185
|
+
},
|
|
186
|
+
];
|
|
187
|
+
resolvedOptions.hmr?.send(hmrUpdate);
|
|
188
|
+
return hmrUpdate;
|
|
189
|
+
}
|
|
120
190
|
let resolvedModule = event === 'change' && updatePathname
|
|
121
191
|
? await tryGetOrCreateResolvedScript(scriptStore.get(normalizedFilePath))
|
|
122
192
|
: undefined;
|
|
@@ -160,6 +230,11 @@ export function createScriptCompiler(options) {
|
|
|
160
230
|
return;
|
|
161
231
|
if (shouldClearResolverCacheForFileEvent(normalizedFilePath, event)) {
|
|
162
232
|
resolverFactory.clearCache();
|
|
233
|
+
for (let directoryResolver of directoryResolverByTsconfig.values()) {
|
|
234
|
+
directoryResolver.clearCache();
|
|
235
|
+
}
|
|
236
|
+
tsconfigByDirectory.clear();
|
|
237
|
+
directoryResolutionIdentityByCacheKey.clear();
|
|
163
238
|
}
|
|
164
239
|
if (isTsconfigPath(normalizedFilePath)) {
|
|
165
240
|
tsconfigTransformOptionsResolver.clear();
|
|
@@ -172,6 +247,44 @@ export function createScriptCompiler(options) {
|
|
|
172
247
|
}
|
|
173
248
|
scriptStore.invalidateForFileEvent(normalizedFilePath, event);
|
|
174
249
|
}
|
|
250
|
+
function isDirectoryResolutionFileIndependent(directory) {
|
|
251
|
+
return getDirectoryTsconfig(directory).fileIndependent;
|
|
252
|
+
}
|
|
253
|
+
function getDirectoryTsconfig(directory) {
|
|
254
|
+
let existing = tsconfigByDirectory.get(directory);
|
|
255
|
+
if (existing)
|
|
256
|
+
return existing;
|
|
257
|
+
let tsconfig = getTsconfig(directory);
|
|
258
|
+
let result = {
|
|
259
|
+
fileIndependent: !tsconfig?.config.references?.length,
|
|
260
|
+
path: tsconfig?.path ?? null,
|
|
261
|
+
};
|
|
262
|
+
tsconfigByDirectory.set(directory, result);
|
|
263
|
+
return result;
|
|
264
|
+
}
|
|
265
|
+
async function resolveDirectorySpecifierIdentity(directory, specifier) {
|
|
266
|
+
let cacheKey = `${directory}\0${specifier}`;
|
|
267
|
+
let existing = directoryResolutionIdentityByCacheKey.get(cacheKey);
|
|
268
|
+
if (existing)
|
|
269
|
+
return existing;
|
|
270
|
+
let promise = (async () => {
|
|
271
|
+
let tsconfigPath = getDirectoryTsconfig(directory).path;
|
|
272
|
+
let directoryResolver = directoryResolverByTsconfig.get(tsconfigPath);
|
|
273
|
+
if (!directoryResolver) {
|
|
274
|
+
directoryResolver = new ResolverFactory({
|
|
275
|
+
...resolverOptions,
|
|
276
|
+
tsconfig: tsconfigPath ? { configFile: tsconfigPath } : undefined,
|
|
277
|
+
});
|
|
278
|
+
directoryResolverByTsconfig.set(tsconfigPath, directoryResolver);
|
|
279
|
+
}
|
|
280
|
+
let result = await directoryResolver.async(directory, specifier);
|
|
281
|
+
if (!result.path || !path.isAbsolute(result.path))
|
|
282
|
+
return null;
|
|
283
|
+
return resolveModulePath(normalizeFilePath(result.path))?.identityPath ?? null;
|
|
284
|
+
})();
|
|
285
|
+
directoryResolutionIdentityByCacheKey.set(cacheKey, promise);
|
|
286
|
+
return promise;
|
|
287
|
+
}
|
|
175
288
|
function resolveServedScriptOrThrow(absolutePath) {
|
|
176
289
|
let resolvedModule = resolveModulePath(absolutePath);
|
|
177
290
|
if (!resolvedModule) {
|
|
@@ -187,6 +300,18 @@ export function createScriptCompiler(options) {
|
|
|
187
300
|
}
|
|
188
301
|
return resolvedModule;
|
|
189
302
|
}
|
|
303
|
+
function resolveInputScriptRoots(filePath) {
|
|
304
|
+
let resolvedEntries = [];
|
|
305
|
+
let seen = new Set();
|
|
306
|
+
for (let nextPath of Array.isArray(filePath) ? filePath : [filePath]) {
|
|
307
|
+
let resolvedModule = resolveServedScriptOrThrow(resolveInputFilePath(nextPath));
|
|
308
|
+
if (seen.has(resolvedModule.identityPath))
|
|
309
|
+
continue;
|
|
310
|
+
seen.add(resolvedModule.identityPath);
|
|
311
|
+
resolvedEntries.push(resolvedModule.identityPath);
|
|
312
|
+
}
|
|
313
|
+
return resolvedEntries;
|
|
314
|
+
}
|
|
190
315
|
function getNotModifiedScript(record, options) {
|
|
191
316
|
if (hasHmrTimestampedDependency(record.resolved)) {
|
|
192
317
|
return null;
|
|
@@ -202,7 +327,7 @@ export function createScriptCompiler(options) {
|
|
|
202
327
|
return getNotModifiedResult(record.staleEmitted, options);
|
|
203
328
|
}
|
|
204
329
|
async function getOrCreateResolvedScripts(records) {
|
|
205
|
-
return mapWithConcurrency(records,
|
|
330
|
+
return mapWithConcurrency(records, scriptConcurrency, (record) => getOrCreateResolvedScript(record));
|
|
206
331
|
}
|
|
207
332
|
async function getOrCreateResolvedScript(record) {
|
|
208
333
|
if (record.resolved && scriptStore.isResolvedFresh(record))
|
|
@@ -230,6 +355,7 @@ export function createScriptCompiler(options) {
|
|
|
230
355
|
resolveModuleResult.tracking,
|
|
231
356
|
]);
|
|
232
357
|
}
|
|
358
|
+
hasResolvedScripts = true;
|
|
233
359
|
return resolveModuleResult.value;
|
|
234
360
|
})();
|
|
235
361
|
resolveInFlightByCacheKey.set(cacheKey, promise);
|
|
@@ -281,10 +407,12 @@ export function createScriptCompiler(options) {
|
|
|
281
407
|
let promise = (async () => {
|
|
282
408
|
let startedVersion = record.invalidationVersion;
|
|
283
409
|
let resolvedModule = await getOrCreateResolvedScript(record);
|
|
410
|
+
await resolveScriptGraph(resolvedModule);
|
|
284
411
|
let emitResolvedModuleResult = await emitResolvedModule(resolvedModule, {
|
|
412
|
+
fingerprintAssets: resolvedOptions.fingerprintAssets,
|
|
413
|
+
getHmrImportTimestamp,
|
|
285
414
|
getServedUrl,
|
|
286
415
|
getStableUrl,
|
|
287
|
-
getHmrImportTimestamp,
|
|
288
416
|
hmrClientPathname: resolvedOptions.hmr?.clientPathname,
|
|
289
417
|
sourceMaps: resolvedOptions.sourceMaps,
|
|
290
418
|
});
|
|
@@ -306,11 +434,33 @@ export function createScriptCompiler(options) {
|
|
|
306
434
|
}
|
|
307
435
|
}
|
|
308
436
|
}
|
|
309
|
-
async function
|
|
310
|
-
|
|
437
|
+
async function resolveScriptGraph(root) {
|
|
438
|
+
let visited = new Set([root.identityPath]);
|
|
439
|
+
let queue = [...root.deps];
|
|
440
|
+
while (queue.length > 0) {
|
|
441
|
+
let frontier = queue;
|
|
442
|
+
queue = [];
|
|
443
|
+
let resolvedModules = await getOrCreateResolvedScripts(frontier
|
|
444
|
+
.filter((identityPath) => !visited.has(identityPath))
|
|
445
|
+
.map((identityPath) => scriptStore.get(identityPath)));
|
|
446
|
+
for (let resolvedModule of resolvedModules) {
|
|
447
|
+
if (visited.has(resolvedModule.identityPath))
|
|
448
|
+
continue;
|
|
449
|
+
visited.add(resolvedModule.identityPath);
|
|
450
|
+
for (let dep of resolvedModule.deps) {
|
|
451
|
+
if (!visited.has(dep))
|
|
452
|
+
queue.push(dep);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
311
456
|
}
|
|
312
|
-
function
|
|
313
|
-
|
|
457
|
+
async function getServedUrl(identityPath) {
|
|
458
|
+
let resolvedModule = await getOrCreateResolvedScript(scriptStore.get(identityPath));
|
|
459
|
+
if (!resolvedOptions.fingerprintAssets) {
|
|
460
|
+
return resolvedModule.stableUrlPathname;
|
|
461
|
+
}
|
|
462
|
+
let emittedModule = await getOrCreateEmittedScript(scriptStore.get(identityPath));
|
|
463
|
+
return formatFingerprintedPathname(resolvedModule.stableUrlPathname, emittedModule.fingerprint);
|
|
314
464
|
}
|
|
315
465
|
function getStableUrl(identityPath) {
|
|
316
466
|
let stableUrlPathname = resolvedOptions.routes.toUrlPathname(identityPath);
|
|
@@ -335,7 +485,8 @@ export function createScriptCompiler(options) {
|
|
|
335
485
|
return [
|
|
336
486
|
{
|
|
337
487
|
accepted: true,
|
|
338
|
-
|
|
488
|
+
acceptedFilePath: resolvedModule.identityPath,
|
|
489
|
+
acceptedUrlPathname: updatePathname,
|
|
339
490
|
filePath: resolvedModule.identityPath,
|
|
340
491
|
path: updatePathname,
|
|
341
492
|
timestamp,
|
|
@@ -347,7 +498,8 @@ export function createScriptCompiler(options) {
|
|
|
347
498
|
if (sourceFilePath !== undefined && boundaries) {
|
|
348
499
|
return dedupeHmrBoundaries(boundaries).map(({ acceptedModule, boundaryModule }) => ({
|
|
349
500
|
accepted: true,
|
|
350
|
-
|
|
501
|
+
acceptedFilePath: acceptedModule.identityPath,
|
|
502
|
+
acceptedUrlPathname: acceptedModule.stableUrlPathname,
|
|
351
503
|
filePath: sourceFilePath,
|
|
352
504
|
path: boundaryModule.stableUrlPathname,
|
|
353
505
|
timestamp,
|
|
@@ -409,6 +561,14 @@ export function createScriptCompiler(options) {
|
|
|
409
561
|
return resolvedOptions.watchIgnoreMatchers.some((matcher) => matcher(filePath));
|
|
410
562
|
}
|
|
411
563
|
}
|
|
564
|
+
function resolveImportMapUrlSpecifier(specifier, importerUrlPathname) {
|
|
565
|
+
return new URL(specifier, `http://localhost${importerUrlPathname}`).pathname;
|
|
566
|
+
}
|
|
567
|
+
function addImportMapEntry(imports, specifier, url) {
|
|
568
|
+
if (specifier === url)
|
|
569
|
+
return;
|
|
570
|
+
imports[specifier] = url;
|
|
571
|
+
}
|
|
412
572
|
function dedupeHmrBoundaries(boundaries) {
|
|
413
573
|
let seen = new Set();
|
|
414
574
|
let result = [];
|
|
@@ -430,13 +590,12 @@ function isFresh(record, version) {
|
|
|
430
590
|
function getNotModifiedResult(emittedModule, options) {
|
|
431
591
|
if (!emittedModule || options.ifNoneMatch === null)
|
|
432
592
|
return null;
|
|
433
|
-
if (options.requestedFingerprint !== null &&
|
|
434
|
-
emittedModule.fingerprint !== options.requestedFingerprint) {
|
|
435
|
-
return null;
|
|
436
|
-
}
|
|
437
593
|
let asset = getEmittedAssetForRequest(emittedModule, options.isSourceMapRequest);
|
|
438
594
|
if (!asset)
|
|
439
595
|
return null;
|
|
596
|
+
if (options.requestedFingerprint !== null && asset.fingerprint !== options.requestedFingerprint) {
|
|
597
|
+
return null;
|
|
598
|
+
}
|
|
440
599
|
if (!IfNoneMatch.from(options.ifNoneMatch).matches(asset.etag))
|
|
441
600
|
return null;
|
|
442
601
|
return { type: 'not-modified', etag: asset.etag };
|
|
@@ -548,15 +707,6 @@ function resolveActualPath(identityPath) {
|
|
|
548
707
|
throw error;
|
|
549
708
|
}
|
|
550
709
|
}
|
|
551
|
-
function isBareImportSpecifier(specifier) {
|
|
552
|
-
return (!specifier.startsWith('./') &&
|
|
553
|
-
!specifier.startsWith('../') &&
|
|
554
|
-
!specifier.startsWith('/') &&
|
|
555
|
-
!specifier.startsWith('file:') &&
|
|
556
|
-
!specifier.startsWith('data:') &&
|
|
557
|
-
!specifier.startsWith('http://') &&
|
|
558
|
-
!specifier.startsWith('https://'));
|
|
559
|
-
}
|
|
560
710
|
function isNoEntityError(error) {
|
|
561
711
|
return (error instanceof Error &&
|
|
562
712
|
'code' in error &&
|
|
@@ -3,11 +3,11 @@ import type { AssetServerCompilationError } from '../compilation-error.ts';
|
|
|
3
3
|
export type EmittedAsset = {
|
|
4
4
|
content: string;
|
|
5
5
|
etag: string;
|
|
6
|
+
fingerprint: string;
|
|
6
7
|
};
|
|
7
8
|
export type EmittedModule = {
|
|
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
|
error: AssetServerCompilationError;
|
|
19
19
|
};
|
|
20
20
|
export declare function emitResolvedModule(resolvedModule: ResolvedModule, options: {
|
|
21
|
+
fingerprintAssets: boolean;
|
|
21
22
|
getHmrImportTimestamp(identityPath: string): number | null;
|
|
22
23
|
getServedUrl(identityPath: string): Promise<string>;
|
|
23
24
|
getStableUrl(identityPath: string): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../../../src/lib/scripts/emit.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAElD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAA;AAE1E,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/scripts/emit.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAElD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAA;AAE1E,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,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,aAAa,CAAA;CACrB,GACD;IACE,EAAE,EAAE,KAAK,CAAA;IACT,KAAK,EAAE,2BAA2B,CAAA;CACnC,CAAA;AAQL,wBAAsB,kBAAkB,CACtC,cAAc,EAAE,cAAc,EAC9B,OAAO,EAAE;IACP,iBAAiB,EAAE,OAAO,CAAA;IAC1B,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IAC1D,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IACnD,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAAA;IAC1C,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,UAAU,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAA;CACnC,GACA,OAAO,CAAC,UAAU,CAAC,CAoCrB"}
|
package/dist/lib/scripts/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 emitResolvedModule(resolvedModule, options) {
|
|
6
6
|
try {
|
|
7
|
-
let importUrls = await Promise.all(resolvedModule.deps.map((depPath) => options.getServedUrl(depPath)));
|
|
8
7
|
let rewriteResult = await rewriteImports(resolvedModule, options);
|
|
9
8
|
let finalCode = prependHmrContext(resolvedModule, rewriteResult.code, options);
|
|
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(resolvedModule.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
|
}
|
|
@@ -37,21 +37,28 @@ export async function emitResolvedModule(resolvedModule, options) {
|
|
|
37
37
|
}
|
|
38
38
|
async function rewriteImports(resolvedModule, options) {
|
|
39
39
|
let rewrittenSource = new MagicString(resolvedModule.rawCode);
|
|
40
|
+
let changed = false;
|
|
40
41
|
for (let imported of resolvedModule.imports) {
|
|
41
|
-
let url = await options.getServedUrl(imported.depPath);
|
|
42
42
|
let hmrImportTimestamp = options.getHmrImportTimestamp(imported.depPath);
|
|
43
|
+
let replacementSpecifier = imported.specifier;
|
|
43
44
|
if (hmrImportTimestamp !== null) {
|
|
44
|
-
|
|
45
|
+
replacementSpecifier = addTimestampQuery(await options.getServedUrl(imported.depPath), hmrImportTimestamp);
|
|
45
46
|
}
|
|
46
|
-
|
|
47
|
+
else if (imported.compiledSpecifier === imported.specifier) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
rewrittenSource.overwrite(imported.start, imported.end, imported.quote
|
|
51
|
+
? `${imported.quote}${replacementSpecifier}${imported.quote}`
|
|
52
|
+
: replacementSpecifier);
|
|
53
|
+
changed = true;
|
|
47
54
|
}
|
|
48
55
|
for (let acceptedDep of resolvedModule.hmr.acceptedDeps) {
|
|
49
56
|
let url = options.getStableUrl(acceptedDep.depPath);
|
|
50
57
|
rewrittenSource.overwrite(acceptedDep.start, acceptedDep.end, acceptedDep.quote ? `${acceptedDep.quote}${url}${acceptedDep.quote}` : url);
|
|
58
|
+
changed = true;
|
|
51
59
|
}
|
|
52
|
-
let code = rewrittenSource.toString();
|
|
53
|
-
let sourceMap = resolvedModule.sourceMap &&
|
|
54
|
-
(resolvedModule.imports.length > 0 || resolvedModule.hmr.acceptedDeps.length > 0)
|
|
60
|
+
let code = changed ? rewrittenSource.toString() : resolvedModule.rawCode;
|
|
61
|
+
let sourceMap = resolvedModule.sourceMap && changed
|
|
55
62
|
? composeSourceMaps(rewrittenSource.generateMap({ hires: true }).toString(), resolvedModule.sourceMap)
|
|
56
63
|
: resolvedModule.sourceMap;
|
|
57
64
|
return { code, sourceMap };
|
|
@@ -67,9 +74,11 @@ function prependHmrContext(resolvedModule, code, options) {
|
|
|
67
74
|
code);
|
|
68
75
|
}
|
|
69
76
|
async function createEmittedAsset(content) {
|
|
77
|
+
let fingerprint = await hashContent(content);
|
|
70
78
|
return {
|
|
71
79
|
content,
|
|
72
|
-
etag: `W/"${
|
|
80
|
+
etag: `W/"${fingerprint}"`,
|
|
81
|
+
fingerprint,
|
|
73
82
|
};
|
|
74
83
|
}
|
|
75
84
|
function toEmitError(error, identityPath) {
|
|
@@ -13,15 +13,17 @@ export declare const resolverExtensionAlias: {
|
|
|
13
13
|
export declare const resolverExtensions: string[];
|
|
14
14
|
export declare const supportedScriptExtensions: string[];
|
|
15
15
|
type ResolvedImport = {
|
|
16
|
+
compiledSpecifier: string;
|
|
16
17
|
depPath: string;
|
|
17
18
|
end: number;
|
|
18
19
|
quote?: '"' | "'" | '`';
|
|
20
|
+
scopePathname?: string;
|
|
21
|
+
specifier: string;
|
|
19
22
|
start: number;
|
|
20
23
|
};
|
|
21
24
|
type ResolvedHmrAcceptedDependency = ResolvedImport;
|
|
22
25
|
export type ResolvedModule = {
|
|
23
26
|
deps: string[];
|
|
24
|
-
fingerprint: string | null;
|
|
25
27
|
hmr: Omit<TransformedModule['hmr'], 'acceptedDeps'> & {
|
|
26
28
|
acceptedDeps: ResolvedHmrAcceptedDependency[];
|
|
27
29
|
};
|
|
@@ -31,6 +33,7 @@ export type ResolvedModule = {
|
|
|
31
33
|
rawCode: string;
|
|
32
34
|
resolvedPath: string;
|
|
33
35
|
sourceMap: string | null;
|
|
36
|
+
staticDeps: string[];
|
|
34
37
|
stableUrlPathname: string;
|
|
35
38
|
};
|
|
36
39
|
type ResolveResult = {
|
|
@@ -43,10 +46,13 @@ type ResolveResult = {
|
|
|
43
46
|
error: AssetServerCompilationError;
|
|
44
47
|
});
|
|
45
48
|
export type ResolveArgs = {
|
|
49
|
+
concurrency: number;
|
|
50
|
+
isDirectoryResolutionFileIndependent(directory: string): boolean;
|
|
46
51
|
isAllowed(absolutePath: string): boolean;
|
|
47
52
|
isWatchIgnored(filePath: string): boolean;
|
|
48
53
|
resolveModulePath(absolutePath: string): ResolveModuleResult | null;
|
|
49
54
|
resolverFactory: ResolverFactory;
|
|
55
|
+
resolveDirectorySpecifierIdentity(directory: string, specifier: string): Promise<string | null>;
|
|
50
56
|
routes: CompiledRoutes;
|
|
51
57
|
};
|
|
52
58
|
export declare function resolveModule(record: ScriptRecord, transformed: TransformedModule, args: ResolveArgs): Promise<ResolveResult>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../../src/lib/scripts/resolve.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAMnD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAA;AAM1E,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAEtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAClD,OAAO,KAAK,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAC5E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../../src/lib/scripts/resolve.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAMnD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAA;AAM1E,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAEtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAClD,OAAO,KAAK,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAC5E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAG9C,KAAK,YAAY,GAAG,YAAY,CAAC,iBAAiB,EAAE,cAAc,EAAE,aAAa,CAAC,CAAA;AAElF,eAAO,MAAM,sBAAsB;;;;CAIC,CAAA;AAEpC,eAAO,MAAM,kBAAkB,UAAiD,CAAA;AAChF,eAAO,MAAM,yBAAyB,UAAiD,CAAA;AAGvF,KAAK,cAAc,GAAG;IACpB,iBAAiB,EAAE,MAAM,CAAA;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,CAAC,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,KAAK,6BAA6B,GAAG,cAAc,CAAA;AAmBnD,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,GAAG,EAAE,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAAE,cAAc,CAAC,GAAG;QACpD,YAAY,EAAE,6BAA6B,EAAE,CAAA;KAC9C,CAAA;IACD,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,cAAc,EAAE,CAAA;IACzB,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,iBAAiB,EAAE,MAAM,CAAA;CAC1B,CAAA;AAED,KAAK,aAAa,GAAG;IACnB,QAAQ,EAAE,cAAc,CAAA;CACzB,GAAG,CACA;IACE,EAAE,EAAE,IAAI,CAAA;IACR,KAAK,EAAE,cAAc,CAAA;CACtB,GACD;IACE,EAAE,EAAE,KAAK,CAAA;IACT,KAAK,EAAE,2BAA2B,CAAA;CACnC,CACJ,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,WAAW,EAAE,MAAM,CAAA;IACnB,oCAAoC,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAA;IAChE,SAAS,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAA;IACxC,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAA;IACzC,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,mBAAmB,GAAG,IAAI,CAAA;IACnE,eAAe,EAAE,eAAe,CAAA;IAChC,iCAAiC,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IAC/F,MAAM,EAAE,cAAc,CAAA;CACvB,CAAA;AAaD,wBAAsB,aAAa,CACjC,MAAM,EAAE,YAAY,EACpB,WAAW,EAAE,iBAAiB,EAC9B,IAAI,EAAE,WAAW,GAChB,OAAO,CAAC,aAAa,CAAC,CAsSxB"}
|