@jsenv/core 24.6.4 → 25.0.0-alpha.2

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 +42 -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 +530 -365
  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 +10 -9
  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),
119
+ )
120
+ const classicWorkerUrls = classicWorkers.map((classicWorker) =>
121
+ resolveUrl(classicWorker, projectDirectoryUrl),
106
122
  )
107
- const serviceWorkerUrls = Object.keys(serviceWorkers).map((key) =>
108
- resolveUrl(key, projectDirectoryUrl),
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,33 @@ export const createRollupPlugins = async ({
163
182
  projectDirectoryUrl,
164
183
  )
165
184
 
166
- // map fileName (build relative urls without hash) to build relative url
185
+ // map build relative urls without hash (called "ressourceName") to real build relative urls
167
186
  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
- }
187
+
188
+ const ressourcesReferencedByJs = []
180
189
  const createImportMapForFilesUsedInJs = () => {
181
190
  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
- })
191
+ ressourcesReferencedByJs.sort(comparePathnames).forEach((ressourceName) => {
192
+ const buildRelativeUrl = buildManifest[ressourceName]
193
+ if (
194
+ ressourceName &&
195
+ buildRelativeUrl &&
196
+ ressourceName !== buildRelativeUrl
197
+ ) {
198
+ topLevelMappings[`./${ressourceName}`] = `./${buildRelativeUrl}`
199
+ }
200
+ })
190
201
  return {
191
202
  imports: topLevelMappings,
192
203
  }
193
204
  }
194
205
 
195
- let buildMappings = {}
196
206
  // an object where keys are build relative urls
197
207
  // and values rollup chunk or asset
198
208
  // we need this because we sometimes tell rollup
199
209
  // that a file.fileName is something while it's not really this
200
210
  // because of remapping
211
+ let buildMappings = {}
201
212
  let rollupBuild
202
213
 
203
214
  const EMPTY_CHUNK_URL = resolveUrl("__empty__", projectDirectoryUrl)
@@ -313,6 +324,7 @@ export const createRollupPlugins = async ({
313
324
  : resolveUrl(chunk.fileName, buildDirectoryUrl),
314
325
  code,
315
326
  map,
327
+ module: format === "esmodule",
316
328
  ...(format === "global" ? { toplevel: false } : { toplevel: true }),
317
329
  })
318
330
 
@@ -329,9 +341,9 @@ export const createRollupPlugins = async ({
329
341
  name: "jsenv",
330
342
 
331
343
  async buildStart() {
332
- logger.info(formatBuildStartLog({ entryPointMap }))
344
+ logger.info(formatBuildStartLog({ entryPoints }))
333
345
 
334
- const entryPointsPrepared = await prepareEntryPoints(entryPointMap, {
346
+ const entryPointsPrepared = await prepareEntryPoints(entryPoints, {
335
347
  logger,
336
348
  projectDirectoryUrl,
337
349
  buildDirectoryUrl,
@@ -360,7 +372,7 @@ export const createRollupPlugins = async ({
360
372
  if (typeof useImportMapToMaximizeCacheReuse === "undefined") {
361
373
  useImportMapToMaximizeCacheReuse =
362
374
  htmlEntryPointCount > 0 &&
363
- // node has no importmap concept, le'ts use the versionned url in that case
375
+ // node has no importmap concept, let's use the versionned url in that case
364
376
  !node
365
377
  }
366
378
 
@@ -442,9 +454,21 @@ export const createRollupPlugins = async ({
442
454
  )
443
455
  importMapUrl = htmlCompiledUrl
444
456
  fetchImportMap = () => {
445
- const importMapRaw = JSON.parse(importMapInfoFromHtml.text)
446
- const importMap = normalizeImportMap(importMapRaw, importMapUrl)
447
- return importMap
457
+ const importmapFileUrl = asProjectUrl(importMapUrl)
458
+ const jsenvImportmap = getDefaultImportmap(importmapFileUrl, {
459
+ projectDirectoryUrl,
460
+ compileDirectoryUrl,
461
+ })
462
+ const htmlImportmap = JSON.parse(importMapInfoFromHtml.text)
463
+ const importmap = composeTwoImportMaps(
464
+ jsenvImportmap,
465
+ htmlImportmap,
466
+ )
467
+ const importmapNormalized = normalizeImportMap(
468
+ importmap,
469
+ importMapUrl,
470
+ )
471
+ return importmapNormalized
448
472
  }
449
473
  }
450
474
  } else if (importMapFileRelativeUrl) {
@@ -459,7 +483,7 @@ export const createRollupPlugins = async ({
459
483
  )
460
484
  }
461
485
  } else {
462
- // there is no importmap, its' fine it's not mandatory to use one
486
+ // there is no importmap, it's fine, it's not mandatory
463
487
  fetchImportMap = () => {
464
488
  const firstEntryPoint = htmlEntryPoints[0] || entryPointsPrepared[0]
465
489
  const { entryProjectRelativeUrl } = firstEntryPoint
@@ -467,16 +491,19 @@ export const createRollupPlugins = async ({
467
491
  entryProjectRelativeUrl,
468
492
  compileDirectoryUrl,
469
493
  )
470
- const defaultImportMap = getDefaultImportMap({
471
- importMapFileUrl: entryCompileUrl,
494
+ const jsenvImportmap = getDefaultImportmap(entryCompileUrl, {
472
495
  projectDirectoryUrl,
473
- compileDirectoryRelativeUrl,
496
+ compileDirectoryUrl,
474
497
  })
475
498
  const entryCompileServerUrl = resolveUrl(
476
499
  entryProjectRelativeUrl,
477
500
  compileDirectoryServerUrl,
478
501
  )
479
- return normalizeImportMap(defaultImportMap, entryCompileServerUrl)
502
+ const importmapNormalized = normalizeImportMap(
503
+ jsenvImportmap,
504
+ entryCompileServerUrl,
505
+ )
506
+ return importmapNormalized
480
507
  }
481
508
  }
482
509
 
@@ -603,13 +630,27 @@ export const createRollupPlugins = async ({
603
630
  }
604
631
 
605
632
  const originalUrl = asOriginalUrl(projectUrl)
606
- if (isWorkerUrl(originalUrl)) {
633
+ if (workerUrls.includes(originalUrl)) {
607
634
  return {
608
635
  isWorker: true,
636
+ isJsModule: true,
609
637
  url: ressourceUrl,
610
638
  }
611
639
  }
612
- if (isServiceWorkerUrl(originalUrl)) {
640
+ if (serviceWorkerUrls.includes(originalUrl)) {
641
+ return {
642
+ isServiceWorker: true,
643
+ isJsModule: true,
644
+ url: ressourceUrl,
645
+ }
646
+ }
647
+ if (classicWorkerUrls.includes(originalUrl)) {
648
+ return {
649
+ isWorker: true,
650
+ url: ressourceUrl,
651
+ }
652
+ }
653
+ if (classicServiceWorkerUrls.includes(originalUrl)) {
613
654
  return {
614
655
  isServiceWorker: true,
615
656
  url: ressourceUrl,
@@ -618,34 +659,79 @@ export const createRollupPlugins = async ({
618
659
 
619
660
  return ressourceUrl
620
661
  },
621
- emitChunk,
622
- emitAsset,
623
- setAssetSource,
624
662
  onJsModule: ({ ressource, jsModuleUrl, jsModuleIsInline }) => {
625
- if (jsModuleIsInline) {
626
- inlineModuleScripts[jsModuleUrl] = ressource
663
+ // we want to emit chunk only when ressource is referenced by something else than rollup
664
+ if (
665
+ jsConcatenation &&
666
+ ressource.references.every((ref) => ref.fromRollup)
667
+ ) {
668
+ return null
627
669
  }
628
670
 
629
- urlImporterMap[jsModuleUrl] = {
630
- url: resolveUrl(
671
+ if (ressource.isEntryPoint) {
672
+ } else {
673
+ const importerUrl = resolveUrl(
631
674
  entryPointsPrepared[0].entryProjectRelativeUrl,
632
675
  compileDirectoryServerUrl,
633
- ),
634
- line: undefined,
635
- column: undefined,
676
+ )
677
+ urlImporterMap[jsModuleUrl] = {
678
+ url: importerUrl,
679
+ line: undefined,
680
+ column: undefined,
681
+ }
682
+ jsModulesFromEntry[asRollupUrl(jsModuleUrl)] = true
683
+ if (jsModuleIsInline) {
684
+ inlineModuleScripts[jsModuleUrl] = ressource
685
+ urlCustomLoaders[jsModuleUrl] = async () => {
686
+ const transformResult = await transformJs({
687
+ code: String(
688
+ inlineModuleScripts[jsModuleUrl].bufferBeforeBuild,
689
+ ),
690
+ url: asOriginalUrl(jsModuleUrl), // transformJs expect a file:// url
691
+ projectDirectoryUrl,
692
+ babelPluginMap,
693
+ // moduleOutFormat: format // we are compiling for rollup output must be "esmodule"
694
+ // we compile for rollup, let top level await untouched
695
+ // it will be converted, if needed, during "renderChunk" hook
696
+ topLevelAwait: "ignore",
697
+ })
698
+ let code = transformResult.code
699
+ let map = transformResult.map
700
+ return {
701
+ code,
702
+ map,
703
+ }
704
+ }
705
+ }
636
706
  }
637
- jsModulesFromEntry[asRollupUrl(jsModuleUrl)] = true
638
- const name = urlToBasename(jsModuleUrl)
707
+
708
+ const fileName = ressource.relativeUrl
639
709
  const rollupReferenceId = emitChunk({
640
- id: asRollupUrl(jsModuleUrl),
641
- name,
710
+ id: jsModuleUrl,
711
+ name: urlToBasename(jsModuleUrl),
642
712
  })
643
713
  return {
644
- name,
645
714
  rollupReferenceId,
715
+ fileName,
646
716
  }
647
717
  },
648
- lineBreakNormalization,
718
+ onAsset: ({ ressource }) => {
719
+ const fileName = ressource.relativeUrl
720
+ const rollupReferenceId = emitAsset({
721
+ fileName,
722
+ })
723
+ return {
724
+ rollupReferenceId,
725
+ fileName,
726
+ }
727
+ },
728
+ onAssetSourceUpdated: ({ ressource }) => {
729
+ setAssetSource(
730
+ ressource.rollupReferenceId,
731
+ ressource.bufferAfterBuild,
732
+ )
733
+ },
734
+ urlVersioner,
649
735
  },
650
736
  )
651
737
 
@@ -654,16 +740,15 @@ export const createRollupPlugins = async ({
654
740
  async ({
655
741
  entryContentType,
656
742
  entryProjectRelativeUrl,
657
- entryBuildRelativeUrl,
658
743
  entryBuffer,
659
744
  }) => {
660
745
  if (entryContentType === "application/javascript") {
661
- emitChunk({
662
- id: ensureRelativeUrlNotation(entryProjectRelativeUrl),
663
- name: urlToBasename(`file:///${entryBuildRelativeUrl}`),
664
- ...(urlVersionningForEntryPoints
665
- ? {}
666
- : { fileName: entryBuildRelativeUrl }),
746
+ await ressourceBuilder.createReferenceForEntryPoint({
747
+ entryContentType,
748
+ entryUrl: resolveUrl(
749
+ entryProjectRelativeUrl,
750
+ compileDirectoryServerUrl,
751
+ ),
667
752
  })
668
753
  return
669
754
  }
@@ -684,8 +769,6 @@ export const createRollupPlugins = async ({
684
769
  entryContentType,
685
770
  entryUrl,
686
771
  entryBuffer,
687
- entryBuildRelativeUrl,
688
- urlVersionningForEntryPoints,
689
772
  })
690
773
  },
691
774
  ),
@@ -699,15 +782,20 @@ export const createRollupPlugins = async ({
699
782
  }
700
783
  },
701
784
 
702
- async resolveId(specifier, importer, { custom }) {
785
+ async resolveId(specifier, importer, { custom = {} } = {}) {
786
+ if (specifier === EMPTY_CHUNK_URL) {
787
+ return specifier
788
+ }
789
+
790
+ let importerUrl
703
791
  if (importer === undefined) {
704
792
  if (specifier.endsWith(".html")) {
705
- importer = compileServerOrigin
793
+ importerUrl = compileServerOrigin
706
794
  } else {
707
- importer = compileDirectoryServerUrl
795
+ importerUrl = compileDirectoryServerUrl
708
796
  }
709
797
  } else {
710
- importer = asServerUrl(importer)
798
+ importerUrl = asServerUrl(importer)
711
799
  }
712
800
 
713
801
  const { importAssertionInfo } = custom
@@ -732,25 +820,23 @@ export const createRollupPlugins = async ({
732
820
  }
733
821
 
734
822
  if (inlineModuleScripts.hasOwnProperty(specifier)) {
735
- return specifier
823
+ return asRollupUrl(specifier)
736
824
  }
737
825
 
738
- if (isFileSystemPath(importer)) {
739
- importer = fileSystemPathToUrl(importer)
740
- }
741
-
742
- const importUrl = await importResolver.resolveImport(specifier, importer)
743
-
826
+ const importUrl = await importResolver.resolveImport(
827
+ specifier,
828
+ importerUrl,
829
+ )
744
830
  const existingImporter = urlImporterMap[importUrl]
745
831
  if (!existingImporter) {
746
832
  urlImporterMap[importUrl] = importAssertionInfo
747
833
  ? {
748
- url: importer,
834
+ url: importerUrl,
749
835
  column: importAssertionInfo.column,
750
836
  line: importAssertionInfo.line,
751
837
  }
752
838
  : {
753
- url: importer,
839
+ url: importerUrl,
754
840
  // rollup do not expose a way to know line and column for the static or dynamic import
755
841
  // referencing that file
756
842
  column: undefined,
@@ -782,34 +868,29 @@ export const createRollupPlugins = async ({
782
868
  },
783
869
 
784
870
  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
-
871
+ ressourcesReferencedByJs.push(fileName)
872
+ const getBuildRelativeUrl = () => {
873
+ const ressource = ressourceBuilder.findRessource((ressource) => {
874
+ return ressource.rollupReferenceId === referenceId
875
+ })
876
+ ressource.fileName = fileName
877
+ const buildRelativeUrl = ressource.buildRelativeUrl
878
+ return buildRelativeUrl
879
+ }
792
880
  if (format === "esmodule") {
793
881
  if (!node && useImportMapToMaximizeCacheReuse && urlVersioning) {
794
- const buildRelativeUrlWithoutVersion =
795
- buildRelativeUrlToFileName(buildRelativeUrl)
796
- return `window.__resolveImportUrl__("./${buildRelativeUrlWithoutVersion}", import.meta.url)`
882
+ return `window.__resolveImportUrl__("./${fileName}", import.meta.url)`
797
883
  }
798
- return `new URL("${buildRelativeUrl}", import.meta.url)`
884
+ return `new URL("${getBuildRelativeUrl()}", import.meta.url)`
799
885
  }
800
886
  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))`
887
+ return `new URL(System.resolve("./${fileName}", module.meta.url))`
807
888
  }
808
889
  if (format === "global") {
809
- return `new URL("${buildRelativeUrl}", document.currentScript && document.currentScript.src || document.baseURI)`
890
+ return `new URL("${getBuildRelativeUrl()}", document.currentScript && document.currentScript.src || document.baseURI)`
810
891
  }
811
892
  if (format === "commonjs") {
812
- return `new URL("${buildRelativeUrl}", "file:///" + __filename.replace(/\\/g, "/"))`
893
+ return `new URL("${getBuildRelativeUrl()}", "file:///" + __filename.replace(/\\/g, "/"))`
813
894
  }
814
895
  return null
815
896
  },
@@ -830,11 +911,10 @@ export const createRollupPlugins = async ({
830
911
  return urlLoader.loadUrl(rollupUrl, {
831
912
  signal,
832
913
  logger,
833
- ressourceBuilder,
834
914
  })
835
915
  })
836
916
 
837
- url = loadResult.url
917
+ if (loadResult.url) url = loadResult.url
838
918
  const code = loadResult.code
839
919
  const map = loadResult.map
840
920
 
@@ -846,6 +926,7 @@ export const createRollupPlugins = async ({
846
926
  originalUrl,
847
927
  jsenvHelpersDirectoryInfo.url,
848
928
  )
929
+ // const isEntryPoint = entryPointUrls[originalUrl]
849
930
 
850
931
  const importer = urlImporterMap[url]
851
932
  // Inform ressource builder that this js module exists
@@ -855,18 +936,12 @@ export const createRollupPlugins = async ({
855
936
  // For import assertions, the imported ressource (css,json,...)
856
937
  // is arelady converted to a js module
857
938
  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
939
  contentTypeExpected: "application/javascript",
864
940
  referenceLabel: "static or dynamic import",
865
941
  referenceUrl: importer.url,
866
942
  referenceColumn: importer.column,
867
943
  referenceLine: importer.line,
868
944
  ressourceSpecifier: url,
869
-
870
945
  isJsenvHelperFile,
871
946
  contentType: "application/javascript",
872
947
  bufferBeforeBuild: Buffer.from(code),
@@ -896,18 +971,30 @@ export const createRollupPlugins = async ({
896
971
  onReferenceWithImportMetaUrlPattern: async ({ importNode }) => {
897
972
  const specifier = importNode.arguments[0].value
898
973
  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
- })
974
+
975
+ const { id } = normalizeRollupResolveReturnValue(
976
+ await this.resolve(specifier, url),
977
+ )
978
+ const ressourceUrl = asServerUrl(id)
979
+ const originalUrl = asOriginalUrl(ressourceUrl)
980
+ const isJsModule = Boolean(
981
+ workerUrls[originalUrl] || serviceWorkerUrls[originalUrl],
982
+ )
983
+ const reference = ressourceBuilder.createReferenceFoundInJsModule({
984
+ referenceLabel: "URL + import.meta.url",
985
+ jsUrl: url,
986
+ jsLine: line,
987
+ jsColumn: column,
988
+ ressourceSpecifier: ressourceUrl,
989
+ isJsModule,
990
+ })
907
991
  if (!reference) {
908
992
  return
909
993
  }
910
- markBuildRelativeUrlAsUsedByJs(reference.ressource.buildRelativeUrl)
994
+ if (!reference.ressource.isJsModule) {
995
+ // so that ressource.buildRelativeUrl is known during "resolveFileUrl" hook`
996
+ await reference.ressource.getReadyPromise()
997
+ }
911
998
  mutations.push((magicString) => {
912
999
  magicString.overwrite(
913
1000
  importNode.start,
@@ -924,7 +1011,6 @@ export const createRollupPlugins = async ({
924
1011
  const { source } = importNode
925
1012
  const importSpecifier = source.value
926
1013
  const { line, column } = importNode.loc.start
927
-
928
1014
  // "type" is dynamic on dynamic import such as
929
1015
  // import("./data.json", {
930
1016
  // assert: {
@@ -952,9 +1038,7 @@ export const createRollupPlugins = async ({
952
1038
  type: typePropertyValue.value,
953
1039
  }
954
1040
  }
955
-
956
1041
  const { type } = assertions
957
-
958
1042
  // "specifier" is dynamic on dynamic import such as
959
1043
  // import(true ? "./a.json" : "b.json", {
960
1044
  // assert: {
@@ -978,9 +1062,7 @@ export const createRollupPlugins = async ({
978
1062
  ),
979
1063
  )
980
1064
  }
981
-
982
1065
  // There is no strategy for css import assertion on Node.js
983
- // and that's normal
984
1066
  if (type === "css" && node) {
985
1067
  throw new Error(
986
1068
  createDetailedMessage(
@@ -1006,29 +1088,31 @@ export const createRollupPlugins = async ({
1006
1088
  },
1007
1089
  }),
1008
1090
  )
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
-
1091
+ // remove import
1092
+ let ressourceUrl = asServerUrl(id)
1093
+ // lod the asset without ?import_type in it
1094
+ ressourceUrl = ressourceUrl.replace(`?import_type=${type}`, "")
1095
+ const fileReference = ressourceBuilder.createReferenceFoundInJsModule(
1096
+ {
1097
+ referenceLabel: `${type} import assertion`,
1098
+ // If all references to a ressource are only import assertions
1099
+ // the file referenced do not need to be written on filesystem
1100
+ // as it was converted to a js file
1101
+ // We pass "isImportAssertion: true" for this purpose
1102
+ isImportAssertion: true,
1103
+ jsUrl: url,
1104
+ jsLine: line,
1105
+ jsColumn: column,
1106
+ ressourceSpecifier: ressourceUrl,
1107
+ contentTypeExpected:
1108
+ type === "css" ? "text/css" : "application/json",
1109
+ },
1110
+ )
1111
+ // reference can be null for cross origin urls
1112
+ if (!fileReference) {
1113
+ return
1114
+ }
1115
+ if (external && !importAssertionSupportedByRuntime) {
1032
1116
  throw new Error(
1033
1117
  createDetailedMessage(
1034
1118
  `import assertion ressource cannot be external when runtime do not support import assertions`,
@@ -1041,16 +1125,64 @@ export const createRollupPlugins = async ({
1041
1125
  )
1042
1126
  }
1043
1127
 
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(
1128
+ // await fileReference.ressource.getReadyPromise()
1129
+ // once the file is ready, we know its buildRelativeUrl
1130
+ // we can update either to the fileName or buildRelativeUrl
1131
+ // should be use the rollup reference id?
1132
+ const ressourceUrlAsJsModule = resolveUrl(
1133
+ `${urlToBasename(
1134
+ ressourceUrl,
1135
+ )}${outputExtension}?import_type=${type}`,
1049
1136
  ressourceUrl,
1050
- {
1051
- import_type: type,
1052
- },
1053
1137
  )
1138
+ const jsUrl = url
1139
+ urlCustomLoaders[ressourceUrlAsJsModule] = async () => {
1140
+ let code
1141
+ let map
1142
+
1143
+ if (type === "json") {
1144
+ await fileReference.ressource.getReadyPromise()
1145
+ code = String(fileReference.ressource.bufferAfterBuild)
1146
+ const jsModuleConversionResult =
1147
+ await convertJsonTextToJavascriptModule({
1148
+ code,
1149
+ map,
1150
+ })
1151
+ code = jsModuleConversionResult.code
1152
+ map = jsModuleConversionResult.map
1153
+ } else if (type === "css") {
1154
+ await fileReference.ressource.getReadyPromise()
1155
+ const cssBuildUrl = resolveUrl(
1156
+ fileReference.ressource.buildRelativeUrl,
1157
+ buildDirectoryUrl,
1158
+ )
1159
+ const jsBuildUrl = resolveUrl(
1160
+ urlToFilename(jsUrl),
1161
+ buildDirectoryUrl,
1162
+ )
1163
+ code = String(fileReference.ressource.bufferAfterBuild)
1164
+ const sourcemapReference =
1165
+ fileReference.ressource.dependencies.find((dependency) => {
1166
+ return dependency.ressource.isSourcemap
1167
+ })
1168
+ if (sourcemapReference) {
1169
+ // because css is ready, it's sourcemap is also ready
1170
+ // we can read directly sourcemapReference.ressource.bufferAfterBuild
1171
+ map = JSON.parse(sourcemapReference.ressource.bufferAfterBuild)
1172
+ }
1173
+ const jsModuleConversionResult =
1174
+ await convertCssTextToJavascriptModule({
1175
+ cssUrl: cssBuildUrl,
1176
+ jsUrl: jsBuildUrl,
1177
+ code,
1178
+ map,
1179
+ })
1180
+ code = jsModuleConversionResult.code
1181
+ map = jsModuleConversionResult.map
1182
+ }
1183
+
1184
+ return { code, map }
1185
+ }
1054
1186
 
1055
1187
  mutations.push((magicString) => {
1056
1188
  magicString.overwrite(
@@ -1078,9 +1210,6 @@ export const createRollupPlugins = async ({
1078
1210
 
1079
1211
  // resolveImportMeta: () => {}
1080
1212
  outputOptions: (outputOptions) => {
1081
- const extension = extname(entryPointMap[Object.keys(entryPointMap)[0]])
1082
- const outputExtension = extension === ".html" ? ".js" : extension
1083
-
1084
1213
  outputOptions.paths = (id) => {
1085
1214
  const mapping = importPaths[id]
1086
1215
  if (mapping) {
@@ -1093,19 +1222,31 @@ export const createRollupPlugins = async ({
1093
1222
  }
1094
1223
  return id
1095
1224
  }
1225
+ // outputOptions.assetFileNames = () => {
1226
+ // return `assets/[name]_[hash][extname]`
1227
+ // }
1096
1228
  outputOptions.entryFileNames = () => {
1097
- if (urlVersionningForEntryPoints) {
1098
- return `[name]-[hash]${outputExtension}`
1229
+ if (useImportMapToMaximizeCacheReuse) {
1230
+ return `[name]${outputExtension}`
1099
1231
  }
1100
- return `[name]${outputExtension}`
1232
+ return entryPoints
1101
1233
  }
1102
- outputOptions.chunkFileNames = () => {
1234
+ outputOptions.chunkFileNames = (chunkInfo) => {
1103
1235
  // const originalUrl = asOriginalUrl(chunkInfo.facadeModuleId)
1104
1236
  // const basename = urlToBasename(originalUrl)
1105
1237
  if (useImportMapToMaximizeCacheReuse) {
1106
1238
  return `[name]${outputExtension}`
1107
1239
  }
1108
- return `[name]-[hash]${outputExtension}`
1240
+ if (chunkInfo.isEntry) {
1241
+ const originalUrl = asOriginalUrl(chunkInfo.facadeModuleId)
1242
+ const entryPointPattern = entryPointUrls[originalUrl]
1243
+ if (entryPointPattern) {
1244
+ return entryPointPattern
1245
+ }
1246
+ }
1247
+ return urlVersioning
1248
+ ? `[name]_[hash]${outputExtension}`
1249
+ : `[name]${outputExtension}`
1109
1250
  }
1110
1251
 
1111
1252
  // rollup does not expects to have http dependency in the mix: fix them
@@ -1137,190 +1278,204 @@ export const createRollupPlugins = async ({
1137
1278
  return outputOptions
1138
1279
  },
1139
1280
 
1281
+ async renderChunk(code, chunk) {
1282
+ const { facadeModuleId } = chunk
1283
+ if (!facadeModuleId) {
1284
+ // happens for inline module scripts for instance
1285
+ return null
1286
+ }
1287
+
1288
+ const url = asOriginalUrl(facadeModuleId)
1289
+ if (workerUrls.includes(url) || serviceWorkerUrls.includes(url)) {
1290
+ const magicString = new MagicString(code)
1291
+ const systemjsCode = await readFile(
1292
+ new URL("../runtime/s.js", import.meta.url),
1293
+ )
1294
+ magicString.prepend(systemjsCode)
1295
+ code = magicString.toString()
1296
+ const map = magicString.generateMap({ hires: true })
1297
+ return {
1298
+ code,
1299
+ map,
1300
+ }
1301
+ }
1302
+
1303
+ return null
1304
+ },
1305
+
1140
1306
  async generateBundle(outputOptions, rollupResult) {
1141
- const jsChunks = {}
1307
+ // it's important to do this to emit late asset
1308
+ rollupEmitFile = (...args) => this.emitFile(...args)
1309
+ rollupSetAssetSource = (...args) => this.setAssetSource(...args)
1142
1310
  // To keep in mind: rollupResult object can be mutated by late asset emission
1143
1311
  // however late chunk (js module) emission is not possible
1144
1312
  // as rollup rightfully prevent late js emission
1145
1313
  Object.keys(rollupResult).forEach((fileName) => {
1146
- const file = rollupResult[fileName]
1147
-
1314
+ const rollupFileInfo = rollupResult[fileName]
1148
1315
  // 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
1316
+ if (rollupFileInfo.type === "chunk") {
1317
+ const { facadeModuleId } = rollupFileInfo
1155
1318
  if (facadeModuleId === EMPTY_CHUNK_URL) {
1319
+ delete rollupResult[fileName]
1156
1320
  return
1157
1321
  }
1158
- const fileCopy = { ...file }
1159
1322
  if (facadeModuleId) {
1160
- fileCopy.url = asServerUrl(facadeModuleId)
1323
+ rollupFileInfo.url = asServerUrl(facadeModuleId)
1161
1324
  } else {
1162
- const sourcePath = file.map.sources[file.map.sources.length - 1]
1163
- const fileBuildUrl = resolveUrl(file.fileName, buildDirectoryUrl)
1325
+ const sourcePath =
1326
+ rollupFileInfo.map.sources[rollupFileInfo.map.sources.length - 1]
1327
+ const fileBuildUrl = resolveUrl(fileName, buildDirectoryUrl)
1164
1328
  const originalProjectUrl = resolveUrl(sourcePath, fileBuildUrl)
1165
- fileCopy.url = asCompiledServerUrl(originalProjectUrl, {
1329
+ rollupFileInfo.url = asCompiledServerUrl(originalProjectUrl, {
1166
1330
  projectDirectoryUrl,
1167
1331
  compileServerOrigin,
1168
1332
  compileDirectoryRelativeUrl,
1169
1333
  })
1170
1334
  }
1171
- jsChunks[fileName] = fileCopy
1172
- }
1173
- })
1174
1335
 
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
-
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
- },
1336
+ if (
1337
+ rollupFileInfo.url in inlineModuleScripts &&
1338
+ format === "systemjs"
1339
+ ) {
1340
+ const code = rollupFileInfo.code
1341
+ const systemRegisterIndex = code.indexOf("System.register([")
1342
+ const magicString = new MagicString(code)
1343
+ magicString.overwrite(
1344
+ systemRegisterIndex,
1345
+ systemRegisterIndex + "System.register([".length,
1346
+ `System.register("${fileName}", [`,
1206
1347
  )
1207
- } else {
1208
- buildRelativeUrl = fileName
1348
+ rollupFileInfo.code = magicString.toString()
1209
1349
  }
1210
- } else {
1211
- buildRelativeUrl = fileName
1212
- fileName = rollupFileNameWithoutHash(fileName)
1213
- }
1214
1350
 
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)
1351
+ const jsRessource = ressourceBuilder.findRessource((ressource) => {
1352
+ return ressource.url === rollupFileInfo.url
1353
+ })
1354
+ if (
1355
+ isReferencedByJs({
1356
+ rollupFileInfo,
1357
+ jsConcatenation,
1358
+ jsRessource,
1359
+ })
1360
+ ) {
1361
+ ressourcesReferencedByJs.push(fileName)
1226
1362
  }
1227
- buildInlineFileContents[buildRelativeUrl] = file.code
1228
- } else {
1229
- markBuildRelativeUrlAsUsedByJs(buildRelativeUrl)
1230
- buildMappings[originalProjectRelativeUrl] = buildRelativeUrl
1231
1363
  }
1232
-
1233
- jsModuleBuild[buildRelativeUrl] = file
1234
1364
  })
1235
1365
 
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
1366
  // malheureusement rollup ne permet pas de savoir lorsqu'un chunk
1241
1367
  // a fini d'etre résolu (parsing des imports statiques et dynamiques recursivement)
1242
1368
  // donc lorsque le build se termine on va indiquer
1243
1369
  // aux assets faisant référence a ces chunk js qu'ils sont terminés
1244
1370
  // et donc les assets peuvent connaitre le nom du chunk
1245
1371
  // et mettre a jour leur dépendance vers ce fichier js
1246
- ressourceBuilder.rollupBuildEnd({ jsModuleBuild, buildManifest })
1372
+ const { jsRessources } = ressourceBuilder.rollupBuildEnd({
1373
+ rollupResult,
1374
+ useImportMapToMaximizeCacheReuse,
1375
+ })
1376
+ Object.keys(jsRessources).forEach((ressourceUrl) => {
1377
+ const jsRessource = jsRessources[ressourceUrl]
1378
+ if (jsRessource.isInline) {
1379
+ buildInlineFileContents[jsRessource.buildRelativeUrl] =
1380
+ jsRessource.bufferAfterBuild
1381
+ // if (format === "systemjs") {
1382
+ // ressourcesReferencedByJs.push(jsRessource.fileName)
1383
+ // }
1384
+ } else {
1385
+ const originalProjectUrl = asOriginalUrl(ressourceUrl)
1386
+ const originalProjectRelativeUrl = urlToRelativeUrl(
1387
+ originalProjectUrl,
1388
+ projectDirectoryUrl,
1389
+ )
1390
+ buildMappings[originalProjectRelativeUrl] =
1391
+ jsRessource.buildRelativeUrl
1392
+ }
1393
+ buildManifest[jsRessource.fileName] = jsRessource.buildRelativeUrl
1394
+ })
1395
+ // wait for asset build relative urls
1396
+ // to ensure the importmap will contain remappings for them
1397
+ // (not sure this is required anymore)
1398
+ await Promise.all(
1399
+ ressourcesReferencedByJs.map(async (ressourceName) => {
1400
+ const ressource = ressourceBuilder.findRessource((ressource) => {
1401
+ return ressource.relativeUrl === ressourceName
1402
+ })
1403
+ if (ressource && !ressource.isJsModule) {
1404
+ await ressource.getReadyPromise()
1405
+ buildManifest[ressourceName] = ressource.buildRelativeUrl
1406
+ }
1407
+ }),
1408
+ )
1247
1409
  // wait html files to be emitted
1248
1410
  await ressourceBuilder.getAllEntryPointsEmittedPromise()
1249
1411
  onBundleEnd()
1250
1412
 
1413
+ const jsModuleBuild = {}
1251
1414
  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
- }
1415
+ Object.keys(rollupResult).forEach((fileName) => {
1416
+ const rollupFileInfo = rollupResult[fileName]
1282
1417
 
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
1418
+ if (rollupFileInfo.type === "chunk") {
1419
+ const jsRessource = ressourceBuilder.findRessource((ressource) => {
1420
+ return ressource.url === rollupFileInfo.url
1290
1421
  })
1291
- if (isReferencedOnlyByImportAssertions) {
1422
+ jsModuleBuild[jsRessource.buildRelativeUrl] = rollupFileInfo
1292
1423
  return
1293
1424
  }
1294
1425
 
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,
1426
+ if (rollupFileInfo.type === "asset") {
1427
+ const assetRessource = ressourceBuilder.findRessource(
1428
+ (ressource) =>
1429
+ // happens for import.meta.url pattern
1430
+ ressource.fileName === fileName ||
1431
+ // happens for sourcemap
1432
+ ressource.relativeUrl === fileName,
1304
1433
  )
1434
+ // ignore potential useless assets which happens when:
1435
+ // - sourcemap re-emitted
1436
+ // - importmap re-emitted to have buildRelativeUrlMap
1437
+ if (assetRessource.shouldBeIgnored) {
1438
+ return
1439
+ }
1440
+ // Ignore file only referenced by import assertions
1441
+ // - if file is referenced by import assertion and html or import meta url
1442
+ // then source file is duplicated. If concatenation is disabled
1443
+ // and import assertions are supported, the file is still converted to js module
1444
+ const isReferencedOnlyByImportAssertions =
1445
+ assetRessource.references.every((reference) => {
1446
+ return reference.isImportAssertion
1447
+ })
1448
+ if (isReferencedOnlyByImportAssertions) {
1449
+ return
1450
+ }
1451
+ const buildRelativeUrl = assetRessource.buildRelativeUrl
1452
+ if (assetRessource.isInline) {
1453
+ buildInlineFileContents[buildRelativeUrl] = rollupFileInfo.source
1454
+ return
1455
+ }
1305
1456
  // 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
1457
+ rollupFileInfo.source = assetRessource.bufferAfterBuild
1458
+ assetBuild[buildRelativeUrl] = rollupFileInfo
1459
+ buildManifest[assetRessource.fileName] = buildRelativeUrl
1460
+ if (assetRessource.bufferBeforeBuild) {
1461
+ const originalProjectUrl = asOriginalUrl(assetRessource.url)
1462
+ const originalProjectRelativeUrl = urlToRelativeUrl(
1463
+ originalProjectUrl,
1464
+ projectDirectoryUrl,
1465
+ )
1466
+ buildMappings[originalProjectRelativeUrl] = buildRelativeUrl
1467
+ }
1468
+ return
1311
1469
  }
1312
1470
  })
1313
-
1314
1471
  rollupBuild = {
1315
1472
  ...jsModuleBuild,
1316
1473
  ...assetBuild,
1317
1474
  }
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
1475
+ rollupBuild = sortObjectByPathnames(rollupBuild)
1476
+ // fill "buildFileContents", "buildInlineFilesContents"
1477
+ // and update "buildManifest" and "buildMappings" in case some ressource where inlined
1478
+ // by ressourceBuilder.rollupBuildEnd
1324
1479
  Object.keys(rollupBuild).forEach((buildRelativeUrl) => {
1325
1480
  const rollupFileInfo = rollupBuild[buildRelativeUrl]
1326
1481
  const ressource = ressourceBuilder.findRessource((ressource) => {
@@ -1332,46 +1487,46 @@ export const createRollupPlugins = async ({
1332
1487
  }
1333
1488
  return false
1334
1489
  })
1335
- if (ressource && ressource.isInline) {
1336
- const fileName = buildRelativeUrlToFileName(buildRelativeUrl)
1337
- if (fileName) {
1338
- delete buildManifest[fileName]
1490
+ if (ressource.isInline) {
1491
+ delete buildManifest[ressource.fileName]
1492
+ if (ressource.isJsModule) {
1493
+ delete jsModuleBuild[buildRelativeUrl]
1494
+ } else {
1495
+ delete assetBuild[buildRelativeUrl]
1339
1496
  }
1340
1497
  const originalProjectUrl = asOriginalUrl(ressource.url)
1341
- delete buildMappings[
1342
- urlToRelativeUrl(originalProjectUrl, projectDirectoryUrl)
1343
- ]
1344
- buildInlineFileContents[buildRelativeUrl] = rollupFileInfo.code
1345
- delete rollupBuild[buildRelativeUrl]
1498
+ const originalRelativeUrl = urlToRelativeUrl(
1499
+ originalProjectUrl,
1500
+ projectDirectoryUrl,
1501
+ )
1502
+ delete buildMappings[originalRelativeUrl]
1503
+ buildInlineFileContents[ressource.buildRelativeUrl] =
1504
+ ressource.bufferAfterBuild
1505
+ } else {
1506
+ buildFileContents[ressource.buildRelativeUrl] =
1507
+ ressource.bufferAfterBuild
1346
1508
  }
1347
1509
  })
1348
1510
 
1349
- await finalizeServiceWorkers({
1350
- serviceWorkers,
1351
- serviceWorkerFinalizer,
1511
+ await visitServiceWorkers({
1352
1512
  projectDirectoryUrl,
1353
- buildDirectoryUrl,
1354
- rollupBuild,
1513
+ serviceWorkerUrls,
1514
+ classicServiceWorkerUrls,
1515
+ serviceWorkerFinalizer,
1355
1516
  buildMappings,
1356
1517
  buildManifest,
1518
+ buildFileContents,
1357
1519
  lineBreakNormalization,
1358
- minify,
1359
1520
  })
1360
1521
 
1361
- rollupBuild = sortObjectByPathnames(rollupBuild)
1362
1522
  buildManifest = sortObjectByPathnames(buildManifest)
1363
1523
  buildMappings = sortObjectByPathnames(buildMappings)
1364
- Object.keys(rollupBuild).forEach((buildRelativeUrl) => {
1365
- const { type, source, code } = rollupBuild[buildRelativeUrl]
1366
- buildFileContents[buildRelativeUrl] = type === "asset" ? source : code
1367
- })
1368
1524
  const buildDuration = Date.now() - buildStartMs
1369
1525
  buildStats = createBuildStats({
1370
1526
  buildFileContents,
1371
1527
  ressourceBuilder,
1372
1528
  buildDuration,
1373
1529
  })
1374
-
1375
1530
  logger.info(
1376
1531
  formatBuildDoneInfo({
1377
1532
  buildStats,
@@ -1400,7 +1555,7 @@ export const createRollupPlugins = async ({
1400
1555
  return {
1401
1556
  rollupPlugins,
1402
1557
  getLastErrorMessage: () => lastErrorMessage,
1403
- getResult: () => {
1558
+ getResult: async () => {
1404
1559
  return {
1405
1560
  rollupBuild,
1406
1561
  urlResponseBodyMap: urlLoader.getUrlResponseBodyMap(),
@@ -1419,7 +1574,7 @@ export const createRollupPlugins = async ({
1419
1574
  }
1420
1575
 
1421
1576
  const prepareEntryPoints = async (
1422
- entryPointMap,
1577
+ entryPoints,
1423
1578
  {
1424
1579
  logger,
1425
1580
  projectDirectoryUrl,
@@ -1428,7 +1583,7 @@ const prepareEntryPoints = async (
1428
1583
  urlFetcher,
1429
1584
  },
1430
1585
  ) => {
1431
- const entryFileRelativeUrls = Object.keys(entryPointMap)
1586
+ const entryFileRelativeUrls = Object.keys(entryPoints)
1432
1587
  const entryPointsPrepared = []
1433
1588
  await entryFileRelativeUrls.reduce(async (previous, entryFileRelativeUrl) => {
1434
1589
  await previous
@@ -1438,10 +1593,9 @@ const prepareEntryPoints = async (
1438
1593
  projectDirectoryUrl,
1439
1594
  )
1440
1595
  const entryBuildUrl = resolveUrl(
1441
- entryPointMap[entryFileRelativeUrl],
1596
+ entryPoints[entryFileRelativeUrl],
1442
1597
  buildDirectoryUrl,
1443
1598
  )
1444
-
1445
1599
  const entryProjectRelativeUrl = urlToRelativeUrl(
1446
1600
  entryProjectUrl,
1447
1601
  projectDirectoryUrl,
@@ -1450,20 +1604,16 @@ const prepareEntryPoints = async (
1450
1604
  entryBuildUrl,
1451
1605
  buildDirectoryUrl,
1452
1606
  )
1453
-
1454
1607
  logger.debug(`${UNICODE.INFO} load entry point ${entryProjectRelativeUrl}`)
1455
-
1456
1608
  const entryServerUrl = resolveUrl(
1457
1609
  entryProjectRelativeUrl,
1458
1610
  compileServerOrigin,
1459
1611
  )
1460
-
1461
1612
  const entryResponse = await urlFetcher.fetchUrl(entryServerUrl, {
1462
- urlTrace: `entryPointMap`,
1613
+ urlTrace: `entryPoints`,
1463
1614
  })
1464
1615
  const entryContentType = entryResponse.headers["content-type"]
1465
1616
  const isHtml = entryContentType === "text/html"
1466
-
1467
1617
  entryPointsPrepared.push({
1468
1618
  entryContentType:
1469
1619
  entryContentType === "text/javascript"
@@ -1511,20 +1661,6 @@ const normalizeRollupResolveReturnValue = (resolveReturnValue) => {
1511
1661
  return resolveReturnValue
1512
1662
  }
1513
1663
 
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
1664
  const externalImportUrlPatternsToExternalUrlPredicate = (
1529
1665
  externalImportUrlPatterns,
1530
1666
  projectDirectoryUrl,
@@ -1560,32 +1696,61 @@ const acceptsJsonContentType = ({ node, format }) => {
1560
1696
  return false
1561
1697
  }
1562
1698
 
1563
- const finalizeServiceWorkers = async ({
1564
- serviceWorkers,
1699
+ const isReferencedByJs = ({ rollupFileInfo, jsConcatenation, jsRessource }) => {
1700
+ if (rollupFileInfo.isDynamicEntry) {
1701
+ return true
1702
+ }
1703
+ if (!jsConcatenation && rollupFileInfo.isEntry) {
1704
+ return true
1705
+ }
1706
+ if (
1707
+ jsRessource &&
1708
+ jsRessource.references.some((ref) => ref.isRessourceHint)
1709
+ ) {
1710
+ return true
1711
+ }
1712
+ return false
1713
+ }
1714
+
1715
+ const visitServiceWorkers = async ({
1716
+ projectDirectoryUrl,
1717
+ serviceWorkerUrls,
1718
+ classicServiceWorkerUrls,
1565
1719
  serviceWorkerFinalizer,
1566
1720
  buildMappings,
1567
1721
  buildManifest,
1568
- rollupBuild,
1722
+ buildFileContents,
1569
1723
  lineBreakNormalization,
1570
1724
  }) => {
1725
+ const allServiceWorkerUrls = [
1726
+ ...serviceWorkerUrls,
1727
+ ...classicServiceWorkerUrls,
1728
+ ]
1729
+
1571
1730
  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]
1731
+ allServiceWorkerUrls.map(async (serviceWorkerUrl) => {
1732
+ const serviceWorkerRelativeUrl = urlToRelativeUrl(
1733
+ serviceWorkerUrl,
1734
+ projectDirectoryUrl,
1735
+ )
1736
+ const serviceWorkerBuildRelativeUrl =
1737
+ buildMappings[serviceWorkerRelativeUrl]
1576
1738
  if (!serviceWorkerBuildRelativeUrl) {
1577
1739
  throw new Error(
1578
- `"${projectRelativeUrl}" service worker file missing in the build`,
1740
+ `"${serviceWorkerRelativeUrl}" service worker file missing in the build`,
1579
1741
  )
1580
1742
  }
1581
- const buildFileContent = rollupBuild[serviceWorkerBuildRelativeUrl].source
1582
- rollupBuild[serviceWorkerBuildRelativeUrl].source =
1583
- serviceWorkerFinalizer(buildFileContent, {
1743
+
1744
+ if (serviceWorkerFinalizer) {
1745
+ let code = buildFileContents[serviceWorkerBuildRelativeUrl]
1746
+ code = await serviceWorkerFinalizer(code, {
1584
1747
  serviceWorkerBuildRelativeUrl,
1585
1748
  buildManifest,
1586
- rollupBuild,
1749
+ buildFileContents,
1587
1750
  lineBreakNormalization,
1588
1751
  })
1752
+ buildFileContents[serviceWorkerBuildRelativeUrl] = code
1753
+ }
1589
1754
  }),
1590
1755
  )
1591
1756
  }