@jsenv/core 24.6.5 → 25.0.0-alpha.3

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.
Files changed (83) hide show
  1. package/dist/browser_runtime/asset-manifest.json +2 -1
  2. package/dist/browser_runtime/{browser_runtime-bb0e3aa4.js → browser_runtime_91c5a3b8.js} +137 -26
  3. package/dist/browser_runtime/browser_runtime_91c5a3b8.js.map +1089 -0
  4. package/dist/build_manifest.js +6 -6
  5. package/dist/compile_proxy/asset-manifest.json +2 -1
  6. package/dist/compile_proxy/{compile_proxy-6eb67db4.html → compile_proxy_7ad5faa6.html} +119 -26
  7. package/dist/compile_proxy/{compile_proxy.html__inline__20-9e168143.js.map → compile_proxy_e3b0c442_809f35f7.js.map} +6 -6
  8. package/dist/event_source_client/asset-manifest.json +2 -1
  9. package/dist/event_source_client/{event_source_client-9f14c8b9.js → event_source_client_80644aee.js} +2 -2
  10. package/dist/event_source_client/{event_source_client-9f14c8b9.js.map → event_source_client_80644aee.js.map} +4 -3
  11. package/dist/redirector/asset-manifest.json +2 -1
  12. package/dist/redirector/{redirector.html__inline__15-3a34a156.js.map → redirector_e3b0c442_e391410e.js.map} +6 -6
  13. package/dist/redirector/{redirector-b6ad84bf.html → redirector_eb92e8a7.html} +119 -26
  14. package/dist/toolbar/asset-manifest.json +11 -10
  15. package/dist/toolbar/assets/{compilation.css-209d68b4.map → compilation.css_e37c747b.map} +1 -1
  16. package/dist/toolbar/assets/{eventsource.css-38cd0a36.map → eventsource.css_c0c71e7b.map} +1 -1
  17. package/dist/toolbar/assets/{execution.css-0ebe522f.map → execution.css_f3377c10.map} +1 -1
  18. package/dist/toolbar/assets/{focus.css-3f9c156d.map → focus.css_896f3e45.map} +1 -1
  19. package/dist/toolbar/assets/{light-theme.css-78b19a80.map → light-theme.css_72a60fa3.map} +1 -1
  20. package/dist/toolbar/assets/{overflow-menu.css-d9688a1c.map → overflow-menu.css_2859d519.map} +1 -1
  21. package/dist/toolbar/assets/{settings.css-2b81b245.map → settings.css_61548139.map} +1 -1
  22. package/dist/toolbar/assets/{toolbar.main.css-846920e9.map → toolbar.main.css_269d7ce2.map} +9 -9
  23. package/dist/toolbar/assets/{tooltip.css-03395ee6.map → tooltip.css_a94a8bdd.map} +1 -1
  24. package/dist/toolbar/{toolbar.main-a5ef2c60.js.map → toolbar.main2_6c1b3d82.js.map} +8 -8
  25. package/dist/toolbar/{toolbar-1fbf8dcb.html → toolbar_04ba410c.html} +129 -36
  26. package/dist/toolbar_injector/asset-manifest.json +3 -2
  27. package/dist/toolbar_injector/assets/{jsenv-logo-188b9ca6.svg → jsenv-logo_188b9ca6.svg} +0 -0
  28. package/dist/toolbar_injector/{toolbar_injector-997dbaa0.js → toolbar_injector_4a48bc53.js} +3 -3
  29. package/dist/toolbar_injector/{toolbar_injector-997dbaa0.js.map → toolbar_injector_4a48bc53.js.map} +2 -2
  30. package/package.json +5 -4
  31. package/readme.md +24 -91
  32. package/src/buildProject.js +51 -27
  33. package/src/dev_server.js +8 -2
  34. package/src/execute.js +7 -1
  35. package/src/executeTestPlan.js +17 -0
  36. package/src/internal/browser_feature_detection/browser_feature_detection.js +18 -25
  37. package/src/internal/browser_runtime/browser_runtime.js +2 -2
  38. package/src/internal/browser_runtime/createBrowserRuntime.js +1 -1
  39. package/src/internal/browser_runtime/displayErrorInDocument.js +2 -0
  40. package/src/internal/browser_runtime/displayErrorNotification.js +1 -1
  41. package/src/internal/building/buildUsingRollup.js +12 -15
  42. package/src/internal/building/build_logs.js +2 -2
  43. package/src/internal/building/build_stats.js +11 -1
  44. package/src/internal/building/html/parseHtmlRessource.js +2 -26
  45. package/src/internal/building/js/parseJsRessource.js +3 -2
  46. package/src/internal/building/json_module.js +11 -0
  47. package/src/internal/building/parseRessource.js +1 -1
  48. package/src/internal/building/ressource_builder.js +210 -216
  49. package/src/internal/building/rollup_plugin_jsenv.js +554 -378
  50. package/src/internal/building/url_loader.js +8 -145
  51. package/src/internal/building/url_versioning.js +220 -0
  52. package/src/internal/compiling/compileHtml.js +8 -1
  53. package/src/internal/compiling/createCompiledFileService.js +28 -40
  54. package/src/internal/compiling/html_source_file_service.js +66 -51
  55. package/src/internal/compiling/js-compilation-service/babel_plugin_systemjs_prepend.js +23 -0
  56. package/src/internal/compiling/js-compilation-service/jsenvTransform.js +16 -12
  57. package/src/internal/compiling/js-compilation-service/transformJs.js +2 -0
  58. package/src/internal/compiling/jsenvCompilerForHtml.js +43 -44
  59. package/src/internal/compiling/jsenvCompilerForImportmap.js +15 -76
  60. package/src/internal/compiling/jsenvCompilerForJavaScript.js +9 -0
  61. package/src/internal/compiling/startCompileServer.js +29 -5
  62. package/src/internal/dev_server/event_source_client/livereload_preference.js +1 -1
  63. package/src/internal/dev_server/toolbar/compilation/toolbar.compilation.js +9 -9
  64. package/src/internal/executing/executePlan.js +6 -0
  65. package/src/internal/generateGroupMap/{jsenvBabelPluginCompatMap.js → babel_plugins_compatibility.js} +0 -0
  66. package/src/internal/generateGroupMap/{featuresCompatMap.js → features_compatibility.js} +9 -1
  67. package/src/internal/generateGroupMap/generateGroupMap.js +6 -35
  68. package/src/internal/generateGroupMap/one_runtime_compat.js +9 -12
  69. package/src/internal/generateGroupMap/runtime_compat.js +10 -15
  70. package/src/internal/generateGroupMap/runtime_compat_composition.js +2 -2
  71. package/src/internal/generateGroupMap/shake_babel_plugin_map.js +21 -0
  72. package/src/internal/import-resolution/importmap_default.js +52 -0
  73. package/src/internal/node_feature_detection/node_feature_detection.js +25 -19
  74. package/src/internal/runtime/s.js +101 -6
  75. package/src/internal/unevalException.js +1 -1
  76. package/src/jsenvServiceWorkerFinalizer.js +12 -17
  77. package/dist/browser_runtime/browser_runtime-bb0e3aa4.js.map +0 -1067
  78. package/src/internal/building/asset_url_versioning.js +0 -50
  79. package/src/internal/building/rollup_build_sourcemap.js +0 -54
  80. package/src/internal/building/url-versioning.js +0 -96
  81. package/src/internal/generateGroupMap/jsenvPluginCompatMap.js +0 -1
  82. package/src/internal/import-resolution/importmap-default.js +0 -34
  83. package/src/internal/renderNamePattern.js +0 -6
@@ -1,10 +1,9 @@
1
1
  import { extname } from "node:path"
2
2
  import MagicString from "magic-string"
3
- import { normalizeImportMap } from "@jsenv/importmap"
3
+ import { composeTwoImportMaps, normalizeImportMap } from "@jsenv/importmap"
4
4
  import { isSpecifierForNodeCoreModule } from "@jsenv/importmap/src/isSpecifierForNodeCoreModule.js"
5
5
  import { createDetailedMessage, loggerToLogLevel } from "@jsenv/logger"
6
6
  import {
7
- isFileSystemPath,
8
7
  fileSystemPathToUrl,
9
8
  resolveUrl,
10
9
  urlToRelativeUrl,
@@ -14,9 +13,13 @@ import {
14
13
  normalizeStructuredMetaMap,
15
14
  urlToMeta,
16
15
  urlToBasename,
16
+ urlToFilename,
17
+ readFile,
17
18
  } from "@jsenv/filesystem"
18
19
  import { UNICODE } from "@jsenv/log"
19
20
 
21
+ import { convertJsonTextToJavascriptModule } from "@jsenv/core/src/internal/building/json_module.js"
22
+ import { convertCssTextToJavascriptModule } from "@jsenv/core/src/internal/building/css_module.js"
20
23
  import { transformJs } from "@jsenv/core/src/internal/compiling/js-compilation-service/transformJs.js"
21
24
  import { createUrlConverter } from "@jsenv/core/src/internal/url_conversion.js"
22
25
  import { createUrlFetcher } from "@jsenv/core/src/internal/building/url_fetcher.js"
@@ -24,7 +27,9 @@ import { createUrlLoader } from "@jsenv/core/src/internal/building/url_loader.js
24
27
  import { stringifyUrlTrace } from "@jsenv/core/src/internal/building/url_trace.js"
25
28
  import { sortObjectByPathnames } from "@jsenv/core/src/internal/building/sortObjectByPathnames.js"
26
29
  import { jsenvHelpersDirectoryInfo } from "@jsenv/core/src/internal/jsenvInternalFiles.js"
27
- import { setUrlSearchParamsDescriptor } from "@jsenv/core/src/internal/url_utils.js"
30
+ import { createImportResolverForNode } from "@jsenv/core/src/internal/import-resolution/import-resolver-node.js"
31
+ import { createImportResolverForImportmap } from "@jsenv/core/src/internal/import-resolution/import-resolver-importmap.js"
32
+ import { getDefaultImportmap } from "@jsenv/core/src/internal/import-resolution/importmap_default.js"
28
33
 
29
34
  import {
30
35
  formatBuildStartLog,
@@ -40,13 +45,9 @@ import {
40
45
  referenceToCodeForRollup,
41
46
  } from "./ressource_builder.js"
42
47
 
43
- import { computeBuildRelativeUrl } from "./url-versioning.js"
48
+ import { createUrlVersioner } from "./url_versioning.js"
44
49
  import { visitImportReferences } from "./import_references.js"
45
50
 
46
- import { createImportResolverForNode } from "../import-resolution/import-resolver-node.js"
47
- import { createImportResolverForImportmap } from "../import-resolution/import-resolver-importmap.js"
48
- import { getDefaultImportMap } from "../import-resolution/importmap-default.js"
49
- import { injectSourcemapInRollupBuild } from "./rollup_build_sourcemap.js"
50
51
  import { createBuildStats } from "./build_stats.js"
51
52
 
52
53
  export const createRollupPlugins = async ({
@@ -54,7 +55,7 @@ export const createRollupPlugins = async ({
54
55
  logger,
55
56
 
56
57
  projectDirectoryUrl,
57
- entryPointMap,
58
+ entryPoints,
58
59
  compileServerOrigin,
59
60
  compileDirectoryRelativeUrl,
60
61
  buildDirectoryUrl,
@@ -69,6 +70,8 @@ export const createRollupPlugins = async ({
69
70
  workers,
70
71
  serviceWorkers,
71
72
  serviceWorkerFinalizer,
73
+ classicWorkers,
74
+ classicServiceWorkers,
72
75
 
73
76
  format,
74
77
  systemJsUrl,
@@ -77,7 +80,6 @@ export const createRollupPlugins = async ({
77
80
  importAssertionsSupport,
78
81
 
79
82
  urlVersioning,
80
- urlVersionningForEntryPoints,
81
83
  lineBreakNormalization,
82
84
  jsConcatenation,
83
85
  cssConcatenation,
@@ -101,14 +103,27 @@ export const createRollupPlugins = async ({
101
103
  lastErrorMessage = error.message
102
104
  }
103
105
 
104
- const workerUrls = Object.keys(workers).map((key) =>
105
- resolveUrl(key, projectDirectoryUrl),
106
+ const extension = extname(entryPoints[Object.keys(entryPoints)[0]])
107
+ const outputExtension = extension === ".html" ? ".js" : extension
108
+
109
+ const entryPointUrls = {}
110
+ Object.keys(entryPoints).forEach((key) => {
111
+ const url = resolveUrl(key, projectDirectoryUrl)
112
+ entryPointUrls[url] = entryPoints[key]
113
+ })
114
+ const workerUrls = workers.map((worker) =>
115
+ resolveUrl(worker, projectDirectoryUrl),
116
+ )
117
+ const serviceWorkerUrls = serviceWorkers.map((serviceWorker) =>
118
+ resolveUrl(serviceWorker, projectDirectoryUrl),
106
119
  )
107
- const serviceWorkerUrls = Object.keys(serviceWorkers).map((key) =>
108
- resolveUrl(key, projectDirectoryUrl),
120
+ const classicWorkerUrls = classicWorkers.map((classicWorker) =>
121
+ resolveUrl(classicWorker, projectDirectoryUrl),
122
+ )
123
+ const classicServiceWorkerUrls = classicServiceWorkers.map(
124
+ (classicServiceWorker) =>
125
+ resolveUrl(classicServiceWorker, projectDirectoryUrl),
109
126
  )
110
- const isWorkerUrl = (url) => workerUrls.includes(url)
111
- const isServiceWorkerUrl = (url) => serviceWorkerUrls.includes(url)
112
127
 
113
128
  let ressourceBuilder
114
129
  let importResolver
@@ -132,6 +147,12 @@ export const createRollupPlugins = async ({
132
147
  urlMappings,
133
148
  })
134
149
 
150
+ const urlVersioner = createUrlVersioner({
151
+ entryPointUrls,
152
+ asOriginalUrl,
153
+ lineBreakNormalization,
154
+ })
155
+
135
156
  const urlFetcher = createUrlFetcher({
136
157
  asOriginalUrl,
137
158
  asProjectUrl,
@@ -142,13 +163,11 @@ export const createRollupPlugins = async ({
142
163
  },
143
164
  })
144
165
 
166
+ const urlCustomLoaders = {}
145
167
  const urlLoader = createUrlLoader({
146
- projectDirectoryUrl,
147
- buildDirectoryUrl,
148
- babelPluginMap,
168
+ urlCustomLoaders,
149
169
  allowJson: acceptsJsonContentType({ node, format }),
150
170
  urlImporterMap,
151
- inlineModuleScripts,
152
171
  jsConcatenation,
153
172
 
154
173
  asServerUrl,
@@ -163,41 +182,29 @@ export const createRollupPlugins = async ({
163
182
  projectDirectoryUrl,
164
183
  )
165
184
 
166
- // map fileName (build relative urls without hash) to build relative url
167
- let buildManifest = {}
168
- const buildRelativeUrlToFileName = (buildRelativeUrl) => {
169
- const fileName = Object.keys(buildManifest).find(
170
- (key) => buildManifest[key] === buildRelativeUrl,
171
- )
172
- return fileName
173
- }
174
- const buildRelativeUrlsUsedInJs = []
175
- const markBuildRelativeUrlAsUsedByJs = (buildRelativeUrl) => {
176
- buildRelativeUrlsUsedInJs.push(buildRelativeUrl)
177
- buildManifest[rollupFileNameWithoutHash(buildRelativeUrl)] =
178
- buildRelativeUrl
179
- }
185
+ // Object mapping project relative urls to build relative urls
186
+ let buildMappings = {}
187
+ // Object mapping ressource names to build relative urls
188
+ let ressourceMappings = {}
189
+
190
+ const ressourcesReferencedByJs = []
180
191
  const createImportMapForFilesUsedInJs = () => {
181
192
  const topLevelMappings = {}
182
- buildRelativeUrlsUsedInJs
183
- .sort(comparePathnames)
184
- .forEach((buildRelativeUrl) => {
185
- const fileName = buildRelativeUrlToFileName(buildRelativeUrl)
186
- if (fileName !== buildRelativeUrl) {
187
- topLevelMappings[`./${fileName}`] = `./${buildRelativeUrl}`
188
- }
189
- })
193
+ ressourcesReferencedByJs.sort(comparePathnames).forEach((ressourceName) => {
194
+ const buildRelativeUrl = ressourceMappings[ressourceName]
195
+ if (
196
+ ressourceName &&
197
+ buildRelativeUrl &&
198
+ ressourceName !== buildRelativeUrl
199
+ ) {
200
+ topLevelMappings[`./${ressourceName}`] = `./${buildRelativeUrl}`
201
+ }
202
+ })
190
203
  return {
191
204
  imports: topLevelMappings,
192
205
  }
193
206
  }
194
207
 
195
- let buildMappings = {}
196
- // an object where keys are build relative urls
197
- // and values rollup chunk or asset
198
- // we need this because we sometimes tell rollup
199
- // that a file.fileName is something while it's not really this
200
- // because of remapping
201
208
  let rollupBuild
202
209
 
203
210
  const EMPTY_CHUNK_URL = resolveUrl("__empty__", projectDirectoryUrl)
@@ -313,6 +320,7 @@ export const createRollupPlugins = async ({
313
320
  : resolveUrl(chunk.fileName, buildDirectoryUrl),
314
321
  code,
315
322
  map,
323
+ module: format === "esmodule",
316
324
  ...(format === "global" ? { toplevel: false } : { toplevel: true }),
317
325
  })
318
326
 
@@ -329,9 +337,9 @@ export const createRollupPlugins = async ({
329
337
  name: "jsenv",
330
338
 
331
339
  async buildStart() {
332
- logger.info(formatBuildStartLog({ entryPointMap }))
340
+ logger.info(formatBuildStartLog({ entryPoints }))
333
341
 
334
- const entryPointsPrepared = await prepareEntryPoints(entryPointMap, {
342
+ const entryPointsPrepared = await prepareEntryPoints(entryPoints, {
335
343
  logger,
336
344
  projectDirectoryUrl,
337
345
  buildDirectoryUrl,
@@ -360,7 +368,7 @@ export const createRollupPlugins = async ({
360
368
  if (typeof useImportMapToMaximizeCacheReuse === "undefined") {
361
369
  useImportMapToMaximizeCacheReuse =
362
370
  htmlEntryPointCount > 0 &&
363
- // node has no importmap concept, le'ts use the versionned url in that case
371
+ // node has no importmap concept, let's use the versionned url in that case
364
372
  !node
365
373
  }
366
374
 
@@ -442,9 +450,21 @@ export const createRollupPlugins = async ({
442
450
  )
443
451
  importMapUrl = htmlCompiledUrl
444
452
  fetchImportMap = () => {
445
- const importMapRaw = JSON.parse(importMapInfoFromHtml.text)
446
- const importMap = normalizeImportMap(importMapRaw, importMapUrl)
447
- return importMap
453
+ const importmapFileUrl = asProjectUrl(importMapUrl)
454
+ const jsenvImportmap = getDefaultImportmap(importmapFileUrl, {
455
+ projectDirectoryUrl,
456
+ compileDirectoryUrl,
457
+ })
458
+ const htmlImportmap = JSON.parse(importMapInfoFromHtml.text)
459
+ const importmap = composeTwoImportMaps(
460
+ jsenvImportmap,
461
+ htmlImportmap,
462
+ )
463
+ const importmapNormalized = normalizeImportMap(
464
+ importmap,
465
+ importMapUrl,
466
+ )
467
+ return importmapNormalized
448
468
  }
449
469
  }
450
470
  } else if (importMapFileRelativeUrl) {
@@ -459,7 +479,7 @@ export const createRollupPlugins = async ({
459
479
  )
460
480
  }
461
481
  } else {
462
- // there is no importmap, its' fine it's not mandatory to use one
482
+ // there is no importmap, it's fine, it's not mandatory
463
483
  fetchImportMap = () => {
464
484
  const firstEntryPoint = htmlEntryPoints[0] || entryPointsPrepared[0]
465
485
  const { entryProjectRelativeUrl } = firstEntryPoint
@@ -467,16 +487,19 @@ export const createRollupPlugins = async ({
467
487
  entryProjectRelativeUrl,
468
488
  compileDirectoryUrl,
469
489
  )
470
- const defaultImportMap = getDefaultImportMap({
471
- importMapFileUrl: entryCompileUrl,
490
+ const jsenvImportmap = getDefaultImportmap(entryCompileUrl, {
472
491
  projectDirectoryUrl,
473
- compileDirectoryRelativeUrl,
492
+ compileDirectoryUrl,
474
493
  })
475
494
  const entryCompileServerUrl = resolveUrl(
476
495
  entryProjectRelativeUrl,
477
496
  compileDirectoryServerUrl,
478
497
  )
479
- return normalizeImportMap(defaultImportMap, entryCompileServerUrl)
498
+ const importmapNormalized = normalizeImportMap(
499
+ jsenvImportmap,
500
+ entryCompileServerUrl,
501
+ )
502
+ return importmapNormalized
480
503
  }
481
504
  }
482
505
 
@@ -603,13 +626,27 @@ export const createRollupPlugins = async ({
603
626
  }
604
627
 
605
628
  const originalUrl = asOriginalUrl(projectUrl)
606
- if (isWorkerUrl(originalUrl)) {
629
+ if (workerUrls.includes(originalUrl)) {
630
+ return {
631
+ isWorker: true,
632
+ isJsModule: true,
633
+ url: ressourceUrl,
634
+ }
635
+ }
636
+ if (serviceWorkerUrls.includes(originalUrl)) {
637
+ return {
638
+ isServiceWorker: true,
639
+ isJsModule: true,
640
+ url: ressourceUrl,
641
+ }
642
+ }
643
+ if (classicWorkerUrls.includes(originalUrl)) {
607
644
  return {
608
645
  isWorker: true,
609
646
  url: ressourceUrl,
610
647
  }
611
648
  }
612
- if (isServiceWorkerUrl(originalUrl)) {
649
+ if (classicServiceWorkerUrls.includes(originalUrl)) {
613
650
  return {
614
651
  isServiceWorker: true,
615
652
  url: ressourceUrl,
@@ -618,34 +655,79 @@ export const createRollupPlugins = async ({
618
655
 
619
656
  return ressourceUrl
620
657
  },
621
- emitChunk,
622
- emitAsset,
623
- setAssetSource,
624
658
  onJsModule: ({ ressource, jsModuleUrl, jsModuleIsInline }) => {
625
- if (jsModuleIsInline) {
626
- inlineModuleScripts[jsModuleUrl] = ressource
659
+ // we want to emit chunk only when ressource is referenced by something else than rollup
660
+ if (
661
+ jsConcatenation &&
662
+ ressource.references.every((ref) => ref.fromRollup)
663
+ ) {
664
+ return null
627
665
  }
628
666
 
629
- urlImporterMap[jsModuleUrl] = {
630
- url: resolveUrl(
667
+ if (ressource.isEntryPoint) {
668
+ } else {
669
+ const importerUrl = resolveUrl(
631
670
  entryPointsPrepared[0].entryProjectRelativeUrl,
632
671
  compileDirectoryServerUrl,
633
- ),
634
- line: undefined,
635
- column: undefined,
672
+ )
673
+ urlImporterMap[jsModuleUrl] = {
674
+ url: importerUrl,
675
+ line: undefined,
676
+ column: undefined,
677
+ }
678
+ jsModulesFromEntry[asRollupUrl(jsModuleUrl)] = true
679
+ if (jsModuleIsInline) {
680
+ inlineModuleScripts[jsModuleUrl] = ressource
681
+ urlCustomLoaders[jsModuleUrl] = async () => {
682
+ const transformResult = await transformJs({
683
+ code: String(
684
+ inlineModuleScripts[jsModuleUrl].bufferBeforeBuild,
685
+ ),
686
+ url: asOriginalUrl(jsModuleUrl), // transformJs expect a file:// url
687
+ projectDirectoryUrl,
688
+ babelPluginMap,
689
+ // moduleOutFormat: format // we are compiling for rollup output must be "esmodule"
690
+ // we compile for rollup, let top level await untouched
691
+ // it will be converted, if needed, during "renderChunk" hook
692
+ topLevelAwait: "ignore",
693
+ })
694
+ let code = transformResult.code
695
+ let map = transformResult.map
696
+ return {
697
+ code,
698
+ map,
699
+ }
700
+ }
701
+ }
636
702
  }
637
- jsModulesFromEntry[asRollupUrl(jsModuleUrl)] = true
638
- const name = urlToBasename(jsModuleUrl)
703
+
704
+ const fileName = ressource.relativeUrl
639
705
  const rollupReferenceId = emitChunk({
640
- id: asRollupUrl(jsModuleUrl),
641
- name,
706
+ id: jsModuleUrl,
707
+ name: urlToBasename(jsModuleUrl),
642
708
  })
643
709
  return {
644
- name,
645
710
  rollupReferenceId,
711
+ fileName,
646
712
  }
647
713
  },
648
- lineBreakNormalization,
714
+ onAsset: ({ ressource }) => {
715
+ const fileName = ressource.relativeUrl
716
+ const rollupReferenceId = emitAsset({
717
+ fileName,
718
+ })
719
+ return {
720
+ rollupReferenceId,
721
+ fileName,
722
+ }
723
+ },
724
+ onAssetSourceUpdated: ({ ressource }) => {
725
+ setAssetSource(
726
+ ressource.rollupReferenceId,
727
+ ressource.bufferAfterBuild,
728
+ )
729
+ },
730
+ urlVersioner,
649
731
  },
650
732
  )
651
733
 
@@ -654,16 +736,15 @@ export const createRollupPlugins = async ({
654
736
  async ({
655
737
  entryContentType,
656
738
  entryProjectRelativeUrl,
657
- entryBuildRelativeUrl,
658
739
  entryBuffer,
659
740
  }) => {
660
741
  if (entryContentType === "application/javascript") {
661
- emitChunk({
662
- id: ensureRelativeUrlNotation(entryProjectRelativeUrl),
663
- name: urlToBasename(`file:///${entryBuildRelativeUrl}`),
664
- ...(urlVersionningForEntryPoints
665
- ? {}
666
- : { fileName: entryBuildRelativeUrl }),
742
+ await ressourceBuilder.createReferenceForEntryPoint({
743
+ entryContentType,
744
+ entryUrl: resolveUrl(
745
+ entryProjectRelativeUrl,
746
+ compileDirectoryServerUrl,
747
+ ),
667
748
  })
668
749
  return
669
750
  }
@@ -684,8 +765,6 @@ export const createRollupPlugins = async ({
684
765
  entryContentType,
685
766
  entryUrl,
686
767
  entryBuffer,
687
- entryBuildRelativeUrl,
688
- urlVersionningForEntryPoints,
689
768
  })
690
769
  },
691
770
  ),
@@ -699,15 +778,20 @@ export const createRollupPlugins = async ({
699
778
  }
700
779
  },
701
780
 
702
- async resolveId(specifier, importer, { custom }) {
781
+ async resolveId(specifier, importer, { custom = {} } = {}) {
782
+ if (specifier === EMPTY_CHUNK_URL) {
783
+ return specifier
784
+ }
785
+
786
+ let importerUrl
703
787
  if (importer === undefined) {
704
788
  if (specifier.endsWith(".html")) {
705
- importer = compileServerOrigin
789
+ importerUrl = compileServerOrigin
706
790
  } else {
707
- importer = compileDirectoryServerUrl
791
+ importerUrl = compileDirectoryServerUrl
708
792
  }
709
793
  } else {
710
- importer = asServerUrl(importer)
794
+ importerUrl = asServerUrl(importer)
711
795
  }
712
796
 
713
797
  const { importAssertionInfo } = custom
@@ -732,25 +816,23 @@ export const createRollupPlugins = async ({
732
816
  }
733
817
 
734
818
  if (inlineModuleScripts.hasOwnProperty(specifier)) {
735
- return specifier
736
- }
737
-
738
- if (isFileSystemPath(importer)) {
739
- importer = fileSystemPathToUrl(importer)
819
+ return asRollupUrl(specifier)
740
820
  }
741
821
 
742
- const importUrl = await importResolver.resolveImport(specifier, importer)
743
-
822
+ const importUrl = await importResolver.resolveImport(
823
+ specifier,
824
+ importerUrl,
825
+ )
744
826
  const existingImporter = urlImporterMap[importUrl]
745
827
  if (!existingImporter) {
746
828
  urlImporterMap[importUrl] = importAssertionInfo
747
829
  ? {
748
- url: importer,
830
+ url: importerUrl,
749
831
  column: importAssertionInfo.column,
750
832
  line: importAssertionInfo.line,
751
833
  }
752
834
  : {
753
- url: importer,
835
+ url: importerUrl,
754
836
  // rollup do not expose a way to know line and column for the static or dynamic import
755
837
  // referencing that file
756
838
  column: undefined,
@@ -782,34 +864,29 @@ export const createRollupPlugins = async ({
782
864
  },
783
865
 
784
866
  resolveFileUrl: ({ referenceId, fileName }) => {
785
- const ressourceFound = ressourceBuilder.findRessource((ressource) => {
786
- return ressource.rollupReferenceId === referenceId
787
- })
788
- const buildRelativeUrl = ressourceFound
789
- ? ressourceFound.buildRelativeUrl
790
- : fileName
791
-
867
+ ressourcesReferencedByJs.push(fileName)
868
+ const getBuildRelativeUrl = () => {
869
+ const ressource = ressourceBuilder.findRessource((ressource) => {
870
+ return ressource.rollupReferenceId === referenceId
871
+ })
872
+ ressource.fileName = fileName
873
+ const buildRelativeUrl = ressource.buildRelativeUrl
874
+ return buildRelativeUrl
875
+ }
792
876
  if (format === "esmodule") {
793
877
  if (!node && useImportMapToMaximizeCacheReuse && urlVersioning) {
794
- const buildRelativeUrlWithoutVersion =
795
- buildRelativeUrlToFileName(buildRelativeUrl)
796
- return `window.__resolveImportUrl__("./${buildRelativeUrlWithoutVersion}", import.meta.url)`
878
+ return `window.__resolveImportUrl__("./${fileName}", import.meta.url)`
797
879
  }
798
- return `new URL("${buildRelativeUrl}", import.meta.url)`
880
+ return `new URL("${getBuildRelativeUrl()}", import.meta.url)`
799
881
  }
800
882
  if (format === "systemjs") {
801
- if (useImportMapToMaximizeCacheReuse && urlVersioning) {
802
- const buildRelativeUrlWithoutVersion =
803
- buildRelativeUrlToFileName(buildRelativeUrl)
804
- return `new URL(System.resolve("./${buildRelativeUrlWithoutVersion}", module.meta.url))`
805
- }
806
- return `new URL(System.resolve("./${buildRelativeUrl}", module.meta.url))`
883
+ return `new URL(System.resolve("./${fileName}", module.meta.url))`
807
884
  }
808
885
  if (format === "global") {
809
- return `new URL("${buildRelativeUrl}", document.currentScript && document.currentScript.src || document.baseURI)`
886
+ return `new URL("${getBuildRelativeUrl()}", document.currentScript && document.currentScript.src || document.baseURI)`
810
887
  }
811
888
  if (format === "commonjs") {
812
- return `new URL("${buildRelativeUrl}", "file:///" + __filename.replace(/\\/g, "/"))`
889
+ return `new URL("${getBuildRelativeUrl()}", "file:///" + __filename.replace(/\\/g, "/"))`
813
890
  }
814
891
  return null
815
892
  },
@@ -830,11 +907,10 @@ export const createRollupPlugins = async ({
830
907
  return urlLoader.loadUrl(rollupUrl, {
831
908
  signal,
832
909
  logger,
833
- ressourceBuilder,
834
910
  })
835
911
  })
836
912
 
837
- url = loadResult.url
913
+ if (loadResult.url) url = loadResult.url
838
914
  const code = loadResult.code
839
915
  const map = loadResult.map
840
916
 
@@ -846,6 +922,7 @@ export const createRollupPlugins = async ({
846
922
  originalUrl,
847
923
  jsenvHelpersDirectoryInfo.url,
848
924
  )
925
+ // const isEntryPoint = entryPointUrls[originalUrl]
849
926
 
850
927
  const importer = urlImporterMap[url]
851
928
  // Inform ressource builder that this js module exists
@@ -855,18 +932,12 @@ export const createRollupPlugins = async ({
855
932
  // For import assertions, the imported ressource (css,json,...)
856
933
  // is arelady converted to a js module
857
934
  ressourceBuilder.createReferenceFoundByRollup({
858
- // we don't want to emit a js chunk for every js file found
859
- // (However we want if the file is preload/prefetch by something else)
860
- // so we tell asset builder not to emit a chunk for this js reference
861
- // otherwise rollup would never concat module together
862
- referenceShouldNotEmitChunk: jsConcatenation,
863
935
  contentTypeExpected: "application/javascript",
864
936
  referenceLabel: "static or dynamic import",
865
937
  referenceUrl: importer.url,
866
938
  referenceColumn: importer.column,
867
939
  referenceLine: importer.line,
868
940
  ressourceSpecifier: url,
869
-
870
941
  isJsenvHelperFile,
871
942
  contentType: "application/javascript",
872
943
  bufferBeforeBuild: Buffer.from(code),
@@ -896,18 +967,30 @@ export const createRollupPlugins = async ({
896
967
  onReferenceWithImportMetaUrlPattern: async ({ importNode }) => {
897
968
  const specifier = importNode.arguments[0].value
898
969
  const { line, column } = importNode.loc.start
899
- const reference =
900
- await ressourceBuilder.createReferenceFoundInJsModule({
901
- referenceLabel: "URL + import.meta.url",
902
- jsUrl: url,
903
- jsLine: line,
904
- jsColumn: column,
905
- ressourceSpecifier: specifier,
906
- })
970
+
971
+ const { id } = normalizeRollupResolveReturnValue(
972
+ await this.resolve(specifier, url),
973
+ )
974
+ const ressourceUrl = asServerUrl(id)
975
+ const originalUrl = asOriginalUrl(ressourceUrl)
976
+ const isJsModule = Boolean(
977
+ workerUrls[originalUrl] || serviceWorkerUrls[originalUrl],
978
+ )
979
+ const reference = ressourceBuilder.createReferenceFoundInJsModule({
980
+ referenceLabel: "URL + import.meta.url",
981
+ jsUrl: url,
982
+ jsLine: line,
983
+ jsColumn: column,
984
+ ressourceSpecifier: ressourceUrl,
985
+ isJsModule,
986
+ })
907
987
  if (!reference) {
908
988
  return
909
989
  }
910
- markBuildRelativeUrlAsUsedByJs(reference.ressource.buildRelativeUrl)
990
+ if (!reference.ressource.isJsModule) {
991
+ // so that ressource.buildRelativeUrl is known during "resolveFileUrl" hook`
992
+ await reference.ressource.getReadyPromise()
993
+ }
911
994
  mutations.push((magicString) => {
912
995
  magicString.overwrite(
913
996
  importNode.start,
@@ -924,7 +1007,6 @@ export const createRollupPlugins = async ({
924
1007
  const { source } = importNode
925
1008
  const importSpecifier = source.value
926
1009
  const { line, column } = importNode.loc.start
927
-
928
1010
  // "type" is dynamic on dynamic import such as
929
1011
  // import("./data.json", {
930
1012
  // assert: {
@@ -952,9 +1034,7 @@ export const createRollupPlugins = async ({
952
1034
  type: typePropertyValue.value,
953
1035
  }
954
1036
  }
955
-
956
1037
  const { type } = assertions
957
-
958
1038
  // "specifier" is dynamic on dynamic import such as
959
1039
  // import(true ? "./a.json" : "b.json", {
960
1040
  // assert: {
@@ -978,9 +1058,7 @@ export const createRollupPlugins = async ({
978
1058
  ),
979
1059
  )
980
1060
  }
981
-
982
1061
  // There is no strategy for css import assertion on Node.js
983
- // and that's normal
984
1062
  if (type === "css" && node) {
985
1063
  throw new Error(
986
1064
  createDetailedMessage(
@@ -1006,29 +1084,31 @@ export const createRollupPlugins = async ({
1006
1084
  },
1007
1085
  }),
1008
1086
  )
1009
-
1010
- const ressourceUrl = asServerUrl(id)
1011
- if (external) {
1012
- if (importAssertionSupportedByRuntime) {
1013
- const reference =
1014
- await ressourceBuilder.createReferenceFoundInJsModule({
1015
- referenceLabel: "import assertion",
1016
- isImportAssertion: true,
1017
- jsUrl: url,
1018
- jsLine: line,
1019
- jsColumn: column,
1020
- ressourceSpecifier: ressourceUrl,
1021
- })
1022
- // reference can be null for cross origin urls
1023
- if (!reference) {
1024
- return
1025
- }
1026
- markBuildRelativeUrlAsUsedByJs(
1027
- reference.ressource.buildRelativeUrl,
1028
- )
1029
- return
1030
- }
1031
-
1087
+ // remove import
1088
+ let ressourceUrl = asServerUrl(id)
1089
+ // lod the asset without ?import_type in it
1090
+ ressourceUrl = ressourceUrl.replace(`?import_type=${type}`, "")
1091
+ const fileReference = ressourceBuilder.createReferenceFoundInJsModule(
1092
+ {
1093
+ referenceLabel: `${type} import assertion`,
1094
+ // If all references to a ressource are only import assertions
1095
+ // the file referenced do not need to be written on filesystem
1096
+ // as it was converted to a js file
1097
+ // We pass "isImportAssertion: true" for this purpose
1098
+ isImportAssertion: true,
1099
+ jsUrl: url,
1100
+ jsLine: line,
1101
+ jsColumn: column,
1102
+ ressourceSpecifier: ressourceUrl,
1103
+ contentTypeExpected:
1104
+ type === "css" ? "text/css" : "application/json",
1105
+ },
1106
+ )
1107
+ // reference can be null for cross origin urls
1108
+ if (!fileReference) {
1109
+ return
1110
+ }
1111
+ if (external && !importAssertionSupportedByRuntime) {
1032
1112
  throw new Error(
1033
1113
  createDetailedMessage(
1034
1114
  `import assertion ressource cannot be external when runtime do not support import assertions`,
@@ -1041,16 +1121,64 @@ export const createRollupPlugins = async ({
1041
1121
  )
1042
1122
  }
1043
1123
 
1044
- // we want to convert the import assertions into a js module
1045
- // to do that we append ?import_type to the url
1046
- // In theory this is not needed anymore:
1047
- // This is already done by the compile server
1048
- const ressourceUrlAsJsModule = setUrlSearchParamsDescriptor(
1124
+ // await fileReference.ressource.getReadyPromise()
1125
+ // once the file is ready, we know its buildRelativeUrl
1126
+ // we can update either to the fileName or buildRelativeUrl
1127
+ // should be use the rollup reference id?
1128
+ const ressourceUrlAsJsModule = resolveUrl(
1129
+ `${urlToBasename(
1130
+ ressourceUrl,
1131
+ )}${outputExtension}?import_type=${type}`,
1049
1132
  ressourceUrl,
1050
- {
1051
- import_type: type,
1052
- },
1053
1133
  )
1134
+ const jsUrl = url
1135
+ urlCustomLoaders[ressourceUrlAsJsModule] = async () => {
1136
+ let code
1137
+ let map
1138
+
1139
+ if (type === "json") {
1140
+ await fileReference.ressource.getReadyPromise()
1141
+ code = String(fileReference.ressource.bufferAfterBuild)
1142
+ const jsModuleConversionResult =
1143
+ await convertJsonTextToJavascriptModule({
1144
+ code,
1145
+ map,
1146
+ })
1147
+ code = jsModuleConversionResult.code
1148
+ map = jsModuleConversionResult.map
1149
+ } else if (type === "css") {
1150
+ await fileReference.ressource.getReadyPromise()
1151
+ const cssBuildUrl = resolveUrl(
1152
+ fileReference.ressource.buildRelativeUrl,
1153
+ buildDirectoryUrl,
1154
+ )
1155
+ const jsBuildUrl = resolveUrl(
1156
+ urlToFilename(jsUrl),
1157
+ buildDirectoryUrl,
1158
+ )
1159
+ code = String(fileReference.ressource.bufferAfterBuild)
1160
+ const sourcemapReference =
1161
+ fileReference.ressource.dependencies.find((dependency) => {
1162
+ return dependency.ressource.isSourcemap
1163
+ })
1164
+ if (sourcemapReference) {
1165
+ // because css is ready, it's sourcemap is also ready
1166
+ // we can read directly sourcemapReference.ressource.bufferAfterBuild
1167
+ map = JSON.parse(sourcemapReference.ressource.bufferAfterBuild)
1168
+ }
1169
+ const jsModuleConversionResult =
1170
+ await convertCssTextToJavascriptModule({
1171
+ cssUrl: cssBuildUrl,
1172
+ jsUrl: jsBuildUrl,
1173
+ code,
1174
+ map,
1175
+ })
1176
+ code = jsModuleConversionResult.code
1177
+ map = jsModuleConversionResult.map
1178
+ }
1179
+
1180
+ return { code, map }
1181
+ }
1054
1182
 
1055
1183
  mutations.push((magicString) => {
1056
1184
  magicString.overwrite(
@@ -1078,9 +1206,6 @@ export const createRollupPlugins = async ({
1078
1206
 
1079
1207
  // resolveImportMeta: () => {}
1080
1208
  outputOptions: (outputOptions) => {
1081
- const extension = extname(entryPointMap[Object.keys(entryPointMap)[0]])
1082
- const outputExtension = extension === ".html" ? ".js" : extension
1083
-
1084
1209
  outputOptions.paths = (id) => {
1085
1210
  const mapping = importPaths[id]
1086
1211
  if (mapping) {
@@ -1093,19 +1218,31 @@ export const createRollupPlugins = async ({
1093
1218
  }
1094
1219
  return id
1095
1220
  }
1221
+ // outputOptions.assetFileNames = () => {
1222
+ // return `assets/[name]_[hash][extname]`
1223
+ // }
1096
1224
  outputOptions.entryFileNames = () => {
1097
- if (urlVersionningForEntryPoints) {
1098
- return `[name]-[hash]${outputExtension}`
1225
+ if (useImportMapToMaximizeCacheReuse) {
1226
+ return `[name]${outputExtension}`
1099
1227
  }
1100
- return `[name]${outputExtension}`
1228
+ return entryPoints
1101
1229
  }
1102
- outputOptions.chunkFileNames = () => {
1230
+ outputOptions.chunkFileNames = (chunkInfo) => {
1103
1231
  // const originalUrl = asOriginalUrl(chunkInfo.facadeModuleId)
1104
1232
  // const basename = urlToBasename(originalUrl)
1105
1233
  if (useImportMapToMaximizeCacheReuse) {
1106
1234
  return `[name]${outputExtension}`
1107
1235
  }
1108
- return `[name]-[hash]${outputExtension}`
1236
+ if (chunkInfo.isEntry) {
1237
+ const originalUrl = asOriginalUrl(chunkInfo.facadeModuleId)
1238
+ const entryPointPattern = entryPointUrls[originalUrl]
1239
+ if (entryPointPattern) {
1240
+ return entryPointPattern
1241
+ }
1242
+ }
1243
+ return urlVersioning
1244
+ ? `[name]_[hash]${outputExtension}`
1245
+ : `[name]${outputExtension}`
1109
1246
  }
1110
1247
 
1111
1248
  // rollup does not expects to have http dependency in the mix: fix them
@@ -1137,190 +1274,204 @@ export const createRollupPlugins = async ({
1137
1274
  return outputOptions
1138
1275
  },
1139
1276
 
1277
+ async renderChunk(code, chunk) {
1278
+ const { facadeModuleId } = chunk
1279
+ if (!facadeModuleId) {
1280
+ // happens for inline module scripts for instance
1281
+ return null
1282
+ }
1283
+
1284
+ const url = asOriginalUrl(facadeModuleId)
1285
+ if (workerUrls.includes(url) || serviceWorkerUrls.includes(url)) {
1286
+ const magicString = new MagicString(code)
1287
+ const systemjsCode = await readFile(
1288
+ new URL("../runtime/s.js", import.meta.url),
1289
+ )
1290
+ magicString.prepend(systemjsCode)
1291
+ code = magicString.toString()
1292
+ const map = magicString.generateMap({ hires: true })
1293
+ return {
1294
+ code,
1295
+ map,
1296
+ }
1297
+ }
1298
+
1299
+ return null
1300
+ },
1301
+
1140
1302
  async generateBundle(outputOptions, rollupResult) {
1141
- const jsChunks = {}
1303
+ // it's important to do this to emit late asset
1304
+ rollupEmitFile = (...args) => this.emitFile(...args)
1305
+ rollupSetAssetSource = (...args) => this.setAssetSource(...args)
1142
1306
  // To keep in mind: rollupResult object can be mutated by late asset emission
1143
1307
  // however late chunk (js module) emission is not possible
1144
1308
  // as rollup rightfully prevent late js emission
1145
1309
  Object.keys(rollupResult).forEach((fileName) => {
1146
- const file = rollupResult[fileName]
1147
-
1310
+ const rollupFileInfo = rollupResult[fileName]
1148
1311
  // there is 3 types of file: "placeholder", "asset", "chunk"
1149
- if (file.type === "asset") {
1150
- return
1151
- }
1152
-
1153
- if (file.type === "chunk") {
1154
- const { facadeModuleId } = file
1312
+ if (rollupFileInfo.type === "chunk") {
1313
+ const { facadeModuleId } = rollupFileInfo
1155
1314
  if (facadeModuleId === EMPTY_CHUNK_URL) {
1315
+ delete rollupResult[fileName]
1156
1316
  return
1157
1317
  }
1158
- const fileCopy = { ...file }
1159
1318
  if (facadeModuleId) {
1160
- fileCopy.url = asServerUrl(facadeModuleId)
1319
+ rollupFileInfo.url = asServerUrl(facadeModuleId)
1161
1320
  } else {
1162
- const sourcePath = file.map.sources[file.map.sources.length - 1]
1163
- const fileBuildUrl = resolveUrl(file.fileName, buildDirectoryUrl)
1321
+ const sourcePath =
1322
+ rollupFileInfo.map.sources[rollupFileInfo.map.sources.length - 1]
1323
+ const fileBuildUrl = resolveUrl(fileName, buildDirectoryUrl)
1164
1324
  const originalProjectUrl = resolveUrl(sourcePath, fileBuildUrl)
1165
- fileCopy.url = asCompiledServerUrl(originalProjectUrl, {
1325
+ rollupFileInfo.url = asCompiledServerUrl(originalProjectUrl, {
1166
1326
  projectDirectoryUrl,
1167
1327
  compileServerOrigin,
1168
1328
  compileDirectoryRelativeUrl,
1169
1329
  })
1170
1330
  }
1171
- jsChunks[fileName] = fileCopy
1172
- }
1173
- })
1174
-
1175
- const jsModuleBuild = {}
1176
- Object.keys(jsChunks).forEach((fileName) => {
1177
- const file = jsChunks[fileName]
1178
- let buildRelativeUrl
1179
- const canBeVersioned =
1180
- asRollupUrl(file.url) in jsModulesFromEntry ||
1181
- urlVersionningForEntryPoints ||
1182
- !file.isEntry
1183
-
1184
- if (file.url in inlineModuleScripts && format === "systemjs") {
1185
- const code = file.code
1186
- const systemRegisterIndex = code.indexOf("System.register([")
1187
- const magicString = new MagicString(code)
1188
- magicString.overwrite(
1189
- systemRegisterIndex,
1190
- systemRegisterIndex + "System.register([".length,
1191
- `System.register("${fileName}", [`,
1192
- )
1193
- file.code = magicString.toString()
1194
- }
1195
1331
 
1196
- if (urlVersioning) {
1197
- if (canBeVersioned && useImportMapToMaximizeCacheReuse) {
1198
- buildRelativeUrl = computeBuildRelativeUrl(
1199
- resolveUrl(fileName, buildDirectoryUrl),
1200
- file.code,
1201
- {
1202
- pattern: `[name]-[hash][extname]`,
1203
- lineBreakNormalization,
1204
- contentType: "application/javascript",
1205
- },
1332
+ if (
1333
+ rollupFileInfo.url in inlineModuleScripts &&
1334
+ format === "systemjs"
1335
+ ) {
1336
+ const code = rollupFileInfo.code
1337
+ const systemRegisterIndex = code.indexOf("System.register([")
1338
+ const magicString = new MagicString(code)
1339
+ magicString.overwrite(
1340
+ systemRegisterIndex,
1341
+ systemRegisterIndex + "System.register([".length,
1342
+ `System.register("${fileName}", [`,
1206
1343
  )
1207
- } else {
1208
- buildRelativeUrl = fileName
1344
+ rollupFileInfo.code = magicString.toString()
1209
1345
  }
1210
- } else {
1211
- buildRelativeUrl = fileName
1212
- fileName = rollupFileNameWithoutHash(fileName)
1213
- }
1214
1346
 
1215
- const originalProjectUrl = asOriginalUrl(file.url)
1216
- const originalProjectRelativeUrl = urlToRelativeUrl(
1217
- originalProjectUrl,
1218
- projectDirectoryUrl,
1219
- )
1220
- const jsRessource = ressourceBuilder.findRessource(
1221
- (ressource) => ressource.url === file.url,
1222
- )
1223
- if (jsRessource && jsRessource.isInline) {
1224
- if (format === "systemjs") {
1225
- markBuildRelativeUrlAsUsedByJs(buildRelativeUrl)
1347
+ const jsRessource = ressourceBuilder.findRessource((ressource) => {
1348
+ return ressource.url === rollupFileInfo.url
1349
+ })
1350
+ if (
1351
+ isReferencedByJs({
1352
+ rollupFileInfo,
1353
+ jsConcatenation,
1354
+ jsRessource,
1355
+ })
1356
+ ) {
1357
+ ressourcesReferencedByJs.push(fileName)
1226
1358
  }
1227
- buildInlineFileContents[buildRelativeUrl] = file.code
1228
- } else {
1229
- markBuildRelativeUrlAsUsedByJs(buildRelativeUrl)
1230
- buildMappings[originalProjectRelativeUrl] = buildRelativeUrl
1231
1359
  }
1232
-
1233
- jsModuleBuild[buildRelativeUrl] = file
1234
1360
  })
1235
1361
 
1236
- // it's important to do this to emit late asset
1237
- rollupEmitFile = (...args) => this.emitFile(...args)
1238
- rollupSetAssetSource = (...args) => this.setAssetSource(...args)
1239
-
1240
1362
  // malheureusement rollup ne permet pas de savoir lorsqu'un chunk
1241
1363
  // a fini d'etre résolu (parsing des imports statiques et dynamiques recursivement)
1242
1364
  // donc lorsque le build se termine on va indiquer
1243
1365
  // aux assets faisant référence a ces chunk js qu'ils sont terminés
1244
1366
  // et donc les assets peuvent connaitre le nom du chunk
1245
1367
  // et mettre a jour leur dépendance vers ce fichier js
1246
- ressourceBuilder.rollupBuildEnd({ jsModuleBuild, buildManifest })
1368
+ const { jsRessources } = ressourceBuilder.rollupBuildEnd({
1369
+ rollupResult,
1370
+ useImportMapToMaximizeCacheReuse,
1371
+ })
1372
+ Object.keys(jsRessources).forEach((ressourceUrl) => {
1373
+ const jsRessource = jsRessources[ressourceUrl]
1374
+ if (jsRessource.isInline) {
1375
+ buildInlineFileContents[jsRessource.buildRelativeUrl] =
1376
+ jsRessource.bufferAfterBuild
1377
+ // if (format === "systemjs") {
1378
+ // ressourcesReferencedByJs.push(jsRessource.fileName)
1379
+ // }
1380
+ } else {
1381
+ const originalProjectUrl = asOriginalUrl(ressourceUrl)
1382
+ const originalProjectRelativeUrl = urlToRelativeUrl(
1383
+ originalProjectUrl,
1384
+ projectDirectoryUrl,
1385
+ )
1386
+ buildMappings[originalProjectRelativeUrl] =
1387
+ jsRessource.buildRelativeUrl
1388
+ }
1389
+ ressourceMappings[jsRessource.fileName] = jsRessource.buildRelativeUrl
1390
+ })
1391
+ // wait for asset build relative urls
1392
+ // to ensure the importmap will contain remappings for them
1393
+ // (not sure this is required anymore)
1394
+ await Promise.all(
1395
+ ressourcesReferencedByJs.map(async (ressourceName) => {
1396
+ const ressource = ressourceBuilder.findRessource((ressource) => {
1397
+ return ressource.relativeUrl === ressourceName
1398
+ })
1399
+ if (ressource && !ressource.isJsModule) {
1400
+ await ressource.getReadyPromise()
1401
+ ressourceMappings[ressourceName] = ressource.buildRelativeUrl
1402
+ }
1403
+ }),
1404
+ )
1247
1405
  // wait html files to be emitted
1248
1406
  await ressourceBuilder.getAllEntryPointsEmittedPromise()
1249
1407
  onBundleEnd()
1250
1408
 
1409
+ const jsModuleBuild = {}
1251
1410
  const assetBuild = {}
1252
- Object.keys(rollupResult).forEach((rollupFileId) => {
1253
- const file = rollupResult[rollupFileId]
1254
- if (file.type !== "asset") {
1255
- return
1256
- }
1257
-
1258
- const { facadeModuleId } = file
1259
- if (facadeModuleId === EMPTY_CHUNK_URL) {
1260
- return
1261
- }
1262
-
1263
- const assetRessource = ressourceBuilder.findRessource(
1264
- (ressource) => ressource.relativeUrl === rollupFileId,
1265
- )
1266
- if (!assetRessource) {
1267
- const buildRelativeUrl = rollupFileId
1268
- const fileName = rollupFileNameWithoutHash(buildRelativeUrl)
1269
- assetBuild[buildRelativeUrl] = file
1270
- buildManifest[fileName] = buildRelativeUrl
1271
- // the asset does not exists in the project it was generated during building
1272
- // happens for sourcemap
1273
- return
1274
- }
1275
-
1276
- // ignore potential useless assets which happens when:
1277
- // - sourcemap re-emitted
1278
- // - importmap re-emitted to have buildRelativeUrlMap
1279
- if (assetRessource.shouldBeIgnored) {
1280
- return
1281
- }
1411
+ Object.keys(rollupResult).forEach((fileName) => {
1412
+ const rollupFileInfo = rollupResult[fileName]
1282
1413
 
1283
- // Ignore file only referenced by import assertions
1284
- // - if file is referenced by import assertion and html or import meta url
1285
- // then source file is duplicated. If concatenation is disabled
1286
- // and import assertions are supported, the file is still converted to js module
1287
- const isReferencedOnlyByImportAssertions =
1288
- assetRessource.references.every((reference) => {
1289
- return reference.isImportAssertion
1414
+ if (rollupFileInfo.type === "chunk") {
1415
+ const jsRessource = ressourceBuilder.findRessource((ressource) => {
1416
+ return ressource.url === rollupFileInfo.url
1290
1417
  })
1291
- if (isReferencedOnlyByImportAssertions) {
1418
+ jsModuleBuild[jsRessource.buildRelativeUrl] = rollupFileInfo
1292
1419
  return
1293
1420
  }
1294
1421
 
1295
- const buildRelativeUrl = assetRessource.buildRelativeUrl
1296
- const fileName = rollupFileNameWithoutHash(buildRelativeUrl)
1297
- if (assetRessource.isInline) {
1298
- buildInlineFileContents[buildRelativeUrl] = file.source
1299
- } else {
1300
- const originalProjectUrl = asOriginalUrl(assetRessource.url)
1301
- const originalProjectRelativeUrl = urlToRelativeUrl(
1302
- originalProjectUrl,
1303
- projectDirectoryUrl,
1422
+ if (rollupFileInfo.type === "asset") {
1423
+ const assetRessource = ressourceBuilder.findRessource(
1424
+ (ressource) =>
1425
+ // happens for import.meta.url pattern
1426
+ ressource.fileName === fileName ||
1427
+ // happens for sourcemap
1428
+ ressource.relativeUrl === fileName,
1304
1429
  )
1430
+ // ignore potential useless assets which happens when:
1431
+ // - sourcemap re-emitted
1432
+ // - importmap re-emitted to have buildRelativeUrlMap
1433
+ if (assetRessource.shouldBeIgnored) {
1434
+ return
1435
+ }
1436
+ // Ignore file only referenced by import assertions
1437
+ // - if file is referenced by import assertion and html or import meta url
1438
+ // then source file is duplicated. If concatenation is disabled
1439
+ // and import assertions are supported, the file is still converted to js module
1440
+ const isReferencedOnlyByImportAssertions =
1441
+ assetRessource.references.every((reference) => {
1442
+ return reference.isImportAssertion
1443
+ })
1444
+ if (isReferencedOnlyByImportAssertions) {
1445
+ return
1446
+ }
1447
+ const buildRelativeUrl = assetRessource.buildRelativeUrl
1448
+ if (assetRessource.isInline) {
1449
+ buildInlineFileContents[buildRelativeUrl] = rollupFileInfo.source
1450
+ return
1451
+ }
1305
1452
  // in case sourcemap is mutated, we must not trust rollup but the asset builder source instead
1306
- file.source = assetRessource.bufferAfterBuild
1307
-
1308
- assetBuild[buildRelativeUrl] = file
1309
- buildMappings[originalProjectRelativeUrl] = buildRelativeUrl
1310
- buildManifest[fileName] = buildRelativeUrl
1453
+ rollupFileInfo.source = assetRessource.bufferAfterBuild
1454
+ assetBuild[buildRelativeUrl] = rollupFileInfo
1455
+ ressourceMappings[assetRessource.fileName] = buildRelativeUrl
1456
+ if (assetRessource.bufferBeforeBuild) {
1457
+ const originalProjectUrl = asOriginalUrl(assetRessource.url)
1458
+ const originalProjectRelativeUrl = urlToRelativeUrl(
1459
+ originalProjectUrl,
1460
+ projectDirectoryUrl,
1461
+ )
1462
+ buildMappings[originalProjectRelativeUrl] = buildRelativeUrl
1463
+ }
1464
+ return
1311
1465
  }
1312
1466
  })
1313
-
1314
1467
  rollupBuild = {
1315
1468
  ...jsModuleBuild,
1316
1469
  ...assetBuild,
1317
1470
  }
1318
- rollupBuild = injectSourcemapInRollupBuild(rollupBuild, {
1319
- buildDirectoryUrl,
1320
- })
1321
-
1322
- // update rollupBuild, buildInlineFilesContents, buildManifest and buildMappings
1323
- // in case some ressources where inlined by ressourceBuilder.rollupBuildEnd
1471
+ rollupBuild = sortObjectByPathnames(rollupBuild)
1472
+ // fill "buildFileContents", "buildInlineFilesContents"
1473
+ // and update "buildMappings"
1474
+ // in case some ressource where inlined by ressourceBuilder.rollupBuildEnd
1324
1475
  Object.keys(rollupBuild).forEach((buildRelativeUrl) => {
1325
1476
  const rollupFileInfo = rollupBuild[buildRelativeUrl]
1326
1477
  const ressource = ressourceBuilder.findRessource((ressource) => {
@@ -1332,38 +1483,37 @@ export const createRollupPlugins = async ({
1332
1483
  }
1333
1484
  return false
1334
1485
  })
1335
- if (ressource && ressource.isInline) {
1336
- const fileName = buildRelativeUrlToFileName(buildRelativeUrl)
1337
- if (fileName) {
1338
- delete buildManifest[fileName]
1486
+ if (ressource.isInline) {
1487
+ if (ressource.isJsModule) {
1488
+ delete jsModuleBuild[buildRelativeUrl]
1489
+ } else {
1490
+ delete assetBuild[buildRelativeUrl]
1339
1491
  }
1340
1492
  const originalProjectUrl = asOriginalUrl(ressource.url)
1341
- delete buildMappings[
1342
- urlToRelativeUrl(originalProjectUrl, projectDirectoryUrl)
1343
- ]
1344
- buildInlineFileContents[buildRelativeUrl] = rollupFileInfo.code
1345
- delete rollupBuild[buildRelativeUrl]
1493
+ const originalRelativeUrl = urlToRelativeUrl(
1494
+ originalProjectUrl,
1495
+ projectDirectoryUrl,
1496
+ )
1497
+ delete buildMappings[originalRelativeUrl]
1498
+ buildInlineFileContents[ressource.buildRelativeUrl] =
1499
+ ressource.bufferAfterBuild
1500
+ } else {
1501
+ buildFileContents[ressource.buildRelativeUrl] =
1502
+ ressource.bufferAfterBuild
1346
1503
  }
1347
1504
  })
1348
1505
 
1349
- await finalizeServiceWorkers({
1350
- serviceWorkers,
1351
- serviceWorkerFinalizer,
1506
+ ressourceMappings = sortObjectByPathnames(ressourceMappings)
1507
+ buildMappings = sortObjectByPathnames(buildMappings)
1508
+ await visitServiceWorkers({
1352
1509
  projectDirectoryUrl,
1353
- buildDirectoryUrl,
1354
- rollupBuild,
1510
+ serviceWorkerUrls,
1511
+ classicServiceWorkerUrls,
1512
+ serviceWorkerFinalizer,
1355
1513
  buildMappings,
1356
- buildManifest,
1514
+ ressourceMappings,
1515
+ buildFileContents,
1357
1516
  lineBreakNormalization,
1358
- minify,
1359
- })
1360
-
1361
- rollupBuild = sortObjectByPathnames(rollupBuild)
1362
- buildManifest = sortObjectByPathnames(buildManifest)
1363
- buildMappings = sortObjectByPathnames(buildMappings)
1364
- Object.keys(rollupBuild).forEach((buildRelativeUrl) => {
1365
- const { type, source, code } = rollupBuild[buildRelativeUrl]
1366
- buildFileContents[buildRelativeUrl] = type === "asset" ? source : code
1367
1517
  })
1368
1518
  const buildDuration = Date.now() - buildStartMs
1369
1519
  buildStats = createBuildStats({
@@ -1371,7 +1521,6 @@ export const createRollupPlugins = async ({
1371
1521
  ressourceBuilder,
1372
1522
  buildDuration,
1373
1523
  })
1374
-
1375
1524
  logger.info(
1376
1525
  formatBuildDoneInfo({
1377
1526
  buildStats,
@@ -1400,12 +1549,16 @@ export const createRollupPlugins = async ({
1400
1549
  return {
1401
1550
  rollupPlugins,
1402
1551
  getLastErrorMessage: () => lastErrorMessage,
1403
- getResult: () => {
1552
+ getResult: async () => {
1404
1553
  return {
1405
1554
  rollupBuild,
1406
1555
  urlResponseBodyMap: urlLoader.getUrlResponseBodyMap(),
1407
1556
  buildMappings,
1408
- buildManifest,
1557
+ ressourceMappings,
1558
+ // Object mapping build relative urls without hash to build relative urls
1559
+ buildManifest: createBuildManifest({
1560
+ buildFileContents,
1561
+ }),
1409
1562
  buildImportMap: createImportMapForFilesUsedInJs(),
1410
1563
  buildFileContents,
1411
1564
  buildInlineFileContents,
@@ -1418,8 +1571,23 @@ export const createRollupPlugins = async ({
1418
1571
  }
1419
1572
  }
1420
1573
 
1574
+ const createBuildManifest = ({ buildFileContents }) => {
1575
+ const buildManifest = {}
1576
+ Object.keys(buildFileContents).forEach((buildRelativeUrl) => {
1577
+ const relativeUrlWithoutHash = asFileNameWithoutHash(buildRelativeUrl)
1578
+ buildManifest[relativeUrlWithoutHash] = buildRelativeUrl
1579
+ })
1580
+ return buildManifest
1581
+ }
1582
+
1583
+ const asFileNameWithoutHash = (fileName) => {
1584
+ return fileName.replace(/_[a-z0-9]{8,}(\..*?)?$/, (_, afterHash = "") => {
1585
+ return afterHash
1586
+ })
1587
+ }
1588
+
1421
1589
  const prepareEntryPoints = async (
1422
- entryPointMap,
1590
+ entryPoints,
1423
1591
  {
1424
1592
  logger,
1425
1593
  projectDirectoryUrl,
@@ -1428,7 +1596,7 @@ const prepareEntryPoints = async (
1428
1596
  urlFetcher,
1429
1597
  },
1430
1598
  ) => {
1431
- const entryFileRelativeUrls = Object.keys(entryPointMap)
1599
+ const entryFileRelativeUrls = Object.keys(entryPoints)
1432
1600
  const entryPointsPrepared = []
1433
1601
  await entryFileRelativeUrls.reduce(async (previous, entryFileRelativeUrl) => {
1434
1602
  await previous
@@ -1438,10 +1606,9 @@ const prepareEntryPoints = async (
1438
1606
  projectDirectoryUrl,
1439
1607
  )
1440
1608
  const entryBuildUrl = resolveUrl(
1441
- entryPointMap[entryFileRelativeUrl],
1609
+ entryPoints[entryFileRelativeUrl],
1442
1610
  buildDirectoryUrl,
1443
1611
  )
1444
-
1445
1612
  const entryProjectRelativeUrl = urlToRelativeUrl(
1446
1613
  entryProjectUrl,
1447
1614
  projectDirectoryUrl,
@@ -1450,20 +1617,16 @@ const prepareEntryPoints = async (
1450
1617
  entryBuildUrl,
1451
1618
  buildDirectoryUrl,
1452
1619
  )
1453
-
1454
1620
  logger.debug(`${UNICODE.INFO} load entry point ${entryProjectRelativeUrl}`)
1455
-
1456
1621
  const entryServerUrl = resolveUrl(
1457
1622
  entryProjectRelativeUrl,
1458
1623
  compileServerOrigin,
1459
1624
  )
1460
-
1461
1625
  const entryResponse = await urlFetcher.fetchUrl(entryServerUrl, {
1462
- urlTrace: `entryPointMap`,
1626
+ urlTrace: `entryPoints`,
1463
1627
  })
1464
1628
  const entryContentType = entryResponse.headers["content-type"]
1465
1629
  const isHtml = entryContentType === "text/html"
1466
-
1467
1630
  entryPointsPrepared.push({
1468
1631
  entryContentType:
1469
1632
  entryContentType === "text/javascript"
@@ -1511,20 +1674,6 @@ const normalizeRollupResolveReturnValue = (resolveReturnValue) => {
1511
1674
  return resolveReturnValue
1512
1675
  }
1513
1676
 
1514
- const rollupFileNameWithoutHash = (fileName) => {
1515
- return fileName.replace(/-[a-z0-9]{8,}(\..*?)?$/, (_, afterHash = "") => {
1516
- return afterHash
1517
- })
1518
- }
1519
-
1520
- // otherwise importmap handle it as a bare import
1521
- const ensureRelativeUrlNotation = (relativeUrl) => {
1522
- if (relativeUrl.startsWith("../")) {
1523
- return relativeUrl
1524
- }
1525
- return `./${relativeUrl}`
1526
- }
1527
-
1528
1677
  const externalImportUrlPatternsToExternalUrlPredicate = (
1529
1678
  externalImportUrlPatterns,
1530
1679
  projectDirectoryUrl,
@@ -1560,32 +1709,59 @@ const acceptsJsonContentType = ({ node, format }) => {
1560
1709
  return false
1561
1710
  }
1562
1711
 
1563
- const finalizeServiceWorkers = async ({
1564
- serviceWorkers,
1712
+ const isReferencedByJs = ({ rollupFileInfo, jsConcatenation, jsRessource }) => {
1713
+ if (rollupFileInfo.isDynamicEntry) {
1714
+ return true
1715
+ }
1716
+ if (!jsConcatenation && rollupFileInfo.isEntry) {
1717
+ return true
1718
+ }
1719
+ if (
1720
+ jsRessource &&
1721
+ jsRessource.references.some((ref) => ref.isRessourceHint)
1722
+ ) {
1723
+ return true
1724
+ }
1725
+ return false
1726
+ }
1727
+
1728
+ const visitServiceWorkers = async ({
1729
+ projectDirectoryUrl,
1730
+ serviceWorkerUrls,
1731
+ classicServiceWorkerUrls,
1565
1732
  serviceWorkerFinalizer,
1566
1733
  buildMappings,
1567
- buildManifest,
1568
- rollupBuild,
1734
+ buildFileContents,
1569
1735
  lineBreakNormalization,
1570
1736
  }) => {
1737
+ const allServiceWorkerUrls = [
1738
+ ...serviceWorkerUrls,
1739
+ ...classicServiceWorkerUrls,
1740
+ ]
1741
+
1571
1742
  await Promise.all(
1572
- Object.keys(serviceWorkers).map(async (projectRelativeUrl) => {
1573
- const projectUrl = resolveUrl(projectRelativeUrl, "file://")
1574
- projectRelativeUrl = urlToRelativeUrl(projectUrl, "file://")
1575
- const serviceWorkerBuildRelativeUrl = buildMappings[projectRelativeUrl]
1743
+ allServiceWorkerUrls.map(async (serviceWorkerUrl) => {
1744
+ const serviceWorkerRelativeUrl = urlToRelativeUrl(
1745
+ serviceWorkerUrl,
1746
+ projectDirectoryUrl,
1747
+ )
1748
+ const serviceWorkerBuildRelativeUrl =
1749
+ buildMappings[serviceWorkerRelativeUrl]
1576
1750
  if (!serviceWorkerBuildRelativeUrl) {
1577
1751
  throw new Error(
1578
- `"${projectRelativeUrl}" service worker file missing in the build`,
1752
+ `"${serviceWorkerRelativeUrl}" service worker file missing in the build`,
1579
1753
  )
1580
1754
  }
1581
- const buildFileContent = rollupBuild[serviceWorkerBuildRelativeUrl].source
1582
- rollupBuild[serviceWorkerBuildRelativeUrl].source =
1583
- serviceWorkerFinalizer(buildFileContent, {
1755
+
1756
+ if (serviceWorkerFinalizer) {
1757
+ let code = buildFileContents[serviceWorkerBuildRelativeUrl]
1758
+ code = await serviceWorkerFinalizer(code, {
1584
1759
  serviceWorkerBuildRelativeUrl,
1585
- buildManifest,
1586
- rollupBuild,
1760
+ buildFileContents,
1587
1761
  lineBreakNormalization,
1588
1762
  })
1763
+ buildFileContents[serviceWorkerBuildRelativeUrl] = code
1764
+ }
1589
1765
  }),
1590
1766
  )
1591
1767
  }