@jsenv/core 28.1.1 → 28.2.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/dist/js/script_type_module_supervisor.js +8 -13
- package/dist/js/supervisor.js +702 -534
- package/dist/main.js +13275 -13164
- package/package.json +5 -5
- package/readme.md +3 -3
- package/src/build/build.js +960 -712
- package/src/build/inject_global_version_mappings.js +5 -20
- package/src/build/start_build_server.js +2 -2
- package/src/dev/start_dev_server.js +3 -2
- package/src/execute/run.js +1 -1
- package/src/execute/runtimes/browsers/from_playwright.js +1 -1
- package/src/omega/compat/runtime_compat.js +9 -6
- package/src/omega/errors.js +3 -0
- package/src/omega/fetched_content_compliance.js +2 -2
- package/src/omega/kitchen.js +189 -145
- package/src/omega/server/file_service.js +104 -71
- package/src/omega/url_graph/url_graph_loader.js +77 -0
- package/src/omega/url_graph/url_info_transformations.js +12 -15
- package/src/omega/url_graph.js +115 -101
- package/src/plugins/autoreload/jsenv_plugin_autoreload_client.js +1 -0
- package/src/plugins/autoreload/jsenv_plugin_autoreload_server.js +34 -36
- package/src/plugins/autoreload/jsenv_plugin_hmr.js +3 -2
- package/src/plugins/bundling/js_module/{bundle_js_module.js → bundle_js_modules.js} +51 -14
- package/src/plugins/bundling/jsenv_plugin_bundling.js +2 -2
- package/src/plugins/import_meta_hot/jsenv_plugin_import_meta_hot.js +11 -0
- package/src/plugins/inline/jsenv_plugin_html_inline_content.js +73 -62
- package/src/plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +77 -89
- package/src/plugins/plugin_controller.js +26 -22
- package/src/plugins/server_events/jsenv_plugin_server_events_client_injection.js +1 -0
- package/src/plugins/supervisor/client/script_type_module_supervisor.js +7 -9
- package/src/plugins/supervisor/client/supervisor.js +125 -96
- package/src/plugins/supervisor/jsenv_plugin_supervisor.js +2 -4
- package/src/plugins/toolbar/client/execution/toolbar_execution.js +1 -1
- package/src/plugins/transpilation/as_js_classic/async-to-promises.js +16 -0
- package/src/plugins/transpilation/as_js_classic/convert_js_module_to_js_classic.js +85 -0
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js +48 -190
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic_conversion.js +102 -0
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic_html.js +161 -240
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic_library.js +84 -0
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic_workers.js +19 -12
- package/src/plugins/transpilation/babel/jsenv_plugin_babel.js +1 -24
- package/src/plugins/transpilation/import_assertions/jsenv_plugin_import_assertions.js +82 -52
- package/src/plugins/transpilation/jsenv_plugin_transpilation.js +12 -13
- package/src/plugins/url_analysis/html/html_urls.js +91 -34
- package/src/plugins/url_analysis/js/js_urls.js +5 -4
- package/src/plugins/url_resolution/jsenv_plugin_url_resolution.js +1 -0
- package/src/test/execute_plan.js +3 -8
- package/src/test/execute_test_plan.js +1 -1
- package/src/build/inject_service_worker_urls.js +0 -78
- package/src/build/resync_resource_hints.js +0 -112
- package/src/omega/url_graph/url_graph_load.js +0 -74
package/src/build/build.js
CHANGED
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
/*
|
|
2
|
-
*
|
|
3
|
-
* 1.
|
|
4
|
-
* 2.
|
|
5
|
-
* 3.
|
|
6
|
-
*
|
|
2
|
+
* Build is split in 3 steps:
|
|
3
|
+
* 1. craft
|
|
4
|
+
* 2. shape
|
|
5
|
+
* 3. refine
|
|
6
|
+
*
|
|
7
|
+
* craft: prepare all the materials
|
|
8
|
+
* - resolve, fetch and transform all source files into "rawGraph"
|
|
9
|
+
* shape: this step can drastically change url content and their relationships
|
|
10
|
+
* - bundling
|
|
11
|
+
* - optimizations (minification)
|
|
12
|
+
* refine: perform minor changes on the url contents
|
|
13
|
+
* - cleaning html
|
|
14
|
+
* - url versioning
|
|
15
|
+
* - ressource hints
|
|
16
|
+
* - injecting urls into service workers
|
|
7
17
|
*/
|
|
8
18
|
|
|
9
19
|
import {
|
|
10
20
|
injectQueryParams,
|
|
11
21
|
setUrlFilename,
|
|
12
|
-
asUrlUntilPathname,
|
|
13
22
|
normalizeUrl,
|
|
14
23
|
asUrlWithoutSearch,
|
|
15
24
|
ensurePathnameTrailingSlash,
|
|
@@ -21,13 +30,25 @@ import {
|
|
|
21
30
|
import {
|
|
22
31
|
assertAndNormalizeDirectoryUrl,
|
|
23
32
|
ensureEmptyDirectory,
|
|
24
|
-
|
|
33
|
+
writeFileSync,
|
|
25
34
|
registerDirectoryLifecycle,
|
|
26
35
|
} from "@jsenv/filesystem"
|
|
27
36
|
import { Abort, raceProcessTeardownEvents } from "@jsenv/abort"
|
|
28
|
-
import {
|
|
29
|
-
|
|
30
|
-
|
|
37
|
+
import {
|
|
38
|
+
createLogger,
|
|
39
|
+
createTaskLog,
|
|
40
|
+
ANSI,
|
|
41
|
+
createDetailedMessage,
|
|
42
|
+
} from "@jsenv/log"
|
|
43
|
+
import { createMagicSource, generateSourcemapFileUrl } from "@jsenv/sourcemap"
|
|
44
|
+
import {
|
|
45
|
+
parseHtmlString,
|
|
46
|
+
stringifyHtmlAst,
|
|
47
|
+
visitHtmlNodes,
|
|
48
|
+
getHtmlNodeAttribute,
|
|
49
|
+
setHtmlNodeAttributes,
|
|
50
|
+
removeHtmlNode,
|
|
51
|
+
} from "@jsenv/ast"
|
|
31
52
|
|
|
32
53
|
import { sortByDependencies } from "../omega/url_graph/sort_by_dependencies.js"
|
|
33
54
|
import { createUrlGraph } from "../omega/url_graph.js"
|
|
@@ -36,16 +57,14 @@ import { jsenvPluginInline } from "../plugins/inline/jsenv_plugin_inline.js"
|
|
|
36
57
|
import { jsenvPluginAsJsClassic } from "../plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js"
|
|
37
58
|
import { getCorePlugins } from "../plugins/plugins.js"
|
|
38
59
|
import { createKitchen } from "../omega/kitchen.js"
|
|
39
|
-
import {
|
|
60
|
+
import { createUrlGraphLoader } from "../omega/url_graph/url_graph_loader.js"
|
|
40
61
|
import { createUrlGraphSummary } from "../omega/url_graph/url_graph_report.js"
|
|
41
62
|
import { isWebWorkerEntryPointReference } from "../omega/web_workers.js"
|
|
42
63
|
|
|
43
64
|
import { GRAPH } from "./graph_utils.js"
|
|
44
65
|
import { createBuilUrlsGenerator } from "./build_urls_generator.js"
|
|
45
|
-
import {
|
|
66
|
+
import { injectVersionMappings } from "./inject_global_version_mappings.js"
|
|
46
67
|
import { createVersionGenerator } from "./version_generator.js"
|
|
47
|
-
import { injectServiceWorkerUrls } from "./inject_service_worker_urls.js"
|
|
48
|
-
import { resyncResourceHints } from "./resync_resource_hints.js"
|
|
49
68
|
|
|
50
69
|
// default runtimeCompat corresponds to
|
|
51
70
|
// "we can keep <script type="module"> intact":
|
|
@@ -151,7 +170,6 @@ export const build = async ({
|
|
|
151
170
|
const runBuild = async ({ signal, logLevel }) => {
|
|
152
171
|
const logger = createLogger({ logLevel })
|
|
153
172
|
const buildOperation = Abort.startOperation()
|
|
154
|
-
const infoLogsAreDisabled = !loggerToLevels(logger).info
|
|
155
173
|
buildOperation.addAbortSignal(signal)
|
|
156
174
|
const entryPointKeys = Object.keys(entryPoints)
|
|
157
175
|
if (entryPointKeys.length === 1) {
|
|
@@ -164,29 +182,27 @@ build ${entryPointKeys.length} entry points`)
|
|
|
164
182
|
const useExplicitJsClassicConversion = entryPointKeys.some((key) =>
|
|
165
183
|
entryPoints[key].includes("?as_js_classic"),
|
|
166
184
|
)
|
|
167
|
-
|
|
185
|
+
const rawRedirections = new Map()
|
|
186
|
+
const bundleRedirections = new Map()
|
|
187
|
+
const bundleInternalRedirections = new Map()
|
|
188
|
+
const finalRedirections = new Map()
|
|
189
|
+
const versioningRedirections = new Map()
|
|
190
|
+
const entryUrls = []
|
|
168
191
|
const rawGraph = createUrlGraph()
|
|
169
|
-
const prebuildTask = createTaskLog("prebuild", {
|
|
170
|
-
disabled: infoLogsAreDisabled,
|
|
171
|
-
})
|
|
172
|
-
const prebuildRedirections = new Map()
|
|
173
192
|
const rawGraphKitchen = createKitchen({
|
|
174
193
|
signal,
|
|
175
|
-
|
|
194
|
+
logLevel,
|
|
176
195
|
rootDirectoryUrl,
|
|
177
196
|
urlGraph: rawGraph,
|
|
178
197
|
scenarios: { build: true },
|
|
179
|
-
sourcemaps,
|
|
180
|
-
sourcemapsSourcesContent,
|
|
181
198
|
runtimeCompat,
|
|
182
|
-
writeGeneratedFiles,
|
|
183
199
|
plugins: [
|
|
184
200
|
...plugins,
|
|
185
201
|
{
|
|
186
202
|
appliesDuring: "build",
|
|
187
203
|
fetchUrlContent: (urlInfo, context) => {
|
|
188
204
|
if (context.reference.original) {
|
|
189
|
-
|
|
205
|
+
rawRedirections.set(
|
|
190
206
|
context.reference.original.url,
|
|
191
207
|
context.reference.url,
|
|
192
208
|
)
|
|
@@ -211,326 +227,97 @@ build ${entryPointKeys.length} entry points`)
|
|
|
211
227
|
transpilation: {
|
|
212
228
|
...transpilation,
|
|
213
229
|
babelHelpersAsImport: !useExplicitJsClassicConversion,
|
|
214
|
-
|
|
230
|
+
jsClassicFallback: false,
|
|
215
231
|
},
|
|
216
232
|
minification,
|
|
217
233
|
bundling,
|
|
218
234
|
}),
|
|
219
235
|
],
|
|
236
|
+
sourcemaps,
|
|
237
|
+
sourcemapsSourcesContent,
|
|
238
|
+
writeGeneratedFiles,
|
|
239
|
+
outDirectoryUrl: new URL(`.jsenv/build/`, rootDirectoryUrl),
|
|
220
240
|
})
|
|
221
|
-
const entryUrls = []
|
|
222
|
-
try {
|
|
223
|
-
await loadUrlGraph({
|
|
224
|
-
operation: buildOperation,
|
|
225
|
-
urlGraph: rawGraph,
|
|
226
|
-
kitchen: rawGraphKitchen,
|
|
227
|
-
writeGeneratedFiles,
|
|
228
|
-
outDirectoryUrl: new URL(`.jsenv/build/`, rootDirectoryUrl),
|
|
229
|
-
startLoading: (cookEntryFile) => {
|
|
230
|
-
Object.keys(entryPoints).forEach((key) => {
|
|
231
|
-
const [, entryUrlInfo] = cookEntryFile({
|
|
232
|
-
trace: {
|
|
233
|
-
message: `"${key}" in entryPoints parameter`,
|
|
234
|
-
},
|
|
235
|
-
type: "entry_point",
|
|
236
|
-
specifier: key,
|
|
237
|
-
})
|
|
238
|
-
entryUrls.push(entryUrlInfo.url)
|
|
239
|
-
entryUrlInfo.filename = entryPoints[key]
|
|
240
|
-
// entryUrlInfo.data.entryPointKey = key
|
|
241
|
-
})
|
|
242
|
-
},
|
|
243
|
-
})
|
|
244
|
-
} catch (e) {
|
|
245
|
-
prebuildTask.fail()
|
|
246
|
-
throw e
|
|
247
|
-
}
|
|
248
|
-
prebuildTask.done()
|
|
249
241
|
|
|
250
242
|
const buildUrlsGenerator = createBuilUrlsGenerator({
|
|
251
243
|
buildDirectoryUrl,
|
|
252
244
|
})
|
|
253
|
-
const
|
|
254
|
-
|
|
255
|
-
const
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
rawGraphKitchen.pluginController.plugins.forEach((plugin) => {
|
|
259
|
-
const bundle = plugin.bundle
|
|
260
|
-
if (!bundle) {
|
|
261
|
-
return
|
|
262
|
-
}
|
|
263
|
-
if (typeof bundle !== "object") {
|
|
264
|
-
throw new Error(
|
|
265
|
-
`bundle must be an object, found "${bundle}" on plugin named "${plugin.name}"`,
|
|
266
|
-
)
|
|
267
|
-
}
|
|
268
|
-
Object.keys(bundle).forEach((type) => {
|
|
269
|
-
const bundleFunction = bundle[type]
|
|
270
|
-
if (!bundleFunction) {
|
|
271
|
-
return
|
|
272
|
-
}
|
|
273
|
-
const bundlerForThatType = bundlers[type]
|
|
274
|
-
if (bundlerForThatType) {
|
|
275
|
-
// first plugin to define a bundle hook wins
|
|
276
|
-
return
|
|
277
|
-
}
|
|
278
|
-
bundlers[type] = {
|
|
279
|
-
plugin,
|
|
280
|
-
bundleFunction: bundle[type],
|
|
281
|
-
urlInfos: [],
|
|
282
|
-
}
|
|
283
|
-
})
|
|
284
|
-
})
|
|
285
|
-
const addToBundlerIfAny = (rawUrlInfo) => {
|
|
286
|
-
const bundler = bundlers[rawUrlInfo.type]
|
|
287
|
-
if (bundler) {
|
|
288
|
-
bundler.urlInfos.push(rawUrlInfo)
|
|
289
|
-
return
|
|
245
|
+
const buildToRawUrls = {}
|
|
246
|
+
// rename "buildDirectoryRedirections"?
|
|
247
|
+
const associateBuildUrlAndRawUrl = (buildUrl, rawUrl, reason) => {
|
|
248
|
+
if (urlIsInsideOf(rawUrl, buildDirectoryUrl)) {
|
|
249
|
+
throw new Error(`raw url must be inside rawGraph, got ${rawUrl}`)
|
|
290
250
|
}
|
|
251
|
+
logger.debug(`build url generated (${reason})
|
|
252
|
+
${ANSI.color(rawUrl, ANSI.GREY)} ->
|
|
253
|
+
${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
254
|
+
`)
|
|
255
|
+
buildToRawUrls[buildUrl] = rawUrl
|
|
291
256
|
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
rawUrlInfo.dependencies.forEach((dependencyUrl) => {
|
|
297
|
-
const dependencyUrlInfo = rawGraph.getUrlInfo(dependencyUrl)
|
|
298
|
-
if (dependencyUrlInfo.isInline) {
|
|
299
|
-
if (dependencyUrlInfo.type === "js_module") {
|
|
300
|
-
// bundle inline script type module deps
|
|
301
|
-
dependencyUrlInfo.references.forEach((inlineScriptRef) => {
|
|
302
|
-
if (inlineScriptRef.type === "js_import_export") {
|
|
303
|
-
const inlineUrlInfo = rawGraph.getUrlInfo(
|
|
304
|
-
inlineScriptRef.url,
|
|
305
|
-
)
|
|
306
|
-
addToBundlerIfAny(inlineUrlInfo)
|
|
307
|
-
}
|
|
308
|
-
})
|
|
309
|
-
}
|
|
310
|
-
// inline content cannot be bundled
|
|
311
|
-
return
|
|
312
|
-
}
|
|
313
|
-
addToBundlerIfAny(dependencyUrlInfo)
|
|
314
|
-
})
|
|
315
|
-
rawUrlInfo.references.forEach((reference) => {
|
|
316
|
-
if (
|
|
317
|
-
reference.isResourceHint &&
|
|
318
|
-
reference.expectedType === "js_module"
|
|
319
|
-
) {
|
|
320
|
-
const referencedUrlInfo = rawGraph.getUrlInfo(reference.url)
|
|
321
|
-
if (
|
|
322
|
-
referencedUrlInfo &&
|
|
323
|
-
// something else than the resource hint is using this url
|
|
324
|
-
referencedUrlInfo.dependents.size > 0
|
|
325
|
-
) {
|
|
326
|
-
addToBundlerIfAny(referencedUrlInfo)
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
})
|
|
330
|
-
return
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
// File referenced with new URL('./file.js', import.meta.url)
|
|
334
|
-
// are entry points that can be bundled
|
|
335
|
-
// For instance we will bundle service worker/workers detected like this
|
|
336
|
-
if (rawUrlInfo.type === "js_module") {
|
|
337
|
-
rawUrlInfo.references.forEach((reference) => {
|
|
338
|
-
if (reference.type === "js_url_specifier") {
|
|
339
|
-
const urlInfo = rawGraph.getUrlInfo(reference.url)
|
|
340
|
-
addToBundlerIfAny(urlInfo)
|
|
341
|
-
}
|
|
342
|
-
})
|
|
343
|
-
}
|
|
344
|
-
})
|
|
345
|
-
const bundleInternalRedirections = {}
|
|
346
|
-
await Object.keys(bundlers).reduce(async (previous, type) => {
|
|
347
|
-
await previous
|
|
348
|
-
const bundler = bundlers[type]
|
|
349
|
-
const urlInfosToBundle = bundler.urlInfos
|
|
350
|
-
if (urlInfosToBundle.length === 0) {
|
|
351
|
-
return
|
|
352
|
-
}
|
|
353
|
-
const bundleTask = createTaskLog(`bundle "${type}"`, {
|
|
354
|
-
disabled: infoLogsAreDisabled,
|
|
355
|
-
})
|
|
356
|
-
try {
|
|
357
|
-
const bundlerGeneratedUrlInfos =
|
|
358
|
-
await rawGraphKitchen.pluginController.callAsyncHook(
|
|
359
|
-
{
|
|
360
|
-
plugin: bundler.plugin,
|
|
361
|
-
hookName: "bundle",
|
|
362
|
-
value: bundler.bundleFunction,
|
|
363
|
-
},
|
|
364
|
-
urlInfosToBundle,
|
|
365
|
-
{
|
|
366
|
-
...rawGraphKitchen.kitchenContext,
|
|
367
|
-
buildDirectoryUrl,
|
|
368
|
-
},
|
|
369
|
-
)
|
|
370
|
-
Object.keys(bundlerGeneratedUrlInfos).forEach((url) => {
|
|
371
|
-
const rawUrlInfo = rawGraph.getUrlInfo(url)
|
|
372
|
-
const bundlerGeneratedUrlInfo = bundlerGeneratedUrlInfos[url]
|
|
373
|
-
const bundleUrlInfo = {
|
|
374
|
-
type,
|
|
375
|
-
subtype: rawUrlInfo ? rawUrlInfo.subtype : undefined,
|
|
376
|
-
isEntryPoint: rawUrlInfo ? rawUrlInfo.isEntryPoint : undefined,
|
|
377
|
-
filename: rawUrlInfo ? rawUrlInfo.filename : undefined,
|
|
378
|
-
originalUrl: rawUrlInfo ? rawUrlInfo.originalUrl : undefined,
|
|
379
|
-
originalContent: rawUrlInfo
|
|
380
|
-
? rawUrlInfo.originalContent
|
|
381
|
-
: undefined,
|
|
382
|
-
...bundlerGeneratedUrlInfo,
|
|
383
|
-
data: {
|
|
384
|
-
...(rawUrlInfo ? rawUrlInfo.data : {}),
|
|
385
|
-
...bundlerGeneratedUrlInfo.data,
|
|
386
|
-
fromBundle: true,
|
|
387
|
-
},
|
|
388
|
-
}
|
|
389
|
-
const buildUrl = buildUrlsGenerator.generate(url, {
|
|
390
|
-
urlInfo: bundleUrlInfo,
|
|
391
|
-
})
|
|
392
|
-
bundleRedirections[url] = buildUrl
|
|
393
|
-
rawUrls[buildUrl] = url
|
|
394
|
-
bundleUrlInfos[buildUrl] = bundleUrlInfo
|
|
395
|
-
if (buildUrl.includes("?")) {
|
|
396
|
-
bundleUrlInfos[asUrlWithoutSearch(buildUrl)] = bundleUrlInfo
|
|
397
|
-
}
|
|
398
|
-
if (bundlerGeneratedUrlInfo.data.bundleRelativeUrl) {
|
|
399
|
-
const urlForBundler = new URL(
|
|
400
|
-
bundlerGeneratedUrlInfo.data.bundleRelativeUrl,
|
|
401
|
-
buildDirectoryUrl,
|
|
402
|
-
).href
|
|
403
|
-
if (urlForBundler !== buildUrl) {
|
|
404
|
-
bundleInternalRedirections[urlForBundler] = buildUrl
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
})
|
|
408
|
-
} catch (e) {
|
|
409
|
-
bundleTask.fail()
|
|
410
|
-
throw e
|
|
411
|
-
}
|
|
412
|
-
bundleTask.done()
|
|
413
|
-
}, Promise.resolve())
|
|
414
|
-
|
|
257
|
+
const buildUrls = new Map()
|
|
258
|
+
const bundleUrlInfos = {}
|
|
259
|
+
const bundlers = {}
|
|
260
|
+
const finalGraph = createUrlGraph()
|
|
415
261
|
const urlAnalysisPlugin = jsenvPluginUrlAnalysis({
|
|
416
262
|
rootDirectoryUrl,
|
|
417
263
|
...urlAnalysis,
|
|
418
264
|
})
|
|
419
|
-
const postBuildRedirections = {}
|
|
420
|
-
const finalGraph = createUrlGraph()
|
|
421
265
|
const finalGraphKitchen = createKitchen({
|
|
422
|
-
|
|
266
|
+
logLevel,
|
|
423
267
|
rootDirectoryUrl,
|
|
424
268
|
urlGraph: finalGraph,
|
|
425
269
|
scenarios: { build: true },
|
|
426
|
-
sourcemaps,
|
|
427
|
-
sourcemapsSourcesContent,
|
|
428
|
-
sourcemapsRelativeSources: !versioning,
|
|
429
270
|
runtimeCompat,
|
|
430
|
-
writeGeneratedFiles,
|
|
431
271
|
plugins: [
|
|
432
272
|
urlAnalysisPlugin,
|
|
433
|
-
jsenvPluginAsJsClassic({
|
|
434
|
-
|
|
273
|
+
jsenvPluginAsJsClassic({
|
|
274
|
+
jsClassicLibrary: false,
|
|
275
|
+
jsClassicFallback: true,
|
|
276
|
+
systemJsInjection: true,
|
|
277
|
+
}),
|
|
278
|
+
jsenvPluginInline({
|
|
279
|
+
fetchInlineUrls: false,
|
|
280
|
+
}),
|
|
435
281
|
{
|
|
436
|
-
name: "jsenv:
|
|
282
|
+
name: "jsenv:build",
|
|
437
283
|
appliesDuring: "build",
|
|
438
284
|
resolveUrl: (reference) => {
|
|
439
|
-
const
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
)
|
|
445
|
-
url = prebuildRedirection
|
|
446
|
-
}
|
|
447
|
-
const bundleRedirection = bundleRedirections[url]
|
|
448
|
-
if (bundleRedirection) {
|
|
449
|
-
logger.debug(
|
|
450
|
-
`\nbundler redirection\n${url} ->\n${bundleRedirection}\n`,
|
|
451
|
-
)
|
|
452
|
-
url = bundleRedirection
|
|
285
|
+
const getUrl = () => {
|
|
286
|
+
if (reference.type === "filesystem") {
|
|
287
|
+
const parentRawUrl = buildToRawUrls[reference.parentUrl]
|
|
288
|
+
const baseUrl = ensurePathnameTrailingSlash(parentRawUrl)
|
|
289
|
+
return new URL(reference.specifier, baseUrl).href
|
|
453
290
|
}
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
`\nbundler internal redirection\n${url} ->\n${bundleInternalRedirection}\n`,
|
|
458
|
-
)
|
|
459
|
-
url = bundleInternalRedirection
|
|
291
|
+
if (reference.specifier[0] === "/") {
|
|
292
|
+
return new URL(reference.specifier.slice(1), buildDirectoryUrl)
|
|
293
|
+
.href
|
|
460
294
|
}
|
|
461
|
-
return
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
if (reference.type === "filesystem") {
|
|
465
|
-
const parentRawUrl = rawUrls[reference.parentUrl]
|
|
466
|
-
const baseUrl = ensurePathnameTrailingSlash(parentRawUrl)
|
|
467
|
-
return performInternalRedirections(
|
|
468
|
-
new URL(reference.specifier, baseUrl).href,
|
|
469
|
-
)
|
|
470
|
-
}
|
|
471
|
-
if (reference.specifier[0] === "/") {
|
|
472
|
-
return performInternalRedirections(
|
|
473
|
-
new URL(reference.specifier.slice(1), buildDirectoryUrl).href,
|
|
474
|
-
)
|
|
475
|
-
}
|
|
476
|
-
return performInternalRedirections(
|
|
477
|
-
new URL(
|
|
295
|
+
return new URL(
|
|
478
296
|
reference.specifier,
|
|
479
297
|
reference.baseUrl || reference.parentUrl,
|
|
480
|
-
).href
|
|
481
|
-
|
|
298
|
+
).href
|
|
299
|
+
}
|
|
300
|
+
let url = getUrl()
|
|
301
|
+
// url = rawRedirections.get(url) || url
|
|
302
|
+
url = bundleRedirections.get(url) || url
|
|
303
|
+
url = bundleInternalRedirections.get(url) || url
|
|
304
|
+
return url
|
|
482
305
|
},
|
|
483
306
|
// redirecting urls into the build directory
|
|
484
307
|
redirectUrl: (reference) => {
|
|
485
308
|
if (!reference.url.startsWith("file:")) {
|
|
486
309
|
return null
|
|
487
310
|
}
|
|
311
|
+
// referenced by resource hint
|
|
312
|
+
// -> keep it untouched, it will be handled by "resync_resource_hints"
|
|
313
|
+
if (reference.isResourceHint) {
|
|
314
|
+
return reference.original ? reference.original.url : null
|
|
315
|
+
}
|
|
488
316
|
// already a build url
|
|
489
|
-
const rawUrl =
|
|
317
|
+
const rawUrl = buildToRawUrls[reference.url]
|
|
490
318
|
if (rawUrl) {
|
|
491
319
|
return reference.url
|
|
492
320
|
}
|
|
493
|
-
// from "js_module_as_js_classic":
|
|
494
|
-
// - injecting "?as_js_classic" for the first time
|
|
495
|
-
// - injecting "?as_js_classic" because the parentUrl has it
|
|
496
|
-
if (reference.original) {
|
|
497
|
-
const referenceOriginalUrl = reference.original.url
|
|
498
|
-
let originalBuildUrl
|
|
499
|
-
if (urlIsInsideOf(referenceOriginalUrl, buildDirectoryUrl)) {
|
|
500
|
-
originalBuildUrl = referenceOriginalUrl
|
|
501
|
-
} else {
|
|
502
|
-
originalBuildUrl = Object.keys(rawUrls).find(
|
|
503
|
-
(key) => rawUrls[key] === referenceOriginalUrl,
|
|
504
|
-
)
|
|
505
|
-
}
|
|
506
|
-
let rawUrl
|
|
507
|
-
if (urlIsInsideOf(reference.url, buildDirectoryUrl)) {
|
|
508
|
-
const originalBuildUrl =
|
|
509
|
-
postBuildRedirections[referenceOriginalUrl]
|
|
510
|
-
rawUrl = originalBuildUrl
|
|
511
|
-
? rawUrls[originalBuildUrl]
|
|
512
|
-
: reference.url
|
|
513
|
-
} else {
|
|
514
|
-
rawUrl = reference.url
|
|
515
|
-
}
|
|
516
|
-
// the url info do not exists yet (it will be created after this "normalize" hook)
|
|
517
|
-
// And the content will be generated when url is cooked by url graph loader.
|
|
518
|
-
// Here we just want to reserve an url for that file
|
|
519
|
-
const buildUrl = buildUrlsGenerator.generate(rawUrl, {
|
|
520
|
-
urlInfo: {
|
|
521
|
-
data: reference.data,
|
|
522
|
-
isEntryPoint:
|
|
523
|
-
reference.isEntryPoint ||
|
|
524
|
-
isWebWorkerEntryPointReference(reference),
|
|
525
|
-
type: reference.expectedType,
|
|
526
|
-
subtype: reference.expectedSubtype,
|
|
527
|
-
filename: reference.filename,
|
|
528
|
-
},
|
|
529
|
-
})
|
|
530
|
-
postBuildRedirections[originalBuildUrl] = buildUrl
|
|
531
|
-
rawUrls[buildUrl] = rawUrl
|
|
532
|
-
return buildUrl
|
|
533
|
-
}
|
|
534
321
|
if (reference.isInline) {
|
|
535
322
|
const rawUrlInfo = GRAPH.find(rawGraph, (rawUrlInfo) => {
|
|
536
323
|
if (!rawUrlInfo.isInline) {
|
|
@@ -555,7 +342,51 @@ build ${entryPointKeys.length} entry points`)
|
|
|
555
342
|
urlInfo: rawUrlInfo,
|
|
556
343
|
parentUrlInfo,
|
|
557
344
|
})
|
|
558
|
-
|
|
345
|
+
associateBuildUrlAndRawUrl(
|
|
346
|
+
buildUrl,
|
|
347
|
+
rawUrlInfo.url,
|
|
348
|
+
"inline content",
|
|
349
|
+
)
|
|
350
|
+
return buildUrl
|
|
351
|
+
}
|
|
352
|
+
// from "js_module_as_js_classic":
|
|
353
|
+
// - injecting "?as_js_classic" for the first time
|
|
354
|
+
// - injecting "?as_js_classic" because the parentUrl has it
|
|
355
|
+
if (reference.original) {
|
|
356
|
+
const urlBeforeRedirect = reference.original.url
|
|
357
|
+
const urlAfterRedirect = reference.url
|
|
358
|
+
const isEntryPoint =
|
|
359
|
+
reference.isEntryPoint ||
|
|
360
|
+
isWebWorkerEntryPointReference(reference)
|
|
361
|
+
// the url info do not exists yet (it will be created after this "redirectUrl" hook)
|
|
362
|
+
// And the content will be generated when url is cooked by url graph loader.
|
|
363
|
+
// Here we just want to reserve an url for that file
|
|
364
|
+
const urlInfo = {
|
|
365
|
+
data: reference.data,
|
|
366
|
+
isEntryPoint,
|
|
367
|
+
type: reference.expectedType,
|
|
368
|
+
subtype: reference.expectedSubtype,
|
|
369
|
+
filename: reference.filename,
|
|
370
|
+
}
|
|
371
|
+
if (urlIsInsideOf(urlBeforeRedirect, buildDirectoryUrl)) {
|
|
372
|
+
// the redirection happened on a build url, happens due to:
|
|
373
|
+
// 1. bundling
|
|
374
|
+
const buildUrl = buildUrlsGenerator.generate(urlAfterRedirect, {
|
|
375
|
+
urlInfo,
|
|
376
|
+
})
|
|
377
|
+
finalRedirections.set(urlBeforeRedirect, buildUrl)
|
|
378
|
+
return buildUrl
|
|
379
|
+
}
|
|
380
|
+
const rawUrl = urlAfterRedirect
|
|
381
|
+
const buildUrl = buildUrlsGenerator.generate(rawUrl, {
|
|
382
|
+
urlInfo,
|
|
383
|
+
})
|
|
384
|
+
finalRedirections.set(urlBeforeRedirect, buildUrl)
|
|
385
|
+
associateBuildUrlAndRawUrl(
|
|
386
|
+
buildUrl,
|
|
387
|
+
rawUrl,
|
|
388
|
+
"redirected during postbuild",
|
|
389
|
+
)
|
|
559
390
|
return buildUrl
|
|
560
391
|
}
|
|
561
392
|
// from "js_module_as_js_classic":
|
|
@@ -567,20 +398,34 @@ build ${entryPointKeys.length} entry points`)
|
|
|
567
398
|
type: "js_classic",
|
|
568
399
|
},
|
|
569
400
|
})
|
|
570
|
-
|
|
401
|
+
associateBuildUrlAndRawUrl(
|
|
402
|
+
buildUrl,
|
|
403
|
+
reference.url,
|
|
404
|
+
"injected during postbuild",
|
|
405
|
+
)
|
|
406
|
+
finalRedirections.set(buildUrl, buildUrl)
|
|
571
407
|
return buildUrl
|
|
572
408
|
}
|
|
573
409
|
const rawUrlInfo = rawGraph.getUrlInfo(reference.url)
|
|
574
410
|
const parentUrlInfo = finalGraph.getUrlInfo(reference.parentUrl)
|
|
575
411
|
// files from root directory but not given to rollup nor postcss
|
|
576
412
|
if (rawUrlInfo) {
|
|
577
|
-
const
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
413
|
+
const referencedUrlObject = new URL(reference.url)
|
|
414
|
+
referencedUrlObject.searchParams.delete("as_js_classic_library")
|
|
415
|
+
const buildUrl = buildUrlsGenerator.generate(
|
|
416
|
+
referencedUrlObject.href,
|
|
417
|
+
{
|
|
418
|
+
urlInfo: rawUrlInfo,
|
|
419
|
+
parentUrlInfo,
|
|
420
|
+
},
|
|
421
|
+
)
|
|
422
|
+
associateBuildUrlAndRawUrl(buildUrl, rawUrlInfo.url, "raw file")
|
|
582
423
|
if (buildUrl.includes("?")) {
|
|
583
|
-
|
|
424
|
+
associateBuildUrlAndRawUrl(
|
|
425
|
+
asUrlWithoutSearch(buildUrl),
|
|
426
|
+
rawUrlInfo.url,
|
|
427
|
+
"raw file",
|
|
428
|
+
)
|
|
584
429
|
}
|
|
585
430
|
return buildUrl
|
|
586
431
|
}
|
|
@@ -606,21 +451,26 @@ build ${entryPointKeys.length} entry points`)
|
|
|
606
451
|
}
|
|
607
452
|
return null
|
|
608
453
|
}
|
|
454
|
+
if (reference.isResourceHint) {
|
|
455
|
+
return null
|
|
456
|
+
}
|
|
609
457
|
if (!urlIsInsideOf(reference.generatedUrl, buildDirectoryUrl)) {
|
|
610
458
|
throw new Error(
|
|
611
459
|
`urls should be inside build directory at this stage, found "${reference.url}"`,
|
|
612
460
|
)
|
|
613
461
|
}
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
462
|
+
const generatedUrlObject = new URL(reference.generatedUrl)
|
|
463
|
+
generatedUrlObject.searchParams.delete("as_js_classic")
|
|
464
|
+
generatedUrlObject.searchParams.delete("as_js_classic_library")
|
|
465
|
+
generatedUrlObject.searchParams.delete("as_json_module")
|
|
466
|
+
generatedUrlObject.searchParams.delete("as_css_module")
|
|
467
|
+
generatedUrlObject.searchParams.delete("as_text_module")
|
|
468
|
+
generatedUrlObject.hash = ""
|
|
469
|
+
const generatedUrl = generatedUrlObject.href
|
|
620
470
|
let specifier
|
|
621
471
|
if (baseUrl === "./") {
|
|
622
472
|
const relativeUrl = urlToRelativeUrl(
|
|
623
|
-
|
|
473
|
+
generatedUrl,
|
|
624
474
|
reference.parentUrl === rootDirectoryUrl
|
|
625
475
|
? buildDirectoryUrl
|
|
626
476
|
: reference.parentUrl,
|
|
@@ -632,26 +482,32 @@ build ${entryPointKeys.length} entry points`)
|
|
|
632
482
|
// if a file is in the same directory we could prefer the relative notation
|
|
633
483
|
// but to keep things simple let's keep the "absolutely relative" to baseUrl for now
|
|
634
484
|
specifier = `${baseUrl}${urlToRelativeUrl(
|
|
635
|
-
|
|
485
|
+
generatedUrl,
|
|
636
486
|
buildDirectoryUrl,
|
|
637
487
|
)}`
|
|
638
488
|
}
|
|
639
|
-
buildUrls
|
|
489
|
+
buildUrls.set(specifier, reference.generatedUrl)
|
|
640
490
|
return specifier
|
|
641
491
|
},
|
|
642
492
|
fetchUrlContent: async (finalUrlInfo, context) => {
|
|
643
493
|
const fromBundleOrRawGraph = (url) => {
|
|
644
494
|
const bundleUrlInfo = bundleUrlInfos[url]
|
|
645
495
|
if (bundleUrlInfo) {
|
|
646
|
-
logger.debug(`fetching from bundle ${url}`)
|
|
496
|
+
// logger.debug(`fetching from bundle ${url}`)
|
|
647
497
|
return bundleUrlInfo
|
|
648
498
|
}
|
|
649
|
-
const rawUrl =
|
|
499
|
+
const rawUrl = buildToRawUrls[url] || url
|
|
650
500
|
const rawUrlInfo = rawGraph.getUrlInfo(rawUrl)
|
|
651
501
|
if (!rawUrlInfo) {
|
|
652
|
-
throw new Error(
|
|
502
|
+
throw new Error(
|
|
503
|
+
createDetailedMessage(`Cannot find url`, {
|
|
504
|
+
url,
|
|
505
|
+
"raw urls": Object.values(buildToRawUrls),
|
|
506
|
+
"build urls": Object.keys(buildToRawUrls),
|
|
507
|
+
}),
|
|
508
|
+
)
|
|
653
509
|
}
|
|
654
|
-
logger.debug(`fetching from raw graph ${url}`)
|
|
510
|
+
// logger.debug(`fetching from raw graph ${url}`)
|
|
655
511
|
if (rawUrlInfo.isInline) {
|
|
656
512
|
// Inline content, such as <script> inside html, is transformed during the previous phase.
|
|
657
513
|
// If we read the inline content it would be considered as the original content.
|
|
@@ -667,24 +523,28 @@ build ${entryPointKeys.length} entry points`)
|
|
|
667
523
|
}
|
|
668
524
|
return rawUrlInfo
|
|
669
525
|
}
|
|
526
|
+
const { reference } = context
|
|
670
527
|
// reference injected during "postbuild":
|
|
671
528
|
// - happens for "as_js_classic" injecting "s.js"
|
|
672
|
-
if (
|
|
529
|
+
if (reference.injected) {
|
|
673
530
|
const [ref, rawUrlInfo] = rawGraphKitchen.injectReference({
|
|
674
|
-
type:
|
|
675
|
-
expectedType:
|
|
676
|
-
expectedSubtype:
|
|
677
|
-
parentUrl:
|
|
678
|
-
specifier:
|
|
531
|
+
type: reference.type,
|
|
532
|
+
expectedType: reference.expectedType,
|
|
533
|
+
expectedSubtype: reference.expectedSubtype,
|
|
534
|
+
parentUrl: buildToRawUrls[reference.parentUrl],
|
|
535
|
+
specifier: reference.specifier,
|
|
679
536
|
injected: true,
|
|
680
537
|
})
|
|
681
538
|
await rawGraphKitchen.cook(rawUrlInfo, { reference: ref })
|
|
682
539
|
return rawUrlInfo
|
|
683
540
|
}
|
|
541
|
+
if (reference.isInline) {
|
|
542
|
+
return fromBundleOrRawGraph(reference.url)
|
|
543
|
+
}
|
|
684
544
|
// reference updated during "postbuild":
|
|
685
545
|
// - happens for "as_js_classic"
|
|
686
|
-
if (
|
|
687
|
-
return fromBundleOrRawGraph(
|
|
546
|
+
if (reference.original) {
|
|
547
|
+
return fromBundleOrRawGraph(reference.original.url)
|
|
688
548
|
}
|
|
689
549
|
return fromBundleOrRawGraph(finalUrlInfo.url)
|
|
690
550
|
},
|
|
@@ -707,115 +567,750 @@ build ${entryPointKeys.length} entry points`)
|
|
|
707
567
|
},
|
|
708
568
|
},
|
|
709
569
|
],
|
|
570
|
+
sourcemaps,
|
|
571
|
+
sourcemapsSourcesContent,
|
|
572
|
+
sourcemapsRelativeSources: !versioning,
|
|
573
|
+
writeGeneratedFiles,
|
|
574
|
+
outDirectoryUrl: new URL(".jsenv/postbuild/", rootDirectoryUrl),
|
|
710
575
|
})
|
|
711
|
-
const
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
576
|
+
const finalEntryUrls = []
|
|
577
|
+
|
|
578
|
+
craft: {
|
|
579
|
+
const loadTask = createTaskLog("load", {
|
|
580
|
+
disabled: logger.levels.debug || !logger.levels.info,
|
|
581
|
+
})
|
|
582
|
+
try {
|
|
583
|
+
if (writeGeneratedFiles) {
|
|
584
|
+
await ensureEmptyDirectory(new URL(`.jsenv/build/`, rootDirectoryUrl))
|
|
585
|
+
}
|
|
586
|
+
const rawUrlGraphLoader = createUrlGraphLoader(
|
|
587
|
+
rawGraphKitchen.kitchenContext,
|
|
588
|
+
)
|
|
589
|
+
Object.keys(entryPoints).forEach((key) => {
|
|
590
|
+
const [entryReference, entryUrlInfo] =
|
|
591
|
+
rawGraphKitchen.kitchenContext.prepareEntryPoint({
|
|
592
|
+
trace: { message: `"${key}" in entryPoints parameter` },
|
|
593
|
+
parentUrl: rootDirectoryUrl,
|
|
725
594
|
type: "entry_point",
|
|
726
|
-
specifier:
|
|
595
|
+
specifier: key,
|
|
727
596
|
})
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
597
|
+
entryUrls.push(entryUrlInfo.url)
|
|
598
|
+
entryUrlInfo.filename = entryPoints[key]
|
|
599
|
+
rawUrlGraphLoader.load(entryUrlInfo, { reference: entryReference })
|
|
600
|
+
})
|
|
601
|
+
await rawUrlGraphLoader.getAllLoadDonePromise(buildOperation)
|
|
602
|
+
} catch (e) {
|
|
603
|
+
loadTask.fail()
|
|
604
|
+
throw e
|
|
605
|
+
}
|
|
606
|
+
loadTask.done()
|
|
735
607
|
}
|
|
736
|
-
buildTask.done()
|
|
737
608
|
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
609
|
+
shape: {
|
|
610
|
+
bundle: {
|
|
611
|
+
rawGraphKitchen.pluginController.plugins.forEach((plugin) => {
|
|
612
|
+
const bundle = plugin.bundle
|
|
613
|
+
if (!bundle) {
|
|
614
|
+
return
|
|
615
|
+
}
|
|
616
|
+
if (typeof bundle !== "object") {
|
|
617
|
+
throw new Error(
|
|
618
|
+
`bundle must be an object, found "${bundle}" on plugin named "${plugin.name}"`,
|
|
619
|
+
)
|
|
620
|
+
}
|
|
621
|
+
Object.keys(bundle).forEach((type) => {
|
|
622
|
+
const bundleFunction = bundle[type]
|
|
623
|
+
if (!bundleFunction) {
|
|
624
|
+
return
|
|
625
|
+
}
|
|
626
|
+
const bundlerForThatType = bundlers[type]
|
|
627
|
+
if (bundlerForThatType) {
|
|
628
|
+
// first plugin to define a bundle hook wins
|
|
629
|
+
return
|
|
630
|
+
}
|
|
631
|
+
bundlers[type] = {
|
|
632
|
+
plugin,
|
|
633
|
+
bundleFunction: bundle[type],
|
|
634
|
+
urlInfos: [],
|
|
635
|
+
}
|
|
636
|
+
})
|
|
637
|
+
})
|
|
638
|
+
const addToBundlerIfAny = (rawUrlInfo) => {
|
|
639
|
+
const bundler = bundlers[rawUrlInfo.type]
|
|
640
|
+
if (bundler) {
|
|
641
|
+
bundler.urlInfos.push(rawUrlInfo)
|
|
642
|
+
return
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
GRAPH.forEach(rawGraph, (rawUrlInfo) => {
|
|
646
|
+
if (rawUrlInfo.isEntryPoint) {
|
|
647
|
+
addToBundlerIfAny(rawUrlInfo)
|
|
648
|
+
if (rawUrlInfo.type === "html") {
|
|
649
|
+
rawUrlInfo.dependencies.forEach((dependencyUrl) => {
|
|
650
|
+
const dependencyUrlInfo = rawGraph.getUrlInfo(dependencyUrl)
|
|
651
|
+
if (dependencyUrlInfo.isInline) {
|
|
652
|
+
if (dependencyUrlInfo.type === "js_module") {
|
|
653
|
+
// bundle inline script type module deps
|
|
654
|
+
dependencyUrlInfo.references.forEach((inlineScriptRef) => {
|
|
655
|
+
if (inlineScriptRef.type === "js_import_export") {
|
|
656
|
+
const inlineUrlInfo = rawGraph.getUrlInfo(
|
|
657
|
+
inlineScriptRef.url,
|
|
658
|
+
)
|
|
659
|
+
addToBundlerIfAny(inlineUrlInfo)
|
|
660
|
+
}
|
|
661
|
+
})
|
|
662
|
+
}
|
|
663
|
+
// inline content cannot be bundled
|
|
664
|
+
return
|
|
665
|
+
}
|
|
666
|
+
addToBundlerIfAny(dependencyUrlInfo)
|
|
667
|
+
})
|
|
668
|
+
rawUrlInfo.references.forEach((reference) => {
|
|
669
|
+
if (
|
|
670
|
+
reference.isResourceHint &&
|
|
671
|
+
reference.expectedType === "js_module"
|
|
672
|
+
) {
|
|
673
|
+
const referencedUrlInfo = rawGraph.getUrlInfo(reference.url)
|
|
674
|
+
if (
|
|
675
|
+
referencedUrlInfo &&
|
|
676
|
+
// something else than the resource hint is using this url
|
|
677
|
+
referencedUrlInfo.dependents.size > 0
|
|
678
|
+
) {
|
|
679
|
+
addToBundlerIfAny(referencedUrlInfo)
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
})
|
|
683
|
+
return
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
// File referenced with new URL('./file.js', import.meta.url)
|
|
687
|
+
// are entry points that can be bundled
|
|
688
|
+
// For instance we will bundle service worker/workers detected like this
|
|
689
|
+
if (rawUrlInfo.type === "js_module") {
|
|
690
|
+
rawUrlInfo.references.forEach((reference) => {
|
|
691
|
+
if (reference.type === "js_url_specifier") {
|
|
692
|
+
const urlInfo = rawGraph.getUrlInfo(reference.url)
|
|
693
|
+
addToBundlerIfAny(urlInfo)
|
|
694
|
+
}
|
|
695
|
+
})
|
|
696
|
+
}
|
|
697
|
+
})
|
|
698
|
+
await Object.keys(bundlers).reduce(async (previous, type) => {
|
|
699
|
+
await previous
|
|
700
|
+
const bundler = bundlers[type]
|
|
701
|
+
const urlInfosToBundle = bundler.urlInfos
|
|
702
|
+
if (urlInfosToBundle.length === 0) {
|
|
703
|
+
return
|
|
704
|
+
}
|
|
705
|
+
const bundleTask = createTaskLog(`bundle "${type}"`, {
|
|
706
|
+
disabled: logger.levels.debug || !logger.levels.info,
|
|
707
|
+
})
|
|
708
|
+
try {
|
|
709
|
+
const bundlerGeneratedUrlInfos =
|
|
710
|
+
await rawGraphKitchen.pluginController.callAsyncHook(
|
|
711
|
+
{
|
|
712
|
+
plugin: bundler.plugin,
|
|
713
|
+
hookName: "bundle",
|
|
714
|
+
value: bundler.bundleFunction,
|
|
715
|
+
},
|
|
716
|
+
urlInfosToBundle,
|
|
717
|
+
{
|
|
718
|
+
...rawGraphKitchen.kitchenContext,
|
|
719
|
+
buildDirectoryUrl,
|
|
720
|
+
},
|
|
721
|
+
)
|
|
722
|
+
Object.keys(bundlerGeneratedUrlInfos).forEach((url) => {
|
|
723
|
+
const rawUrlInfo = rawGraph.getUrlInfo(url)
|
|
724
|
+
const bundlerGeneratedUrlInfo = bundlerGeneratedUrlInfos[url]
|
|
725
|
+
const bundleUrlInfo = {
|
|
726
|
+
type,
|
|
727
|
+
subtype: rawUrlInfo ? rawUrlInfo.subtype : undefined,
|
|
728
|
+
isEntryPoint: rawUrlInfo ? rawUrlInfo.isEntryPoint : undefined,
|
|
729
|
+
filename: rawUrlInfo ? rawUrlInfo.filename : undefined,
|
|
730
|
+
originalUrl: rawUrlInfo ? rawUrlInfo.originalUrl : undefined,
|
|
731
|
+
originalContent: rawUrlInfo
|
|
732
|
+
? rawUrlInfo.originalContent
|
|
733
|
+
: undefined,
|
|
734
|
+
...bundlerGeneratedUrlInfo,
|
|
735
|
+
data: {
|
|
736
|
+
...(rawUrlInfo ? rawUrlInfo.data : {}),
|
|
737
|
+
...bundlerGeneratedUrlInfo.data,
|
|
738
|
+
fromBundle: true,
|
|
739
|
+
},
|
|
740
|
+
}
|
|
741
|
+
if (bundlerGeneratedUrlInfo.sourceUrls) {
|
|
742
|
+
bundlerGeneratedUrlInfo.sourceUrls.forEach((sourceUrl) => {
|
|
743
|
+
const rawUrlInfo = rawGraph.getUrlInfo(sourceUrl)
|
|
744
|
+
if (rawUrlInfo) {
|
|
745
|
+
rawUrlInfo.data.bundled = true
|
|
746
|
+
}
|
|
747
|
+
})
|
|
748
|
+
}
|
|
749
|
+
const buildUrl = buildUrlsGenerator.generate(url, {
|
|
750
|
+
urlInfo: bundleUrlInfo,
|
|
751
|
+
})
|
|
752
|
+
bundleRedirections.set(url, buildUrl)
|
|
753
|
+
if (urlIsInsideOf(url, buildDirectoryUrl)) {
|
|
754
|
+
// chunk generated by rollup to share code
|
|
755
|
+
} else {
|
|
756
|
+
associateBuildUrlAndRawUrl(buildUrl, url, "bundle")
|
|
757
|
+
}
|
|
758
|
+
bundleUrlInfos[buildUrl] = bundleUrlInfo
|
|
759
|
+
if (buildUrl.includes("?")) {
|
|
760
|
+
bundleUrlInfos[asUrlWithoutSearch(buildUrl)] = bundleUrlInfo
|
|
761
|
+
}
|
|
762
|
+
if (bundlerGeneratedUrlInfo.data.bundleRelativeUrl) {
|
|
763
|
+
const urlForBundler = new URL(
|
|
764
|
+
bundlerGeneratedUrlInfo.data.bundleRelativeUrl,
|
|
765
|
+
buildDirectoryUrl,
|
|
766
|
+
).href
|
|
767
|
+
if (urlForBundler !== buildUrl) {
|
|
768
|
+
bundleInternalRedirections.set(urlForBundler, buildUrl)
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
})
|
|
772
|
+
} catch (e) {
|
|
773
|
+
bundleTask.fail()
|
|
774
|
+
throw e
|
|
775
|
+
}
|
|
776
|
+
bundleTask.done()
|
|
777
|
+
}, Promise.resolve())
|
|
767
778
|
}
|
|
768
|
-
|
|
769
|
-
|
|
779
|
+
reload_in_build_directory: {
|
|
780
|
+
const buildTask = createTaskLog("build", {
|
|
781
|
+
disabled: logger.levels.debug || !logger.levels.info,
|
|
782
|
+
})
|
|
783
|
+
try {
|
|
784
|
+
if (writeGeneratedFiles) {
|
|
785
|
+
await ensureEmptyDirectory(
|
|
786
|
+
new URL(`.jsenv/postbuild/`, rootDirectoryUrl),
|
|
787
|
+
)
|
|
788
|
+
}
|
|
789
|
+
const finalUrlGraphLoader = createUrlGraphLoader(
|
|
790
|
+
finalGraphKitchen.kitchenContext,
|
|
791
|
+
)
|
|
792
|
+
entryUrls.forEach((entryUrl) => {
|
|
793
|
+
const [finalEntryReference, finalEntryUrlInfo] =
|
|
794
|
+
finalGraphKitchen.kitchenContext.prepareEntryPoint({
|
|
795
|
+
trace: { message: `entryPoint` },
|
|
796
|
+
parentUrl: rootDirectoryUrl,
|
|
797
|
+
type: "entry_point",
|
|
798
|
+
specifier: entryUrl,
|
|
799
|
+
})
|
|
800
|
+
finalEntryUrls.push(finalEntryUrlInfo.url)
|
|
801
|
+
finalUrlGraphLoader.load(finalEntryUrlInfo, {
|
|
802
|
+
reference: finalEntryReference,
|
|
803
|
+
})
|
|
804
|
+
})
|
|
805
|
+
await finalUrlGraphLoader.getAllLoadDonePromise(buildOperation)
|
|
806
|
+
} catch (e) {
|
|
807
|
+
buildTask.fail()
|
|
808
|
+
throw e
|
|
809
|
+
}
|
|
810
|
+
buildTask.done()
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
refine: {
|
|
815
|
+
inject_version_in_urls: {
|
|
816
|
+
if (!versioning) {
|
|
817
|
+
break inject_version_in_urls
|
|
818
|
+
}
|
|
819
|
+
const versioningTask = createTaskLog("inject version in urls", {
|
|
820
|
+
disabled: logger.levels.debug || !logger.levels.info,
|
|
821
|
+
})
|
|
822
|
+
try {
|
|
823
|
+
const urlsSorted = sortByDependencies(finalGraph.toObject())
|
|
824
|
+
urlsSorted.forEach((url) => {
|
|
825
|
+
if (url.startsWith("data:")) {
|
|
826
|
+
return
|
|
827
|
+
}
|
|
828
|
+
const urlInfo = finalGraph.getUrlInfo(url)
|
|
829
|
+
if (urlInfo.type === "sourcemap") {
|
|
830
|
+
return
|
|
831
|
+
}
|
|
832
|
+
// ignore:
|
|
833
|
+
// - inline files:
|
|
834
|
+
// they are already taken into account in the file where they appear
|
|
835
|
+
// - ignored files:
|
|
836
|
+
// we don't know their content
|
|
837
|
+
// - unused files without reference
|
|
838
|
+
// File updated such as style.css -> style.css.js or file.js->file.nomodule.js
|
|
839
|
+
// Are used at some point just to be discarded later because they need to be converted
|
|
840
|
+
// There is no need to version them and we could not because the file have been ignored
|
|
841
|
+
// so their content is unknown
|
|
842
|
+
if (urlInfo.isInline) {
|
|
843
|
+
return
|
|
844
|
+
}
|
|
845
|
+
if (!urlInfo.shouldHandle) {
|
|
846
|
+
return
|
|
847
|
+
}
|
|
848
|
+
if (!urlInfo.isEntryPoint && urlInfo.dependents.size === 0) {
|
|
849
|
+
return
|
|
850
|
+
}
|
|
851
|
+
const urlContent =
|
|
852
|
+
urlInfo.type === "html"
|
|
853
|
+
? stringifyHtmlAst(
|
|
854
|
+
parseHtmlString(urlInfo.content, {
|
|
855
|
+
storeOriginalPositions: false,
|
|
856
|
+
}),
|
|
857
|
+
{ cleanupJsenvAttributes: true },
|
|
858
|
+
)
|
|
859
|
+
: urlInfo.content
|
|
860
|
+
const versionGenerator = createVersionGenerator()
|
|
861
|
+
versionGenerator.augmentWithContent({
|
|
862
|
+
content: urlContent,
|
|
863
|
+
contentType: urlInfo.contentType,
|
|
864
|
+
lineBreakNormalization,
|
|
865
|
+
})
|
|
866
|
+
urlInfo.dependencies.forEach((dependencyUrl) => {
|
|
867
|
+
// this dependency is inline
|
|
868
|
+
if (dependencyUrl.startsWith("data:")) {
|
|
869
|
+
return
|
|
870
|
+
}
|
|
871
|
+
const dependencyUrlInfo = finalGraph.getUrlInfo(dependencyUrl)
|
|
872
|
+
if (
|
|
873
|
+
// this content is part of the file, no need to take into account twice
|
|
874
|
+
dependencyUrlInfo.isInline ||
|
|
875
|
+
// this dependency content is not known
|
|
876
|
+
!dependencyUrlInfo.shouldHandle
|
|
877
|
+
) {
|
|
878
|
+
return
|
|
879
|
+
}
|
|
880
|
+
if (dependencyUrlInfo.data.version) {
|
|
881
|
+
versionGenerator.augmentWithDependencyVersion(
|
|
882
|
+
dependencyUrlInfo.data.version,
|
|
883
|
+
)
|
|
884
|
+
} else {
|
|
885
|
+
// because all dependencies are know, if the dependency has no version
|
|
886
|
+
// it means there is a circular dependency between this file
|
|
887
|
+
// and it's dependency
|
|
888
|
+
// in that case we'll use the dependency content
|
|
889
|
+
versionGenerator.augmentWithContent({
|
|
890
|
+
content: dependencyUrlInfo.content,
|
|
891
|
+
contentType: dependencyUrlInfo.contentType,
|
|
892
|
+
lineBreakNormalization,
|
|
893
|
+
})
|
|
894
|
+
}
|
|
895
|
+
})
|
|
896
|
+
urlInfo.data.version = versionGenerator.generate()
|
|
897
|
+
|
|
898
|
+
const buildUrlObject = new URL(urlInfo.url)
|
|
899
|
+
// remove ?as_js_classic as
|
|
900
|
+
// this information is already hold into ".nomodule"
|
|
901
|
+
buildUrlObject.searchParams.delete("as_js_classic")
|
|
902
|
+
buildUrlObject.searchParams.delete("as_js_classic_library")
|
|
903
|
+
buildUrlObject.searchParams.delete("as_json_module")
|
|
904
|
+
buildUrlObject.searchParams.delete("as_css_module")
|
|
905
|
+
buildUrlObject.searchParams.delete("as_text_module")
|
|
906
|
+
const buildUrl = buildUrlObject.href
|
|
907
|
+
finalRedirections.set(urlInfo.url, buildUrl)
|
|
908
|
+
urlInfo.data.versionedUrl = normalizeUrl(
|
|
909
|
+
injectVersionIntoBuildUrl({
|
|
910
|
+
buildUrl,
|
|
911
|
+
version: urlInfo.data.version,
|
|
912
|
+
versioningMethod,
|
|
913
|
+
}),
|
|
914
|
+
)
|
|
915
|
+
})
|
|
916
|
+
const versionMappings = {}
|
|
917
|
+
const usedVersionMappings = new Set()
|
|
918
|
+
const versioningKitchen = createKitchen({
|
|
919
|
+
logLevel: logger.level,
|
|
920
|
+
rootDirectoryUrl: buildDirectoryUrl,
|
|
921
|
+
urlGraph: finalGraph,
|
|
922
|
+
scenarios: { build: true },
|
|
923
|
+
runtimeCompat,
|
|
924
|
+
plugins: [
|
|
925
|
+
urlAnalysisPlugin,
|
|
926
|
+
jsenvPluginInline({
|
|
927
|
+
fetchInlineUrls: false,
|
|
928
|
+
analyzeConvertedScripts: true, // to be able to version their urls
|
|
929
|
+
allowEscapeForVersioning: true,
|
|
930
|
+
}),
|
|
931
|
+
{
|
|
932
|
+
name: "jsenv:versioning",
|
|
933
|
+
appliesDuring: "build",
|
|
934
|
+
resolveUrl: (reference) => {
|
|
935
|
+
const buildUrl = buildUrls.get(reference.specifier)
|
|
936
|
+
if (buildUrl) {
|
|
937
|
+
return buildUrl
|
|
938
|
+
}
|
|
939
|
+
const urlObject = new URL(
|
|
940
|
+
reference.specifier,
|
|
941
|
+
reference.baseUrl || reference.parentUrl,
|
|
942
|
+
)
|
|
943
|
+
const url = urlObject.href
|
|
944
|
+
// during versioning we revisit the deps
|
|
945
|
+
// but the code used to enforce trailing slash on directories
|
|
946
|
+
// is not applied because "jsenv:file_url_resolution" is not used
|
|
947
|
+
// so here we search if the url with a trailing slash exists
|
|
948
|
+
if (
|
|
949
|
+
reference.type === "filesystem" &&
|
|
950
|
+
!urlObject.pathname.endsWith("/")
|
|
951
|
+
) {
|
|
952
|
+
const urlWithTrailingSlash = `${url}/`
|
|
953
|
+
const specifier = findKey(buildUrls, urlWithTrailingSlash)
|
|
954
|
+
if (specifier) {
|
|
955
|
+
return urlWithTrailingSlash
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
return url
|
|
959
|
+
},
|
|
960
|
+
formatUrl: (reference) => {
|
|
961
|
+
if (!reference.shouldHandle) {
|
|
962
|
+
if (reference.generatedUrl.startsWith("ignore:")) {
|
|
963
|
+
return reference.generatedUrl.slice("ignore:".length)
|
|
964
|
+
}
|
|
965
|
+
return null
|
|
966
|
+
}
|
|
967
|
+
if (reference.isInline || reference.url.startsWith("data:")) {
|
|
968
|
+
return null
|
|
969
|
+
}
|
|
970
|
+
if (reference.isResourceHint) {
|
|
971
|
+
return null
|
|
972
|
+
}
|
|
973
|
+
// specifier comes from "normalize" hook done a bit earlier in this file
|
|
974
|
+
// we want to get back their build url to access their infos
|
|
975
|
+
const referencedUrlInfo = finalGraph.getUrlInfo(reference.url)
|
|
976
|
+
if (!canUseVersionedUrl(referencedUrlInfo)) {
|
|
977
|
+
return reference.specifier
|
|
978
|
+
}
|
|
979
|
+
if (!referencedUrlInfo.shouldHandle) {
|
|
980
|
+
return null
|
|
981
|
+
}
|
|
982
|
+
const versionedUrl = referencedUrlInfo.data.versionedUrl
|
|
983
|
+
if (!versionedUrl) {
|
|
984
|
+
// happens for sourcemap
|
|
985
|
+
return `${baseUrl}${urlToRelativeUrl(
|
|
986
|
+
referencedUrlInfo.url,
|
|
987
|
+
buildDirectoryUrl,
|
|
988
|
+
)}`
|
|
989
|
+
}
|
|
990
|
+
const versionedSpecifier = `${baseUrl}${urlToRelativeUrl(
|
|
991
|
+
versionedUrl,
|
|
992
|
+
buildDirectoryUrl,
|
|
993
|
+
)}`
|
|
994
|
+
versionMappings[reference.specifier] = versionedSpecifier
|
|
995
|
+
versioningRedirections.set(reference.url, versionedUrl)
|
|
996
|
+
buildUrls.set(versionedSpecifier, versionedUrl)
|
|
997
|
+
|
|
998
|
+
const parentUrlInfo = finalGraph.getUrlInfo(
|
|
999
|
+
reference.parentUrl,
|
|
1000
|
+
)
|
|
1001
|
+
if (parentUrlInfo.jsQuote) {
|
|
1002
|
+
// the url is inline inside js quotes
|
|
1003
|
+
usedVersionMappings.add(reference.specifier)
|
|
1004
|
+
return () =>
|
|
1005
|
+
`${parentUrlInfo.jsQuote}+__v__(${JSON.stringify(
|
|
1006
|
+
reference.specifier,
|
|
1007
|
+
)})+${parentUrlInfo.jsQuote}`
|
|
1008
|
+
}
|
|
1009
|
+
if (
|
|
1010
|
+
reference.type === "js_url_specifier" ||
|
|
1011
|
+
reference.subtype === "import_dynamic"
|
|
1012
|
+
) {
|
|
1013
|
+
usedVersionMappings.add(reference.specifier)
|
|
1014
|
+
return () => `__v__(${JSON.stringify(reference.specifier)})`
|
|
1015
|
+
}
|
|
1016
|
+
return versionedSpecifier
|
|
1017
|
+
},
|
|
1018
|
+
fetchUrlContent: (versionedUrlInfo) => {
|
|
1019
|
+
if (versionedUrlInfo.isInline) {
|
|
1020
|
+
const rawUrlInfo = rawGraph.getUrlInfo(
|
|
1021
|
+
buildToRawUrls[versionedUrlInfo.url],
|
|
1022
|
+
)
|
|
1023
|
+
const finalUrlInfo = finalGraph.getUrlInfo(
|
|
1024
|
+
versionedUrlInfo.url,
|
|
1025
|
+
)
|
|
1026
|
+
return {
|
|
1027
|
+
content: versionedUrlInfo.content,
|
|
1028
|
+
contentType: versionedUrlInfo.contentType,
|
|
1029
|
+
originalContent: rawUrlInfo
|
|
1030
|
+
? rawUrlInfo.originalContent
|
|
1031
|
+
: undefined,
|
|
1032
|
+
sourcemap: finalUrlInfo
|
|
1033
|
+
? finalUrlInfo.sourcemap
|
|
1034
|
+
: undefined,
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
return versionedUrlInfo
|
|
1038
|
+
},
|
|
1039
|
+
},
|
|
1040
|
+
],
|
|
1041
|
+
sourcemaps,
|
|
1042
|
+
sourcemapsSourcesContent,
|
|
1043
|
+
sourcemapsRelativeSources: true,
|
|
1044
|
+
writeGeneratedFiles,
|
|
1045
|
+
outDirectoryUrl: new URL(
|
|
1046
|
+
".jsenv/postbuild/",
|
|
1047
|
+
finalGraphKitchen.rootDirectoryUrl,
|
|
1048
|
+
),
|
|
1049
|
+
})
|
|
1050
|
+
const versioningUrlGraphLoader = createUrlGraphLoader(
|
|
1051
|
+
versioningKitchen.kitchenContext,
|
|
1052
|
+
)
|
|
1053
|
+
finalEntryUrls.forEach((finalEntryUrl) => {
|
|
1054
|
+
const [finalEntryReference, finalEntryUrlInfo] =
|
|
1055
|
+
finalGraphKitchen.kitchenContext.prepareEntryPoint({
|
|
1056
|
+
trace: { message: `entryPoint` },
|
|
1057
|
+
parentUrl: buildDirectoryUrl,
|
|
1058
|
+
type: "entry_point",
|
|
1059
|
+
specifier: finalEntryUrl,
|
|
1060
|
+
})
|
|
1061
|
+
versioningUrlGraphLoader.load(finalEntryUrlInfo, {
|
|
1062
|
+
reference: finalEntryReference,
|
|
1063
|
+
})
|
|
1064
|
+
})
|
|
1065
|
+
await versioningUrlGraphLoader.getAllLoadDonePromise(buildOperation)
|
|
1066
|
+
if (usedVersionMappings.size) {
|
|
1067
|
+
const versionMappingsNeeded = {}
|
|
1068
|
+
usedVersionMappings.forEach((specifier) => {
|
|
1069
|
+
versionMappingsNeeded[specifier] = versionMappings[specifier]
|
|
1070
|
+
})
|
|
1071
|
+
const actions = []
|
|
1072
|
+
GRAPH.forEach(finalGraph, (urlInfo) => {
|
|
1073
|
+
if (urlInfo.isEntryPoint) {
|
|
1074
|
+
actions.push(async () => {
|
|
1075
|
+
await injectVersionMappings({
|
|
1076
|
+
urlInfo,
|
|
1077
|
+
kitchen: finalGraphKitchen,
|
|
1078
|
+
versionMappings: versionMappingsNeeded,
|
|
1079
|
+
})
|
|
1080
|
+
})
|
|
1081
|
+
}
|
|
1082
|
+
})
|
|
1083
|
+
await Promise.all(actions.map((action) => action()))
|
|
1084
|
+
}
|
|
1085
|
+
} catch (e) {
|
|
1086
|
+
versioningTask.fail()
|
|
1087
|
+
throw e
|
|
1088
|
+
}
|
|
1089
|
+
versioningTask.done()
|
|
770
1090
|
}
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
1091
|
+
cleanup_jsenv_attributes_from_html: {
|
|
1092
|
+
GRAPH.forEach(finalGraph, (urlInfo) => {
|
|
1093
|
+
if (!urlInfo.shouldHandle) {
|
|
1094
|
+
return
|
|
1095
|
+
}
|
|
1096
|
+
if (!urlInfo.url.startsWith("file:")) {
|
|
1097
|
+
return
|
|
1098
|
+
}
|
|
1099
|
+
if (urlInfo.type === "html") {
|
|
1100
|
+
const htmlAst = parseHtmlString(urlInfo.content, {
|
|
1101
|
+
storeOriginalPositions: false,
|
|
1102
|
+
})
|
|
1103
|
+
urlInfo.content = stringifyHtmlAst(htmlAst, {
|
|
1104
|
+
cleanupJsenvAttributes: true,
|
|
1105
|
+
})
|
|
1106
|
+
}
|
|
774
1107
|
})
|
|
775
|
-
|
|
776
|
-
|
|
1108
|
+
}
|
|
1109
|
+
/*
|
|
1110
|
+
* Update <link rel="preload"> and friends after build (once we know everything)
|
|
1111
|
+
* - Used to remove resource hint targeting an url that is no longer used:
|
|
1112
|
+
* - Happens because of import assertions transpilation (file is inlined into JS)
|
|
1113
|
+
*/
|
|
1114
|
+
resync_resource_hints: {
|
|
1115
|
+
const actions = []
|
|
1116
|
+
GRAPH.forEach(finalGraph, (urlInfo) => {
|
|
1117
|
+
if (urlInfo.type !== "html") {
|
|
1118
|
+
return
|
|
1119
|
+
}
|
|
1120
|
+
actions.push(async () => {
|
|
1121
|
+
const htmlAst = parseHtmlString(urlInfo.content, {
|
|
1122
|
+
storeOriginalPositions: false,
|
|
1123
|
+
})
|
|
1124
|
+
const mutations = []
|
|
1125
|
+
visitHtmlNodes(htmlAst, {
|
|
1126
|
+
link: (node) => {
|
|
1127
|
+
const href = getHtmlNodeAttribute(node, "href")
|
|
1128
|
+
if (href === undefined || href.startsWith("data:")) {
|
|
1129
|
+
return
|
|
1130
|
+
}
|
|
1131
|
+
const rel = getHtmlNodeAttribute(node, "rel")
|
|
1132
|
+
const isResourceHint = [
|
|
1133
|
+
"preconnect",
|
|
1134
|
+
"dns-prefetch",
|
|
1135
|
+
"prefetch",
|
|
1136
|
+
"preload",
|
|
1137
|
+
"modulepreload",
|
|
1138
|
+
].includes(rel)
|
|
1139
|
+
if (!isResourceHint) {
|
|
1140
|
+
return
|
|
1141
|
+
}
|
|
1142
|
+
const onBuildUrl = (buildUrl) => {
|
|
1143
|
+
const buildUrlInfo = buildUrl
|
|
1144
|
+
? finalGraph.getUrlInfo(buildUrl)
|
|
1145
|
+
: null
|
|
1146
|
+
if (!buildUrlInfo) {
|
|
1147
|
+
logger.warn(
|
|
1148
|
+
`remove resource hint because cannot find "${href}" in the graph`,
|
|
1149
|
+
)
|
|
1150
|
+
mutations.push(() => {
|
|
1151
|
+
removeHtmlNode(node)
|
|
1152
|
+
})
|
|
1153
|
+
return
|
|
1154
|
+
}
|
|
1155
|
+
if (buildUrlInfo.dependents.size === 0) {
|
|
1156
|
+
logger.info(
|
|
1157
|
+
`remove resource hint because "${href}" not used anymore`,
|
|
1158
|
+
)
|
|
1159
|
+
mutations.push(() => {
|
|
1160
|
+
removeHtmlNode(node)
|
|
1161
|
+
})
|
|
1162
|
+
return
|
|
1163
|
+
}
|
|
1164
|
+
const buildUrlFormatted =
|
|
1165
|
+
versioningRedirections.get(buildUrlInfo.url) ||
|
|
1166
|
+
buildUrlInfo.url
|
|
1167
|
+
const buildSpecifierBeforeRedirect = findKey(
|
|
1168
|
+
buildUrls,
|
|
1169
|
+
buildUrlFormatted,
|
|
1170
|
+
)
|
|
1171
|
+
mutations.push(() => {
|
|
1172
|
+
setHtmlNodeAttributes(node, {
|
|
1173
|
+
href: buildSpecifierBeforeRedirect,
|
|
1174
|
+
crossorigin: undefined,
|
|
1175
|
+
})
|
|
1176
|
+
})
|
|
1177
|
+
}
|
|
1178
|
+
if (href.startsWith("file:")) {
|
|
1179
|
+
let url = href
|
|
1180
|
+
url = rawRedirections.get(url) || url
|
|
1181
|
+
const rawUrlInfo = rawGraph.getUrlInfo(url)
|
|
1182
|
+
if (rawUrlInfo && rawUrlInfo.data.bundled) {
|
|
1183
|
+
logger.info(
|
|
1184
|
+
`remove resource hint on "${href}" because it was bundled`,
|
|
1185
|
+
)
|
|
1186
|
+
mutations.push(() => {
|
|
1187
|
+
removeHtmlNode(node)
|
|
1188
|
+
})
|
|
1189
|
+
} else {
|
|
1190
|
+
url = bundleRedirections.get(url) || url
|
|
1191
|
+
url = bundleInternalRedirections.get(url) || url
|
|
1192
|
+
url = finalRedirections.get(url) || url
|
|
1193
|
+
onBuildUrl(url)
|
|
1194
|
+
}
|
|
1195
|
+
} else {
|
|
1196
|
+
onBuildUrl(null)
|
|
1197
|
+
}
|
|
1198
|
+
},
|
|
1199
|
+
})
|
|
1200
|
+
if (mutations.length > 0) {
|
|
1201
|
+
mutations.forEach((mutation) => mutation())
|
|
1202
|
+
await finalGraphKitchen.urlInfoTransformer.applyFinalTransformations(
|
|
1203
|
+
urlInfo,
|
|
1204
|
+
{
|
|
1205
|
+
content: stringifyHtmlAst(htmlAst),
|
|
1206
|
+
},
|
|
1207
|
+
)
|
|
1208
|
+
}
|
|
1209
|
+
})
|
|
777
1210
|
})
|
|
1211
|
+
await Promise.all(
|
|
1212
|
+
actions.map((resourceHintAction) => resourceHintAction()),
|
|
1213
|
+
)
|
|
1214
|
+
buildOperation.throwIfAborted()
|
|
778
1215
|
}
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
})
|
|
796
|
-
buildOperation.throwIfAborted()
|
|
797
|
-
const cleanupActions = []
|
|
798
|
-
GRAPH.forEach(finalGraph, (urlInfo) => {
|
|
799
|
-
// nothing uses this url anymore
|
|
800
|
-
// - versioning update inline content
|
|
801
|
-
// - file converted for import assertion of js_classic conversion
|
|
802
|
-
if (
|
|
803
|
-
!urlInfo.isEntryPoint &&
|
|
804
|
-
urlInfo.type !== "sourcemap" &&
|
|
805
|
-
urlInfo.dependents.size === 0
|
|
806
|
-
) {
|
|
807
|
-
cleanupActions.push(() => {
|
|
808
|
-
finalGraph.deleteUrlInfo(urlInfo.url)
|
|
1216
|
+
delete_unused_urls: {
|
|
1217
|
+
const actions = []
|
|
1218
|
+
GRAPH.forEach(finalGraph, (urlInfo) => {
|
|
1219
|
+
// nothing uses this url anymore
|
|
1220
|
+
// - versioning update inline content
|
|
1221
|
+
// - file converted for import assertion or js_classic conversion
|
|
1222
|
+
if (
|
|
1223
|
+
!urlInfo.isEntryPoint &&
|
|
1224
|
+
urlInfo.type !== "sourcemap" &&
|
|
1225
|
+
urlInfo.dependents.size === 0 &&
|
|
1226
|
+
!urlInfo.injected // injected during postbuild
|
|
1227
|
+
) {
|
|
1228
|
+
actions.push(() => {
|
|
1229
|
+
finalGraph.deleteUrlInfo(urlInfo.url)
|
|
1230
|
+
})
|
|
1231
|
+
}
|
|
809
1232
|
})
|
|
1233
|
+
actions.forEach((action) => action())
|
|
810
1234
|
}
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
1235
|
+
inject_urls_in_service_workers: {
|
|
1236
|
+
const serviceWorkerEntryUrlInfos = GRAPH.filter(
|
|
1237
|
+
finalGraph,
|
|
1238
|
+
(finalUrlInfo) => {
|
|
1239
|
+
return (
|
|
1240
|
+
finalUrlInfo.subtype === "service_worker" &&
|
|
1241
|
+
finalUrlInfo.isEntryPoint
|
|
1242
|
+
)
|
|
1243
|
+
},
|
|
1244
|
+
)
|
|
1245
|
+
if (serviceWorkerEntryUrlInfos.length > 0) {
|
|
1246
|
+
const serviceWorkerUrls = {}
|
|
1247
|
+
GRAPH.forEach(finalGraph, (urlInfo) => {
|
|
1248
|
+
if (urlInfo.isInline || !urlInfo.shouldHandle) {
|
|
1249
|
+
return
|
|
1250
|
+
}
|
|
1251
|
+
if (!urlInfo.url.startsWith("file:")) {
|
|
1252
|
+
return
|
|
1253
|
+
}
|
|
1254
|
+
const versionedUrl = urlInfo.data.versionedUrl
|
|
1255
|
+
if (!versionedUrl) {
|
|
1256
|
+
// when url is not versioned we compute a "version" for that url anyway
|
|
1257
|
+
// so that service worker source still changes and navigator
|
|
1258
|
+
// detect there is a change
|
|
1259
|
+
const versionGenerator = createVersionGenerator()
|
|
1260
|
+
versionGenerator.augmentWithContent({
|
|
1261
|
+
content: urlInfo.content,
|
|
1262
|
+
contentType: urlInfo.contentType,
|
|
1263
|
+
lineBreakNormalization,
|
|
1264
|
+
})
|
|
1265
|
+
const version = versionGenerator.generate()
|
|
1266
|
+
urlInfo.data.version = version
|
|
1267
|
+
const specifier = findKey(buildUrls, urlInfo.url)
|
|
1268
|
+
serviceWorkerUrls[specifier] = { versioned: false, version }
|
|
1269
|
+
return
|
|
1270
|
+
}
|
|
1271
|
+
if (!canUseVersionedUrl(urlInfo)) {
|
|
1272
|
+
const specifier = findKey(buildUrls, urlInfo.url)
|
|
1273
|
+
serviceWorkerUrls[specifier] = {
|
|
1274
|
+
versioned: false,
|
|
1275
|
+
version: urlInfo.data.version,
|
|
1276
|
+
}
|
|
1277
|
+
return
|
|
1278
|
+
}
|
|
1279
|
+
const versionedSpecifier = findKey(buildUrls, versionedUrl)
|
|
1280
|
+
serviceWorkerUrls[versionedSpecifier] = { versioned: true }
|
|
1281
|
+
})
|
|
1282
|
+
serviceWorkerEntryUrlInfos.forEach((serviceWorkerEntryUrlInfo) => {
|
|
1283
|
+
const magicSource = createMagicSource(
|
|
1284
|
+
serviceWorkerEntryUrlInfo.content,
|
|
1285
|
+
)
|
|
1286
|
+
const urlsWithoutSelf = {
|
|
1287
|
+
...serviceWorkerUrls,
|
|
1288
|
+
}
|
|
1289
|
+
const serviceWorkerSpecifier = findKey(
|
|
1290
|
+
buildUrls,
|
|
1291
|
+
serviceWorkerEntryUrlInfo.url,
|
|
1292
|
+
)
|
|
1293
|
+
delete urlsWithoutSelf[serviceWorkerSpecifier]
|
|
1294
|
+
magicSource.prepend(
|
|
1295
|
+
`\nself.serviceWorkerUrls = ${JSON.stringify(
|
|
1296
|
+
urlsWithoutSelf,
|
|
1297
|
+
null,
|
|
1298
|
+
" ",
|
|
1299
|
+
)};\n`,
|
|
1300
|
+
)
|
|
1301
|
+
const { content, sourcemap } = magicSource.toContentAndSourcemap()
|
|
1302
|
+
finalGraphKitchen.urlInfoTransformer.applyFinalTransformations(
|
|
1303
|
+
serviceWorkerEntryUrlInfo,
|
|
1304
|
+
{
|
|
1305
|
+
content,
|
|
1306
|
+
sourcemap,
|
|
1307
|
+
},
|
|
1308
|
+
)
|
|
1309
|
+
})
|
|
1310
|
+
}
|
|
1311
|
+
buildOperation.throwIfAborted()
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
819
1314
|
|
|
820
1315
|
const buildManifest = {}
|
|
821
1316
|
const buildFileContents = {}
|
|
@@ -830,19 +1325,32 @@ ${Array.from(finalGraph.urlInfoMap.keys()).join("\n")}`,
|
|
|
830
1325
|
if (urlInfo.type === "directory") {
|
|
831
1326
|
return
|
|
832
1327
|
}
|
|
833
|
-
const buildRelativeUrl = urlToRelativeUrl(
|
|
834
|
-
urlInfo.data.buildUrl,
|
|
835
|
-
buildDirectoryUrl,
|
|
836
|
-
)
|
|
837
1328
|
if (urlInfo.isInline) {
|
|
838
|
-
|
|
839
|
-
} else {
|
|
840
|
-
buildFileContents[buildRelativeUrl] = urlInfo.content
|
|
841
|
-
const buildRelativeUrlWithoutVersioning = urlToRelativeUrl(
|
|
1329
|
+
const buildRelativeUrl = urlToRelativeUrl(
|
|
842
1330
|
urlInfo.url,
|
|
843
1331
|
buildDirectoryUrl,
|
|
844
1332
|
)
|
|
845
|
-
|
|
1333
|
+
buildInlineContents[buildRelativeUrl] = urlInfo.content
|
|
1334
|
+
} else {
|
|
1335
|
+
const versionedUrl = urlInfo.data.versionedUrl
|
|
1336
|
+
if (versionedUrl && canUseVersionedUrl(urlInfo)) {
|
|
1337
|
+
const buildRelativeUrl = urlToRelativeUrl(
|
|
1338
|
+
urlInfo.url,
|
|
1339
|
+
buildDirectoryUrl,
|
|
1340
|
+
)
|
|
1341
|
+
const versionedBuildRelativeUrl = urlToRelativeUrl(
|
|
1342
|
+
versionedUrl,
|
|
1343
|
+
buildDirectoryUrl,
|
|
1344
|
+
)
|
|
1345
|
+
buildFileContents[versionedBuildRelativeUrl] = urlInfo.content
|
|
1346
|
+
buildManifest[buildRelativeUrl] = versionedBuildRelativeUrl
|
|
1347
|
+
} else {
|
|
1348
|
+
const buildRelativeUrl = urlToRelativeUrl(
|
|
1349
|
+
urlInfo.url,
|
|
1350
|
+
buildDirectoryUrl,
|
|
1351
|
+
)
|
|
1352
|
+
buildFileContents[buildRelativeUrl] = urlInfo.content
|
|
1353
|
+
}
|
|
846
1354
|
}
|
|
847
1355
|
})
|
|
848
1356
|
if (writeOnFileSystem) {
|
|
@@ -850,16 +1358,14 @@ ${Array.from(finalGraph.urlInfoMap.keys()).join("\n")}`,
|
|
|
850
1358
|
await ensureEmptyDirectory(buildDirectoryUrl)
|
|
851
1359
|
}
|
|
852
1360
|
const buildRelativeUrls = Object.keys(buildFileContents)
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
}),
|
|
860
|
-
)
|
|
1361
|
+
buildRelativeUrls.forEach((buildRelativeUrl) => {
|
|
1362
|
+
writeFileSync(
|
|
1363
|
+
new URL(buildRelativeUrl, buildDirectoryUrl),
|
|
1364
|
+
buildFileContents[buildRelativeUrl],
|
|
1365
|
+
)
|
|
1366
|
+
})
|
|
861
1367
|
if (versioning && assetManifest && Object.keys(buildManifest).length) {
|
|
862
|
-
|
|
1368
|
+
writeFileSync(
|
|
863
1369
|
new URL(assetManifestFileRelativeUrl, buildDirectoryUrl),
|
|
864
1370
|
JSON.stringify(buildManifest, null, " "),
|
|
865
1371
|
)
|
|
@@ -948,271 +1454,13 @@ ${Array.from(finalGraph.urlInfoMap.keys()).join("\n")}`,
|
|
|
948
1454
|
return stopWatchingClientFiles
|
|
949
1455
|
}
|
|
950
1456
|
|
|
951
|
-
const
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
buildDirectoryUrl,
|
|
956
|
-
rawUrls,
|
|
957
|
-
buildUrls,
|
|
958
|
-
baseUrl,
|
|
959
|
-
postBuildEntryUrls,
|
|
960
|
-
sourcemaps,
|
|
961
|
-
sourcemapsSourcesContent,
|
|
962
|
-
runtimeCompat,
|
|
963
|
-
writeGeneratedFiles,
|
|
964
|
-
rawGraph,
|
|
965
|
-
urlAnalysisPlugin,
|
|
966
|
-
finalGraph,
|
|
967
|
-
finalGraphKitchen,
|
|
968
|
-
lineBreakNormalization,
|
|
969
|
-
versioningMethod,
|
|
970
|
-
}) => {
|
|
971
|
-
const versioningTask = createTaskLog("inject version in urls", {
|
|
972
|
-
disabled: infoLogsAreDisabled,
|
|
973
|
-
})
|
|
974
|
-
try {
|
|
975
|
-
const urlsSorted = sortByDependencies(finalGraph.toObject())
|
|
976
|
-
urlsSorted.forEach((url) => {
|
|
977
|
-
if (url.startsWith("data:")) {
|
|
978
|
-
return
|
|
979
|
-
}
|
|
980
|
-
const urlInfo = finalGraph.getUrlInfo(url)
|
|
981
|
-
if (urlInfo.type === "sourcemap") {
|
|
982
|
-
return
|
|
983
|
-
}
|
|
984
|
-
// ignore:
|
|
985
|
-
// - inline files:
|
|
986
|
-
// they are already taken into account in the file where they appear
|
|
987
|
-
// - ignored files:
|
|
988
|
-
// we don't know their content
|
|
989
|
-
// - unused files without reference
|
|
990
|
-
// File updated such as style.css -> style.css.js or file.js->file.nomodule.js
|
|
991
|
-
// Are used at some point just to be discarded later because they need to be converted
|
|
992
|
-
// There is no need to version them and we could not because the file have been ignored
|
|
993
|
-
// so their content is unknown
|
|
994
|
-
if (urlInfo.isInline) {
|
|
995
|
-
return
|
|
996
|
-
}
|
|
997
|
-
if (!urlInfo.shouldHandle) {
|
|
998
|
-
return
|
|
999
|
-
}
|
|
1000
|
-
if (!urlInfo.isEntryPoint && urlInfo.dependents.size === 0) {
|
|
1001
|
-
return
|
|
1002
|
-
}
|
|
1003
|
-
|
|
1004
|
-
const urlContent =
|
|
1005
|
-
urlInfo.type === "html"
|
|
1006
|
-
? stringifyHtmlAst(
|
|
1007
|
-
parseHtmlString(urlInfo.content, {
|
|
1008
|
-
storeOriginalPositions: false,
|
|
1009
|
-
}),
|
|
1010
|
-
{ removeOriginalPositionAttributes: true },
|
|
1011
|
-
)
|
|
1012
|
-
: urlInfo.content
|
|
1013
|
-
const versionGenerator = createVersionGenerator()
|
|
1014
|
-
versionGenerator.augmentWithContent({
|
|
1015
|
-
content: urlContent,
|
|
1016
|
-
contentType: urlInfo.contentType,
|
|
1017
|
-
lineBreakNormalization,
|
|
1018
|
-
})
|
|
1019
|
-
urlInfo.dependencies.forEach((dependencyUrl) => {
|
|
1020
|
-
// this dependency is inline
|
|
1021
|
-
if (dependencyUrl.startsWith("data:")) {
|
|
1022
|
-
return
|
|
1023
|
-
}
|
|
1024
|
-
const dependencyUrlInfo = finalGraph.getUrlInfo(dependencyUrl)
|
|
1025
|
-
if (
|
|
1026
|
-
// this content is part of the file, no need to take into account twice
|
|
1027
|
-
dependencyUrlInfo.isInline ||
|
|
1028
|
-
// this dependency content is not known
|
|
1029
|
-
!dependencyUrlInfo.shouldHandle
|
|
1030
|
-
) {
|
|
1031
|
-
return
|
|
1032
|
-
}
|
|
1033
|
-
if (dependencyUrlInfo.data.version) {
|
|
1034
|
-
versionGenerator.augmentWithDependencyVersion(
|
|
1035
|
-
dependencyUrlInfo.data.version,
|
|
1036
|
-
)
|
|
1037
|
-
} else {
|
|
1038
|
-
// because all dependencies are know, if the dependency has no version
|
|
1039
|
-
// it means there is a circular dependency between this file
|
|
1040
|
-
// and it's dependency
|
|
1041
|
-
// in that case we'll use the dependency content
|
|
1042
|
-
versionGenerator.augmentWithContent({
|
|
1043
|
-
content: dependencyUrlInfo.content,
|
|
1044
|
-
contentType: dependencyUrlInfo.contentType,
|
|
1045
|
-
lineBreakNormalization,
|
|
1046
|
-
})
|
|
1047
|
-
}
|
|
1048
|
-
})
|
|
1049
|
-
urlInfo.data.version = versionGenerator.generate()
|
|
1050
|
-
|
|
1051
|
-
urlInfo.data.versionedUrl = normalizeUrl(
|
|
1052
|
-
injectVersionIntoBuildUrl({
|
|
1053
|
-
buildUrl: urlInfo.url,
|
|
1054
|
-
version: urlInfo.data.version,
|
|
1055
|
-
versioningMethod,
|
|
1056
|
-
}),
|
|
1057
|
-
)
|
|
1058
|
-
})
|
|
1059
|
-
const versionMappings = {}
|
|
1060
|
-
const usedVersionMappings = []
|
|
1061
|
-
const versioningKitchen = createKitchen({
|
|
1062
|
-
logger,
|
|
1063
|
-
rootDirectoryUrl: buildDirectoryUrl,
|
|
1064
|
-
urlGraph: finalGraph,
|
|
1065
|
-
scenarios: { build: true },
|
|
1066
|
-
sourcemaps,
|
|
1067
|
-
sourcemapsSourcesContent,
|
|
1068
|
-
sourcemapsRelativeSources: true,
|
|
1069
|
-
runtimeCompat,
|
|
1070
|
-
writeGeneratedFiles,
|
|
1071
|
-
plugins: [
|
|
1072
|
-
urlAnalysisPlugin,
|
|
1073
|
-
jsenvPluginInline({
|
|
1074
|
-
fetchInlineUrls: false,
|
|
1075
|
-
analyzeConvertedScripts: true, // to be able to version their urls
|
|
1076
|
-
allowEscapeForVersioning: true,
|
|
1077
|
-
}),
|
|
1078
|
-
{
|
|
1079
|
-
name: "jsenv:versioning",
|
|
1080
|
-
appliesDuring: "build",
|
|
1081
|
-
resolveUrl: (reference) => {
|
|
1082
|
-
const buildUrl = buildUrls[reference.specifier]
|
|
1083
|
-
if (buildUrl) {
|
|
1084
|
-
return buildUrl
|
|
1085
|
-
}
|
|
1086
|
-
const urlObject = new URL(
|
|
1087
|
-
reference.specifier,
|
|
1088
|
-
reference.baseUrl || reference.parentUrl,
|
|
1089
|
-
)
|
|
1090
|
-
const url = urlObject.href
|
|
1091
|
-
// during versioning we revisit the deps
|
|
1092
|
-
// but the code used to enforce trailing slash on directories
|
|
1093
|
-
// is not applied because "jsenv:file_url_resolution" is not used
|
|
1094
|
-
// so here we search if the url with a trailing slash exists
|
|
1095
|
-
if (
|
|
1096
|
-
reference.type === "filesystem" &&
|
|
1097
|
-
!urlObject.pathname.endsWith("/")
|
|
1098
|
-
) {
|
|
1099
|
-
const urlWithTrailingSlash = `${url}/`
|
|
1100
|
-
const specifier = Object.keys(buildUrls).find(
|
|
1101
|
-
(key) => buildUrls[key] === urlWithTrailingSlash,
|
|
1102
|
-
)
|
|
1103
|
-
if (specifier) {
|
|
1104
|
-
return urlWithTrailingSlash
|
|
1105
|
-
}
|
|
1106
|
-
}
|
|
1107
|
-
return url
|
|
1108
|
-
},
|
|
1109
|
-
formatUrl: (reference) => {
|
|
1110
|
-
if (!reference.shouldHandle) {
|
|
1111
|
-
if (reference.generatedUrl.startsWith("ignore:")) {
|
|
1112
|
-
return reference.generatedUrl.slice("ignore:".length)
|
|
1113
|
-
}
|
|
1114
|
-
return null
|
|
1115
|
-
}
|
|
1116
|
-
if (reference.isInline || reference.url.startsWith("data:")) {
|
|
1117
|
-
return null
|
|
1118
|
-
}
|
|
1119
|
-
if (reference.isResourceHint) {
|
|
1120
|
-
return null
|
|
1121
|
-
}
|
|
1122
|
-
// specifier comes from "normalize" hook done a bit earlier in this file
|
|
1123
|
-
// we want to get back their build url to access their infos
|
|
1124
|
-
const referencedUrlInfo = finalGraph.getUrlInfo(reference.url)
|
|
1125
|
-
if (!canUseVersionedUrl(referencedUrlInfo)) {
|
|
1126
|
-
return reference.specifier
|
|
1127
|
-
}
|
|
1128
|
-
if (!referencedUrlInfo.shouldHandle) {
|
|
1129
|
-
return null
|
|
1130
|
-
}
|
|
1131
|
-
const versionedUrl = referencedUrlInfo.data.versionedUrl
|
|
1132
|
-
if (!versionedUrl) {
|
|
1133
|
-
// happens for sourcemap
|
|
1134
|
-
return `${baseUrl}${urlToRelativeUrl(
|
|
1135
|
-
referencedUrlInfo.url,
|
|
1136
|
-
buildDirectoryUrl,
|
|
1137
|
-
)}`
|
|
1138
|
-
}
|
|
1139
|
-
const versionedSpecifier = `${baseUrl}${urlToRelativeUrl(
|
|
1140
|
-
versionedUrl,
|
|
1141
|
-
buildDirectoryUrl,
|
|
1142
|
-
)}`
|
|
1143
|
-
versionMappings[reference.specifier] = versionedSpecifier
|
|
1144
|
-
buildUrls[versionedSpecifier] = versionedUrl
|
|
1145
|
-
|
|
1146
|
-
const parentUrlInfo = finalGraph.getUrlInfo(reference.parentUrl)
|
|
1147
|
-
if (parentUrlInfo.jsQuote) {
|
|
1148
|
-
// the url is inline inside js quotes
|
|
1149
|
-
usedVersionMappings.push(reference.specifier)
|
|
1150
|
-
return () =>
|
|
1151
|
-
`${parentUrlInfo.jsQuote}+__v__(${JSON.stringify(
|
|
1152
|
-
reference.specifier,
|
|
1153
|
-
)})+${parentUrlInfo.jsQuote}`
|
|
1154
|
-
}
|
|
1155
|
-
if (
|
|
1156
|
-
reference.type === "js_url_specifier" ||
|
|
1157
|
-
reference.subtype === "import_dynamic"
|
|
1158
|
-
) {
|
|
1159
|
-
usedVersionMappings.push(reference.specifier)
|
|
1160
|
-
return () => `__v__(${JSON.stringify(reference.specifier)})`
|
|
1161
|
-
}
|
|
1162
|
-
return versionedSpecifier
|
|
1163
|
-
},
|
|
1164
|
-
fetchUrlContent: (versionedUrlInfo) => {
|
|
1165
|
-
if (versionedUrlInfo.isInline) {
|
|
1166
|
-
const rawUrlInfo = rawGraph.getUrlInfo(
|
|
1167
|
-
rawUrls[versionedUrlInfo.url],
|
|
1168
|
-
)
|
|
1169
|
-
const finalUrlInfo = finalGraph.getUrlInfo(versionedUrlInfo.url)
|
|
1170
|
-
return {
|
|
1171
|
-
content: versionedUrlInfo.content,
|
|
1172
|
-
contentType: versionedUrlInfo.contentType,
|
|
1173
|
-
originalContent: rawUrlInfo
|
|
1174
|
-
? rawUrlInfo.originalContent
|
|
1175
|
-
: undefined,
|
|
1176
|
-
sourcemap: finalUrlInfo ? finalUrlInfo.sourcemap : undefined,
|
|
1177
|
-
}
|
|
1178
|
-
}
|
|
1179
|
-
return versionedUrlInfo
|
|
1180
|
-
},
|
|
1181
|
-
},
|
|
1182
|
-
],
|
|
1183
|
-
})
|
|
1184
|
-
await loadUrlGraph({
|
|
1185
|
-
operation: buildOperation,
|
|
1186
|
-
urlGraph: finalGraph,
|
|
1187
|
-
kitchen: versioningKitchen,
|
|
1188
|
-
skipResourceHint: true,
|
|
1189
|
-
writeGeneratedFiles,
|
|
1190
|
-
startLoading: (cookEntryFile) => {
|
|
1191
|
-
postBuildEntryUrls.forEach((postBuildEntryUrl) => {
|
|
1192
|
-
cookEntryFile({
|
|
1193
|
-
trace: `entryPoint`,
|
|
1194
|
-
type: "entry_point",
|
|
1195
|
-
specifier: postBuildEntryUrl,
|
|
1196
|
-
})
|
|
1197
|
-
})
|
|
1198
|
-
},
|
|
1199
|
-
})
|
|
1200
|
-
if (usedVersionMappings.length) {
|
|
1201
|
-
const versionMappingsNeeded = {}
|
|
1202
|
-
usedVersionMappings.forEach((specifier) => {
|
|
1203
|
-
versionMappingsNeeded[specifier] = versionMappings[specifier]
|
|
1204
|
-
})
|
|
1205
|
-
await injectGlobalVersionMapping({
|
|
1206
|
-
finalGraphKitchen,
|
|
1207
|
-
finalGraph,
|
|
1208
|
-
versionMappings: versionMappingsNeeded,
|
|
1209
|
-
})
|
|
1457
|
+
const findKey = (map, value) => {
|
|
1458
|
+
for (const [keyCandidate, valueCandidate] of map) {
|
|
1459
|
+
if (valueCandidate === value) {
|
|
1460
|
+
return keyCandidate
|
|
1210
1461
|
}
|
|
1211
|
-
} catch (e) {
|
|
1212
|
-
versioningTask.fail()
|
|
1213
|
-
throw e
|
|
1214
1462
|
}
|
|
1215
|
-
|
|
1463
|
+
return undefined
|
|
1216
1464
|
}
|
|
1217
1465
|
|
|
1218
1466
|
const injectVersionIntoBuildUrl = ({ buildUrl, version, versioningMethod }) => {
|