@jsenv/core 27.0.0-alpha.3 → 27.0.0-alpha.32

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 (222) hide show
  1. package/main.js +4 -0
  2. package/package.json +17 -14
  3. package/readme.md +4 -12
  4. package/src/build/build.js +690 -429
  5. package/src/build/build_urls_generator.js +33 -21
  6. package/src/build/graph_utils.js +31 -0
  7. package/src/build/{inject_version_mappings.js → inject_global_version_mappings.js} +33 -15
  8. package/src/build/inject_service_worker_urls.js +79 -0
  9. package/src/build/resync_ressource_hints.js +68 -0
  10. package/src/build/start_build_server.js +201 -0
  11. package/src/dev/plugins/explorer/jsenv_plugin_explorer.js +2 -2
  12. package/src/dev/plugins/toolbar/jsenv_plugin_toolbar.js +3 -1
  13. package/src/dev/start_dev_server.js +58 -26
  14. package/src/execute/execute.js +30 -4
  15. package/src/execute/run.js +19 -56
  16. package/src/execute/runtimes/browsers/from_playwright.js +201 -147
  17. package/src/execute/runtimes/node/controllable_file.mjs +26 -10
  18. package/src/execute/runtimes/node/node_execution_performance.js +67 -0
  19. package/src/execute/runtimes/node/node_process.js +280 -39
  20. package/src/omega/{runtime_support/default_runtime_support.js → compat/default_runtime_compat.js} +3 -5
  21. package/src/omega/{runtime_support/features_compatibility.js → compat/features_compats.js} +66 -4
  22. package/src/omega/compat/runtime_compat.js +50 -0
  23. package/src/omega/errors.js +51 -58
  24. package/src/omega/fetched_content_compliance.js +24 -0
  25. package/src/omega/file_url_converter.js +8 -50
  26. package/src/omega/kitchen.js +409 -286
  27. package/src/omega/server/file_service.js +9 -11
  28. package/src/omega/url_graph/url_graph_load.js +14 -7
  29. package/src/omega/url_graph/url_graph_report.js +17 -15
  30. package/src/omega/url_graph.js +32 -10
  31. package/src/omega/web_workers.js +42 -0
  32. package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/autoreload_preference.js +0 -0
  33. package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/event_source_client.js +2 -2
  34. package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/reload.js +0 -0
  35. package/src/{dev/plugins/autoreload → plugins/autoreload/dev_sse}/client/url_helpers.js +0 -0
  36. package/src/plugins/autoreload/dev_sse/jsenv_plugin_dev_sse_client.js +41 -0
  37. package/src/{dev/plugins/autoreload/jsenv_plugin_autoreload.js → plugins/autoreload/dev_sse/jsenv_plugin_dev_sse_server.js} +27 -168
  38. package/src/plugins/autoreload/jsenv_plugin_autoreload.js +25 -0
  39. package/src/plugins/autoreload/jsenv_plugin_hmr.js +35 -0
  40. package/src/plugins/bundling/css/bundle_css.js +21 -0
  41. package/src/plugins/bundling/js_classic_workers/bundle_js_classic_workers.js +13 -0
  42. package/src/{build/plugins/bundle_js_module/jsenv_plugin_bundle_js_module.js → plugins/bundling/js_module/bundle_js_module.js} +120 -79
  43. package/src/plugins/bundling/jsenv_plugin_bundling.js +51 -0
  44. package/src/{omega/core_plugins → plugins}/commonjs_globals/jsenv_plugin_commonjs_globals.js +48 -41
  45. package/src/plugins/file_urls/jsenv_plugin_file_urls.js +66 -0
  46. package/src/{omega/core_plugins → plugins}/filesystem_magic/jsenv_plugin_filesystem_magic.js +7 -4
  47. package/src/{omega/core_plugins → plugins}/html_supervisor/client/error_in_document.js +0 -0
  48. package/src/{omega/core_plugins → plugins}/html_supervisor/client/error_in_notification.js +0 -0
  49. package/src/{omega/core_plugins → plugins}/html_supervisor/client/html_supervisor_installer.js +3 -2
  50. package/src/{omega/core_plugins → plugins}/html_supervisor/client/html_supervisor_setup.js +0 -0
  51. package/src/{omega/core_plugins → plugins}/html_supervisor/client/perf_browser.js +0 -0
  52. package/src/{omega/core_plugins → plugins}/html_supervisor/client/uneval_exception.js +0 -0
  53. package/src/{omega/core_plugins → plugins}/html_supervisor/jsenv_plugin_html_supervisor.js +38 -46
  54. package/src/plugins/http_urls/jsenv_plugin_http_urls.js +12 -0
  55. package/src/{dev/plugins/autoreload → plugins/import_meta_hot}/babel_plugin_metadata_import_meta_hot.js +4 -5
  56. package/src/{dev/plugins/autoreload → plugins/import_meta_hot}/client/import_meta_hot.js +3 -1
  57. package/src/{dev/plugins/autoreload → plugins/import_meta_hot}/html_hot_dependencies.js +2 -2
  58. package/src/plugins/import_meta_hot/jsenv_plugin_import_meta_hot.js +98 -0
  59. package/src/{omega/core_plugins → plugins}/import_meta_scenarios/jsenv_plugin_import_meta_scenarios.js +26 -8
  60. package/src/plugins/import_meta_url/client/import_meta_url_browser.js +52 -0
  61. package/src/plugins/import_meta_url/client/import_meta_url_commonjs.mjs +9 -0
  62. package/src/{omega/core_plugins → plugins}/importmap/jsenv_plugin_importmap.js +37 -31
  63. package/src/plugins/inject_globals/jsenv_plugin_inject_globals.js +25 -0
  64. package/src/{omega/core_plugins → plugins}/inline/client/inline_content.js +0 -0
  65. package/src/{omega/core_plugins → plugins}/inline/jsenv_plugin_data_urls.js +18 -14
  66. package/src/{omega/core_plugins/inline/jsenv_plugin_js_and_css_inside_html.js → plugins/inline/jsenv_plugin_html_inline_content.js} +61 -40
  67. package/src/plugins/inline/jsenv_plugin_inline.js +36 -0
  68. package/src/{omega/core_plugins → plugins}/inline/jsenv_plugin_inline_query_param.js +6 -6
  69. package/src/plugins/inline/jsenv_plugin_js_inline_content.js +263 -0
  70. package/src/plugins/leading_slash/jsenv_plugin_leading_slash.js +13 -0
  71. package/src/plugins/minification/css/minify_css.js +9 -0
  72. package/src/plugins/minification/html/minify_html.js +15 -0
  73. package/src/{build/plugins/minify_js/jsenv_plugin_minify_js.js → plugins/minification/js/minify_js.js} +6 -22
  74. package/src/plugins/minification/jsenv_plugin_minification.js +78 -0
  75. package/src/plugins/minification/json/minify_json.js +8 -0
  76. package/src/{omega/core_plugins → plugins}/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +15 -15
  77. package/src/{omega → plugins}/plugin_controller.js +18 -10
  78. package/src/plugins/plugins.js +73 -0
  79. package/src/plugins/transpilation/as_js_classic/client/s.js +808 -0
  80. package/src/plugins/transpilation/as_js_classic/client/s.js.md +1 -0
  81. package/src/plugins/transpilation/as_js_classic/helpers/babel_plugin_transform_import_meta_url.js +47 -0
  82. package/src/plugins/transpilation/as_js_classic/helpers/systemjs_old.js +43 -0
  83. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js +183 -0
  84. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_script_type_module_as_classic.js +256 -0
  85. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_workers_type_module_as_classic.js +139 -0
  86. package/src/{omega/core_plugins → plugins/transpilation}/babel/global_this/babel_plugin_global_this_as_jsenv_import.js +0 -0
  87. package/src/{omega/core_plugins → plugins/transpilation}/babel/global_this/client/global_this.js +0 -0
  88. package/src/{omega/core_plugins/babel/babel_helper → plugins/transpilation/babel/helpers}/babel_plugin_babel_helpers_as_jsenv_imports.js +1 -2
  89. package/src/plugins/transpilation/babel/helpers/babel_plugin_structure.js +161 -0
  90. package/src/{omega/core_plugins → plugins/transpilation}/babel/helpers/babel_plugins_compatibility.js +0 -0
  91. package/src/{omega/core_plugins → plugins/transpilation}/babel/jsenv_plugin_babel.js +38 -22
  92. package/src/{omega/core_plugins → plugins/transpilation}/babel/new_stylesheet/babel_plugin_new_stylesheet_as_jsenv_import.js +30 -6
  93. package/src/{omega/core_plugins → plugins/transpilation}/babel/new_stylesheet/client/.eslintrc.cjs +0 -0
  94. package/src/{omega/core_plugins → plugins/transpilation}/babel/new_stylesheet/client/new_stylesheet.js +0 -0
  95. package/src/{omega/core_plugins → plugins/transpilation}/babel/regenerator_runtime/babel_plugin_regenerator_runtime_as_jsenv_import.js +0 -0
  96. package/src/{omega/core_plugins → plugins/transpilation}/babel/regenerator_runtime/client/regenerator_runtime.js +0 -0
  97. package/src/plugins/transpilation/css_parcel/jsenv_plugin_css_parcel.js +18 -0
  98. package/src/plugins/transpilation/fetch_original_url_info.js +30 -0
  99. package/src/{omega/core_plugins → plugins/transpilation}/import_assertions/helpers/babel_plugin_metadata_import_assertions.js +0 -0
  100. package/src/plugins/transpilation/import_assertions/jsenv_plugin_import_assertions.js +225 -0
  101. package/src/plugins/transpilation/jsenv_plugin_top_level_await.js +37 -0
  102. package/src/plugins/transpilation/jsenv_plugin_transpilation.js +44 -0
  103. package/src/plugins/url_references/css/css_urls.js +49 -0
  104. package/src/plugins/url_references/html/html_urls.js +273 -0
  105. package/src/plugins/url_references/js/js_urls.js +163 -0
  106. package/src/plugins/url_references/jsenv_plugin_url_references.js +18 -0
  107. package/src/plugins/url_references/webmanifest/webmanifest_urls.js +17 -0
  108. package/src/{omega/core_plugins → plugins}/url_resolution/jsenv_plugin_url_resolution.js +12 -5
  109. package/src/{omega/core_plugins → plugins}/url_version/jsenv_plugin_url_version.js +8 -8
  110. package/src/test/execute_plan.js +25 -11
  111. package/src/test/execute_test_plan.js +14 -1
  112. package/src/test/logs_file_execution.js +8 -7
  113. package/src/build/plugins/minify_html/jsenv_plugin_minify_html.js +0 -30
  114. package/src/dev/plugins/autoreload/client/event_source_connection.js +0 -195
  115. package/src/dev/plugins/autoreload/sse_service.js +0 -149
  116. package/src/execute/runtimes/node/controlled_process.js +0 -316
  117. package/src/omega/core_plugins/babel/babel_helper/babel_helper_directory.js +0 -29
  118. package/src/omega/core_plugins/babel/babel_helper/client/.eslintrc.cjs +0 -24
  119. package/src/omega/core_plugins/babel/babel_helper/client/AsyncGenerator/AsyncGenerator.js +0 -81
  120. package/src/omega/core_plugins/babel/babel_helper/client/AwaitValue/AwaitValue.js +0 -3
  121. package/src/omega/core_plugins/babel/babel_helper/client/applyDecoratorDescriptor/applyDecoratorDescriptor.js +0 -33
  122. package/src/omega/core_plugins/babel/babel_helper/client/arrayLikeToArray/arrayLikeToArray.js +0 -7
  123. package/src/omega/core_plugins/babel/babel_helper/client/arrayWithHoles/arrayWithHoles.js +0 -4
  124. package/src/omega/core_plugins/babel/babel_helper/client/arrayWithoutHoles/arrayWithoutHoles.js +0 -6
  125. package/src/omega/core_plugins/babel/babel_helper/client/assertThisInitialized/assertThisInitialized.js +0 -7
  126. package/src/omega/core_plugins/babel/babel_helper/client/asyncGeneratorDelegate/asyncGeneratorDelegate.js +0 -40
  127. package/src/omega/core_plugins/babel/babel_helper/client/asyncIterator/asyncIterator.js +0 -65
  128. package/src/omega/core_plugins/babel/babel_helper/client/asyncToGenerator/asyncToGenerator.js +0 -34
  129. package/src/omega/core_plugins/babel/babel_helper/client/awaitAsyncGenerator/awaitAsyncGenerator.js +0 -5
  130. package/src/omega/core_plugins/babel/babel_helper/client/classApplyDescriptorDestructureSet/classApplyDescriptorDestructureSet.js +0 -20
  131. package/src/omega/core_plugins/babel/babel_helper/client/classApplyDescriptorGet/classApplyDescriptorGet.js +0 -6
  132. package/src/omega/core_plugins/babel/babel_helper/client/classApplyDescriptorSet/classApplyDescriptorSet.js +0 -13
  133. package/src/omega/core_plugins/babel/babel_helper/client/classCallCheck/classCallCheck.js +0 -5
  134. package/src/omega/core_plugins/babel/babel_helper/client/classCheckPrivateStaticAccess/classCheckPrivateStaticAccess.js +0 -5
  135. package/src/omega/core_plugins/babel/babel_helper/client/classCheckPrivateStaticFieldDescriptor/classCheckPrivateStaticFieldDescriptor.js +0 -6
  136. package/src/omega/core_plugins/babel/babel_helper/client/classExtractFieldDescriptor/classExtractFieldDescriptor.js +0 -7
  137. package/src/omega/core_plugins/babel/babel_helper/client/classNameTDZError/classNameTDZError.js +0 -4
  138. package/src/omega/core_plugins/babel/babel_helper/client/classPrivateFieldDestructureSet/classPrivateFieldDestructureSet.js +0 -7
  139. package/src/omega/core_plugins/babel/babel_helper/client/classPrivateFieldGet/classPrivateFieldGet.js +0 -7
  140. package/src/omega/core_plugins/babel/babel_helper/client/classPrivateFieldLooseBase/classPrivateFieldLooseBase.js +0 -6
  141. package/src/omega/core_plugins/babel/babel_helper/client/classPrivateFieldLooseKey/classPrivateFieldLooseKey.js +0 -5
  142. package/src/omega/core_plugins/babel/babel_helper/client/classPrivateFieldSet/classPrivateFieldSet.js +0 -8
  143. package/src/omega/core_plugins/babel/babel_helper/client/classPrivateMethodGet/classPrivateMethodGet.js +0 -6
  144. package/src/omega/core_plugins/babel/babel_helper/client/classPrivateMethodSet/classPrivateMethodSet.js +0 -3
  145. package/src/omega/core_plugins/babel/babel_helper/client/classStaticPrivateFieldSpecGet/classStaticPrivateFieldSpecGet.js +0 -9
  146. package/src/omega/core_plugins/babel/babel_helper/client/classStaticPrivateFieldSpecSet/classStaticPrivateFieldSpecSet.js +0 -15
  147. package/src/omega/core_plugins/babel/babel_helper/client/classStaticPrivateMethodGet/classStaticPrivateMethodGet.js +0 -6
  148. package/src/omega/core_plugins/babel/babel_helper/client/classStaticPrivateMethodSet/classStaticPrivateMethodSet.js +0 -3
  149. package/src/omega/core_plugins/babel/babel_helper/client/construct/construct.js +0 -16
  150. package/src/omega/core_plugins/babel/babel_helper/client/createClass/createClass.js +0 -15
  151. package/src/omega/core_plugins/babel/babel_helper/client/createForOfIteratorHelper/createForOfIteratorHelper.js +0 -60
  152. package/src/omega/core_plugins/babel/babel_helper/client/createForOfIteratorHelperLoose/createForOfIteratorHelperLoose.js +0 -23
  153. package/src/omega/core_plugins/babel/babel_helper/client/createRawReactElement/createRawReactElement.js +0 -50
  154. package/src/omega/core_plugins/babel/babel_helper/client/createSuper/createSuper.js +0 -22
  155. package/src/omega/core_plugins/babel/babel_helper/client/decorate/decorate.js +0 -403
  156. package/src/omega/core_plugins/babel/babel_helper/client/defaults/defaults.js +0 -11
  157. package/src/omega/core_plugins/babel/babel_helper/client/defineEnumerableProperties/defineEnumerableProperties.js +0 -23
  158. package/src/omega/core_plugins/babel/babel_helper/client/defineProperty/defineProperty.js +0 -18
  159. package/src/omega/core_plugins/babel/babel_helper/client/extends/extends.js +0 -14
  160. package/src/omega/core_plugins/babel/babel_helper/client/get/get.js +0 -19
  161. package/src/omega/core_plugins/babel/babel_helper/client/getPrototypeOf/getPrototypeOf.js +0 -4
  162. package/src/omega/core_plugins/babel/babel_helper/client/inherits/inherits.js +0 -19
  163. package/src/omega/core_plugins/babel/babel_helper/client/inheritsLoose/inheritsLoose.js +0 -7
  164. package/src/omega/core_plugins/babel/babel_helper/client/initializerDefineProperty/initializerDefineProperty.js +0 -10
  165. package/src/omega/core_plugins/babel/babel_helper/client/initializerWarningHelper/initializerWarningHelper.js +0 -6
  166. package/src/omega/core_plugins/babel/babel_helper/client/instanceof/instanceof.js +0 -6
  167. package/src/omega/core_plugins/babel/babel_helper/client/interopRequireDefault/interopRequireDefault.js +0 -3
  168. package/src/omega/core_plugins/babel/babel_helper/client/interopRequireWildcard/interopRequireWildcard.js +0 -37
  169. package/src/omega/core_plugins/babel/babel_helper/client/isNativeFunction/isNativeFunction.js +0 -4
  170. package/src/omega/core_plugins/babel/babel_helper/client/isNativeReflectConstruct/isNativeReflectConstruct.js +0 -21
  171. package/src/omega/core_plugins/babel/babel_helper/client/iterableToArray/iterableToArray.js +0 -7
  172. package/src/omega/core_plugins/babel/babel_helper/client/iterableToArrayLimit/iterableToArrayLimit.js +0 -36
  173. package/src/omega/core_plugins/babel/babel_helper/client/iterableToArrayLimitLoose/iterableToArrayLimitLoose.js +0 -10
  174. package/src/omega/core_plugins/babel/babel_helper/client/jsx/jsx.js +0 -50
  175. package/src/omega/core_plugins/babel/babel_helper/client/maybeArrayLike/maybeArrayLike.js +0 -10
  176. package/src/omega/core_plugins/babel/babel_helper/client/newArrowCheck/newArrowCheck.js +0 -5
  177. package/src/omega/core_plugins/babel/babel_helper/client/nonIterableRest/nonIterableRest.js +0 -5
  178. package/src/omega/core_plugins/babel/babel_helper/client/nonIterableSpread/nonIterableSpread.js +0 -5
  179. package/src/omega/core_plugins/babel/babel_helper/client/objectDestructuringEmpty/objectDestructuringEmpty.js +0 -3
  180. package/src/omega/core_plugins/babel/babel_helper/client/objectSpread/objectSpread.js +0 -23
  181. package/src/omega/core_plugins/babel/babel_helper/client/objectSpread2/objectSpread2.js +0 -41
  182. package/src/omega/core_plugins/babel/babel_helper/client/objectWithoutProperties/objectWithoutProperties.js +0 -19
  183. package/src/omega/core_plugins/babel/babel_helper/client/objectWithoutPropertiesLoose/objectWithoutPropertiesLoose.js +0 -13
  184. package/src/omega/core_plugins/babel/babel_helper/client/possibleConstructorReturn/possibleConstructorReturn.js +0 -10
  185. package/src/omega/core_plugins/babel/babel_helper/client/readOnlyError/readOnlyError.js +0 -4
  186. package/src/omega/core_plugins/babel/babel_helper/client/readme.md +0 -8
  187. package/src/omega/core_plugins/babel/babel_helper/client/set/set.js +0 -44
  188. package/src/omega/core_plugins/babel/babel_helper/client/setPrototypeOf/setPrototypeOf.js +0 -6
  189. package/src/omega/core_plugins/babel/babel_helper/client/skipFirstGeneratorNext/skipFirstGeneratorNext.js +0 -8
  190. package/src/omega/core_plugins/babel/babel_helper/client/slicedToArray/slicedToArray.js +0 -10
  191. package/src/omega/core_plugins/babel/babel_helper/client/slicedToArrayLoose/slicedToArrayLoose.js +0 -13
  192. package/src/omega/core_plugins/babel/babel_helper/client/superPropBase/superPropBase.js +0 -10
  193. package/src/omega/core_plugins/babel/babel_helper/client/taggedTemplateLiteral/taggedTemplateLiteral.js +0 -10
  194. package/src/omega/core_plugins/babel/babel_helper/client/taggedTemplateLiteralLoose/taggedTemplateLiteralLoose.js +0 -7
  195. package/src/omega/core_plugins/babel/babel_helper/client/tdz/tdz.js +0 -4
  196. package/src/omega/core_plugins/babel/babel_helper/client/temporalRef/temporalRef.js +0 -6
  197. package/src/omega/core_plugins/babel/babel_helper/client/temporalUndefined/temporalUndefined.js +0 -3
  198. package/src/omega/core_plugins/babel/babel_helper/client/toArray/toArray.js +0 -10
  199. package/src/omega/core_plugins/babel/babel_helper/client/toConsumableArray/toConsumableArray.js +0 -10
  200. package/src/omega/core_plugins/babel/babel_helper/client/toPrimitive/toPrimitive.js +0 -10
  201. package/src/omega/core_plugins/babel/babel_helper/client/toPropertyKey/toPropertyKey.js +0 -6
  202. package/src/omega/core_plugins/babel/babel_helper/client/typeof/typeof.js +0 -14
  203. package/src/omega/core_plugins/babel/babel_helper/client/unsupportedIterableToArray/unsupportedIterableToArray.js +0 -12
  204. package/src/omega/core_plugins/babel/babel_helper/client/wrapAsyncGenerator/wrapAsyncGenerator.js +0 -8
  205. package/src/omega/core_plugins/babel/babel_helper/client/wrapNativeSuper/wrapNativeSuper.js +0 -30
  206. package/src/omega/core_plugins/babel/babel_helper/client/wrapRegExp/wrapRegExp.js +0 -63
  207. package/src/omega/core_plugins/babel/babel_helper/client/writeOnlyError/writeOnlyError.js +0 -4
  208. package/src/omega/core_plugins/babel/helpers/babel_plugin_structure.js +0 -187
  209. package/src/omega/core_plugins/file_urls/jsenv_plugin_file_urls.js +0 -67
  210. package/src/omega/core_plugins/import_assertions/helpers/json_module.js +0 -12
  211. package/src/omega/core_plugins/import_assertions/helpers/text_module.js +0 -6
  212. package/src/omega/core_plugins/import_assertions/jsenv_plugin_import_assertions.js +0 -211
  213. package/src/omega/core_plugins/inline/jsenv_plugin_inline.js +0 -13
  214. package/src/omega/core_plugins/inline/jsenv_plugin_new_inline_content.js +0 -210
  215. package/src/omega/core_plugins/leading_slash/jsenv_plugin_leading_slash.js +0 -12
  216. package/src/omega/core_plugins.js +0 -39
  217. package/src/omega/runtime_support/runtime_support.js +0 -20
  218. package/src/omega/url_mentions/css_url_mentions.js +0 -63
  219. package/src/omega/url_mentions/html_url_mentions.js +0 -185
  220. package/src/omega/url_mentions/js_module_url_mentions.js +0 -91
  221. package/src/omega/url_mentions/parse_url_mentions.js +0 -37
  222. package/src/omega/url_mentions/worker_classic_url_mentions.js +0 -37
@@ -21,28 +21,30 @@ import { createTaskLog } from "@jsenv/utils/logs/task_log.js"
21
21
  import {
22
22
  injectQueryParams,
23
23
  setUrlFilename,
24
+ asUrlUntilPathname,
24
25
  } from "@jsenv/utils/urls/url_utils.js"
25
- import { createUrlVersionGenerator } from "@jsenv/utils/urls/url_version_generator.js"
26
+ import { createVersionGenerator } from "@jsenv/utils/versioning/version_generator.js"
26
27
  import { generateSourcemapUrl } from "@jsenv/utils/sourcemap/sourcemap_utils.js"
27
28
  import {
28
29
  parseHtmlString,
29
30
  stringifyHtmlAst,
30
31
  } from "@jsenv/utils/html_ast/html_ast.js"
31
32
 
32
- import { defaultRuntimeSupport } from "../omega/runtime_support/default_runtime_support.js"
33
- import { jsenvPluginInline } from "../omega/core_plugins/inline/jsenv_plugin_inline.js"
33
+ import { jsenvPluginInline } from "../plugins/inline/jsenv_plugin_inline.js"
34
+ import { jsenvPluginAsJsClassic } from "../plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js"
34
35
  import { createUrlGraph } from "../omega/url_graph.js"
35
- import { getCorePlugins } from "../omega/core_plugins.js"
36
+ import { getCorePlugins } from "../plugins/plugins.js"
36
37
  import { createKitchen } from "../omega/kitchen.js"
37
38
  import { loadUrlGraph } from "../omega/url_graph/url_graph_load.js"
38
39
  import { createUrlGraphSummary } from "../omega/url_graph/url_graph_report.js"
39
40
  import { sortUrlGraphByDependencies } from "../omega/url_graph/url_graph_sort.js"
41
+ import { isWebWorkerEntryPointReference } from "../omega/web_workers.js"
40
42
 
43
+ import { GRAPH } from "./graph_utils.js"
41
44
  import { createBuilUrlsGenerator } from "./build_urls_generator.js"
42
- import { injectVersionMappings } from "./inject_version_mappings.js"
43
- import { jsenvPluginBundleJsModule } from "./plugins/bundle_js_module/jsenv_plugin_bundle_js_module.js"
44
- import { jsenvPluginMinifyJs } from "./plugins/minify_js/jsenv_plugin_minify_js.js"
45
- import { jsenvPluginMinifyHtml } from "./plugins/minify_html/jsenv_plugin_minify_html.js"
45
+ import { injectGlobalVersionMapping } from "./inject_global_version_mappings.js"
46
+ import { injectServiceWorkerUrls } from "./inject_service_worker_urls.js"
47
+ import { resyncRessourceHints } from "./resync_ressource_hints.js"
46
48
 
47
49
  export const build = async ({
48
50
  signal = new AbortController().signal,
@@ -54,37 +56,40 @@ export const build = async ({
54
56
  // that will just pass different options to build project
55
57
  // and this function will be agnostic about "preview" concept
56
58
  isPreview = false,
59
+
57
60
  plugins = [],
58
- htmlSupervisor,
61
+ sourcemaps = isPreview ? "file" : false,
59
62
  nodeEsmResolution,
60
63
  fileSystemMagicResolution,
61
- babel,
62
- runtimeSupport = defaultRuntimeSupport,
63
- sourcemaps = isPreview ? "file" : false,
64
-
64
+ injectedGlobals,
65
+ runtimeCompat,
66
+ transpilation = {},
65
67
  bundling = true,
66
- minify = true,
67
- versioning = "filename", // "filename", "search_param", "none"
68
+ minification = true,
69
+ versioning = true,
70
+ versioningMethod = "search_param", // "filename", "search_param"
68
71
  lineBreakNormalization = process.platform === "win32",
69
72
 
70
73
  writeOnFileSystem = true,
71
74
  buildDirectoryClean = true,
72
75
  baseUrl = "/",
76
+ assetManifest = true,
77
+ assetManifestFileRelativeUrl = "asset-manifest.json",
73
78
  }) => {
74
79
  const logger = createLogger({ logLevel })
75
80
  rootDirectoryUrl = assertAndNormalizeDirectoryUrl(rootDirectoryUrl)
76
81
  buildDirectoryUrl = assertAndNormalizeDirectoryUrl(buildDirectoryUrl)
77
82
  assertEntryPoints({ entryPoints })
78
- if (!["filename", "search_param", "none"].includes(versioning)) {
83
+ if (!["filename", "search_param"].includes(versioningMethod)) {
79
84
  throw new Error(
80
- `Unexpected "versioning": must be "filename", "search_param" or "none"; got ${versioning}`,
85
+ `Unexpected "versioningMethod": must be "filename", "search_param"; got ${versioning}`,
81
86
  )
82
87
  }
83
88
 
84
89
  const entryPointKeys = Object.keys(entryPoints)
85
90
  if (entryPointKeys.length === 1) {
86
91
  logger.info(`
87
- build ${entryPointKeys[0]}`)
92
+ build "${entryPointKeys[0]}"`)
88
93
  } else {
89
94
  logger.info(`
90
95
  build ${entryPointKeys.length} entry points`)
@@ -97,6 +102,9 @@ build ${entryPointKeys.length} entry points`)
97
102
  logger,
98
103
  rootDirectoryUrl,
99
104
  urlGraph: rawGraph,
105
+ scenario: "build",
106
+ sourcemaps,
107
+ runtimeCompat,
100
108
  plugins: [
101
109
  ...plugins,
102
110
  {
@@ -108,33 +116,34 @@ build ${entryPointKeys.length} entry points`)
108
116
  },
109
117
  },
110
118
  ...getCorePlugins({
111
- htmlSupervisor,
112
119
  nodeEsmResolution,
113
120
  fileSystemMagicResolution,
114
- babel,
121
+ injectedGlobals,
122
+ transpilation: {
123
+ ...transpilation,
124
+ jsModuleAsJsClassic: false,
125
+ },
126
+ minification,
127
+ bundling,
115
128
  }),
116
- jsenvPluginBundleJsModule(),
117
- ...(minify ? [jsenvPluginMinifyJs(), jsenvPluginMinifyHtml()] : []),
118
129
  ],
119
- scenario: "build",
120
- sourcemaps,
121
130
  })
122
- const loadEntryFiles = (cookEntryFile) => {
123
- Object.keys(entryPoints).forEach((key) => {
124
- cookEntryFile({
125
- trace: `"${key}" in entryPoints parameter`,
126
- type: "entry_point",
127
- specifier: key,
128
- })
129
- })
130
- }
131
+ const entryUrls = []
131
132
  try {
132
133
  await loadUrlGraph({
133
134
  urlGraph: rawGraph,
134
135
  kitchen: rawGraphKitchen,
135
136
  outDirectoryUrl: new URL(`.jsenv/build/`, rootDirectoryUrl),
136
- runtimeSupport,
137
- startLoading: loadEntryFiles,
137
+ startLoading: (cookEntryFile) => {
138
+ Object.keys(entryPoints).forEach((key) => {
139
+ const [, entryUrlInfo] = cookEntryFile({
140
+ trace: `"${key}" in entryPoints parameter`,
141
+ type: "entry_point",
142
+ specifier: key,
143
+ })
144
+ entryUrls.push(entryUrlInfo.url)
145
+ })
146
+ },
138
147
  })
139
148
  } catch (e) {
140
149
  prebuildTask.fail()
@@ -147,44 +156,50 @@ build ${entryPointKeys.length} entry points`)
147
156
  ${Object.keys(rawGraph.urlInfos).join("\n")}`,
148
157
  )
149
158
 
159
+ const buildUrlsGenerator = createBuilUrlsGenerator({
160
+ buildDirectoryUrl,
161
+ })
162
+ const rawUrls = {}
163
+ const buildUrls = {}
164
+ const rawUrlRedirections = {}
150
165
  const bundleUrlInfos = {}
151
- if (bundling) {
152
- const bundlers = {}
153
- rawGraphKitchen.pluginController.plugins.forEach((plugin) => {
154
- const bundle = plugin.bundle
155
- if (!bundle) {
166
+ const bundlers = {}
167
+ rawGraphKitchen.pluginController.plugins.forEach((plugin) => {
168
+ const bundle = plugin.bundle
169
+ if (!bundle) {
170
+ return
171
+ }
172
+ if (typeof bundle !== "object") {
173
+ throw new Error(
174
+ `bundle must be an object, found "${bundle}" on plugin named "${plugin.name}"`,
175
+ )
176
+ }
177
+ Object.keys(bundle).forEach((type) => {
178
+ const bundleFunction = bundle[type]
179
+ if (!bundleFunction) {
156
180
  return
157
181
  }
158
- if (typeof bundle !== "object") {
159
- throw new Error(
160
- `bundle must be an object, found "${bundle}" on plugin named "${plugin.name}"`,
161
- )
162
- }
163
- Object.keys(bundle).forEach((type) => {
164
- const bundlerForThatType = bundlers[type]
165
- if (bundlerForThatType) {
166
- // first plugin to define a bundle hook wins
167
- return
168
- }
169
- bundlers[type] = {
170
- plugin,
171
- bundleFunction: bundle[type],
172
- urlInfos: [],
173
- }
174
- })
175
- })
176
- const addToBundlerIfAny = (rawUrlInfo) => {
177
- const bundler = bundlers[rawUrlInfo.type]
178
- if (bundler) {
179
- bundler.urlInfos.push(rawUrlInfo)
182
+ const bundlerForThatType = bundlers[type]
183
+ if (bundlerForThatType) {
184
+ // first plugin to define a bundle hook wins
180
185
  return
181
186
  }
182
- }
183
- Object.keys(rawGraph.urlInfos).forEach((rawUrl) => {
184
- const rawUrlInfo = rawGraph.getUrlInfo(rawUrl)
185
- if (!rawUrlInfo.data.isEntryPoint) {
186
- return
187
+ bundlers[type] = {
188
+ plugin,
189
+ bundleFunction: bundle[type],
190
+ urlInfos: [],
187
191
  }
192
+ })
193
+ })
194
+ const addToBundlerIfAny = (rawUrlInfo) => {
195
+ const bundler = bundlers[rawUrlInfo.type]
196
+ if (bundler) {
197
+ bundler.urlInfos.push(rawUrlInfo)
198
+ return
199
+ }
200
+ }
201
+ GRAPH.forEach(rawGraph, (rawUrlInfo) => {
202
+ if (rawUrlInfo.data.isEntryPoint) {
188
203
  addToBundlerIfAny(rawUrlInfo)
189
204
  if (rawUrlInfo.type === "html") {
190
205
  rawUrlInfo.dependencies.forEach((dependencyUrl) => {
@@ -194,7 +209,8 @@ ${Object.keys(rawGraph.urlInfos).join("\n")}`,
194
209
  // bundle inline script type module deps
195
210
  dependencyUrlInfo.references.forEach((inlineScriptRef) => {
196
211
  if (inlineScriptRef.type === "js_import_export") {
197
- addToBundlerIfAny(rawGraph.getUrlInfo(inlineScriptRef.url))
212
+ const inlineUrlInfo = rawGraph.getUrlInfo(inlineScriptRef.url)
213
+ addToBundlerIfAny(inlineUrlInfo)
198
214
  }
199
215
  })
200
216
  }
@@ -205,231 +221,333 @@ ${Object.keys(rawGraph.urlInfos).join("\n")}`,
205
221
  })
206
222
  return
207
223
  }
208
- })
209
- await Object.keys(bundlers).reduce(async (previous, type) => {
210
- await previous
211
- const bundler = bundlers[type]
212
- const urlInfosToBundle = bundler.urlInfos
213
- if (urlInfosToBundle.length === 0) {
214
- return
215
- }
216
- const bundleTask = createTaskLog(logger, `bundle "${type}"`)
217
- try {
218
- const bundlerGeneratedUrlInfos =
219
- await rawGraphKitchen.pluginController.callAsyncHook(
220
- {
221
- plugin: bundler.plugin,
222
- hookName: "bundle",
223
- value: bundler.bundleFunction,
224
- },
225
- urlInfosToBundle,
226
- {
227
- signal,
228
- logger,
229
- rootDirectoryUrl,
230
- buildDirectoryUrl,
231
- urlGraph: rawGraph,
232
- runtimeSupport,
233
- sourcemaps,
234
- },
235
- )
236
- Object.keys(bundlerGeneratedUrlInfos).forEach((url) => {
237
- const bundleUrlInfo = bundlerGeneratedUrlInfos[url]
238
- const rawUrlInfo = rawGraph.getUrlInfo(url)
239
- bundleUrlInfos[url] = {
240
- type,
241
- ...bundleUrlInfo,
242
- data: {
243
- ...(rawUrlInfo ? rawUrlInfo.data : {}),
244
- ...bundleUrlInfo.data,
245
- fromBundle: true,
246
- },
247
- }
224
+ }
225
+ // File referenced with new URL('./file.js', import.meta.url)
226
+ // are entry points that can be bundled
227
+ // For instance we will bundle service worker/workers detected like this
228
+ if (rawUrlInfo.type === "js_module") {
229
+ rawUrlInfo.references.forEach((reference) => {
230
+ if (reference.type === "js_url_specifier") {
231
+ const urlInfo = rawGraph.getUrlInfo(reference.url)
232
+ addToBundlerIfAny(urlInfo)
233
+ }
234
+ })
235
+ }
236
+ })
237
+ const bundleUrlRedirections = {}
238
+ await Object.keys(bundlers).reduce(async (previous, type) => {
239
+ await previous
240
+ const bundler = bundlers[type]
241
+ const urlInfosToBundle = bundler.urlInfos
242
+ if (urlInfosToBundle.length === 0) {
243
+ return
244
+ }
245
+ const bundleTask = createTaskLog(logger, `bundle "${type}"`)
246
+ try {
247
+ const bundlerGeneratedUrlInfos =
248
+ await rawGraphKitchen.pluginController.callAsyncHook(
249
+ {
250
+ plugin: bundler.plugin,
251
+ hookName: "bundle",
252
+ value: bundler.bundleFunction,
253
+ },
254
+ urlInfosToBundle,
255
+ {
256
+ ...rawGraphKitchen.baseContext,
257
+ buildDirectoryUrl,
258
+ },
259
+ )
260
+ Object.keys(bundlerGeneratedUrlInfos).forEach((url) => {
261
+ const rawUrlInfo = rawGraph.getUrlInfo(url)
262
+ const bundlerGeneratedUrlInfo = bundlerGeneratedUrlInfos[url]
263
+ const bundleUrlInfo = {
264
+ type,
265
+ subtype: rawUrlInfo ? rawUrlInfo.subtype : undefined,
266
+ filename: rawUrlInfo ? rawUrlInfo.filename : undefined,
267
+ ...bundlerGeneratedUrlInfo,
268
+ data: {
269
+ ...(rawUrlInfo ? rawUrlInfo.data : {}),
270
+ ...bundlerGeneratedUrlInfo.data,
271
+ fromBundle: true,
272
+ },
273
+ }
274
+ const buildUrl = buildUrlsGenerator.generate(url, {
275
+ urlInfo: bundleUrlInfo,
248
276
  })
249
- } catch (e) {
250
- bundleTask.fail()
251
- throw e
252
- }
253
- bundleTask.done()
254
- }, Promise.resolve())
255
- }
277
+ rawUrlRedirections[url] = buildUrl
278
+ rawUrls[buildUrl] = url
279
+ bundleUrlInfos[buildUrl] = bundleUrlInfo
280
+ if (bundlerGeneratedUrlInfo.data.bundleRelativeUrl) {
281
+ const urlForBundler = new URL(
282
+ bundlerGeneratedUrlInfo.data.bundleRelativeUrl,
283
+ buildDirectoryUrl,
284
+ ).href
285
+ bundleUrlRedirections[urlForBundler] = buildUrl
286
+ }
287
+ })
288
+ } catch (e) {
289
+ bundleTask.fail()
290
+ throw e
291
+ }
292
+ bundleTask.done()
293
+ }, Promise.resolve())
256
294
 
257
- const buildUrlsGenerator = createBuilUrlsGenerator({
258
- buildDirectoryUrl,
259
- })
260
- const rawUrls = {}
261
- const buildUrls = {}
295
+ const buildUrlRedirections = {}
262
296
  const finalGraph = createUrlGraph()
263
- const optimizeHooks = rawGraphKitchen.pluginController.addHook("optimize")
297
+ const optimizeUrlContentHooks =
298
+ rawGraphKitchen.pluginController.addHook("optimizeUrlContent")
264
299
  const finalGraphKitchen = createKitchen({
265
300
  logger,
266
301
  rootDirectoryUrl,
267
302
  urlGraph: finalGraph,
268
- // Inline content, such as <script> inside html, is transformed during the previous phase.
269
- // If we read the inline content it would be considered as the original content.
270
- // - It could be "fixed" by taking into account sourcemap and consider sourcemap sources
271
- // as the original content.
272
- // - But it would not work when sourcemap are not generated
273
- // - would be a bit slower
274
- // - So instead of reading the inline content directly, we search into raw graph
275
- // to get "originalContent" and "sourcemap"
276
- loadInlineUrlInfos: (finalUrlInfo) => {
277
- const rawUrl = finalUrlInfo.data.rawUrl
278
- const bundleUrlInfo = bundleUrlInfos[rawUrl]
279
- const urlInfo = bundleUrlInfo || finalUrlInfo
280
- const rawUrlInfo = rawGraph.getUrlInfo(rawUrl)
281
- return {
282
- originalContent: rawUrlInfo ? rawUrlInfo.originalContent : undefined,
283
- sourcemap: bundleUrlInfo
284
- ? bundleUrlInfo.sourcemap
285
- : rawUrlInfo
286
- ? rawUrlInfo.sourcemap
287
- : undefined,
288
- contentType: urlInfo.contentType,
289
- content: urlInfo.content,
290
- }
291
- },
303
+ scenario: "build",
304
+ sourcemaps,
305
+ runtimeCompat,
292
306
  plugins: [
293
- jsenvPluginInline(),
307
+ jsenvPluginAsJsClassic({
308
+ systemJsInjection: true,
309
+ }),
310
+ jsenvPluginInline({
311
+ fetchInlineUrls: false,
312
+ }),
294
313
  {
295
314
  name: "jsenv:postbuild",
296
315
  appliesDuring: { build: true },
297
- resolve: (reference) => {
298
- if (reference.specifier[0] === "/") {
299
- const url = new URL(reference.specifier.slice(1), rootDirectoryUrl)
300
- .href
301
- return url
316
+ resolveUrl: (reference) => {
317
+ if (reference.specifier[0] === "#") {
318
+ reference.external = true
302
319
  }
303
- const parentUrlInfo = finalGraph.getUrlInfo(reference.parentUrl)
304
- if (parentUrlInfo && parentUrlInfo.data.fromBundle) {
305
- // code generated by rollup contains specifier relative
306
- // to the generated file.
307
- // This file does not exists yet we must resolve against the raw url, not the build url
308
- const parentRawUrl = parentUrlInfo.data.rawUrl
309
- const rawUrl = new URL(reference.specifier, parentRawUrl).href
310
- return rawUrl
320
+ let url =
321
+ reference.specifier[0] === "/"
322
+ ? new URL(reference.specifier.slice(1), buildDirectoryUrl).href
323
+ : new URL(reference.specifier, reference.parentUrl).href
324
+ const urlRedirectedByBundle = bundleUrlRedirections[url]
325
+ if (urlRedirectedByBundle) {
326
+ return urlRedirectedByBundle
327
+ }
328
+ const parentIsFromBundle = Boolean(
329
+ bundleUrlInfos[reference.parentUrl],
330
+ )
331
+ // urls inside css bundled by parcel
332
+ // contains url relative to the bundle file (which is considered inside build directory)
333
+ // if the file is not itself a bundle file it must be resolved against
334
+ // the original css url
335
+ if (
336
+ parentIsFromBundle &&
337
+ !bundleUrlInfos[url] &&
338
+ urlIsInsideOf(url, buildDirectoryUrl)
339
+ ) {
340
+ const parentRawUrl = rawUrls[reference.parentUrl]
341
+ url = new URL(reference.specifier, parentRawUrl).href
311
342
  }
312
- return new URL(reference.specifier, reference.parentUrl).href
343
+ const urlRedirected = rawUrlRedirections[url]
344
+ return urlRedirected || url
313
345
  },
314
- normalize: (reference) => {
346
+ normalizeUrl: (reference) => {
315
347
  if (!reference.url.startsWith("file:")) {
316
348
  return null
317
349
  }
318
350
  // already a build url
319
351
  const rawUrl = rawUrls[reference.url]
320
352
  if (rawUrl) {
321
- reference.data.rawUrl = rawUrl
322
353
  return reference.url
323
354
  }
324
- const bundleUrlInfo = bundleUrlInfos[reference.url]
325
355
  // from rollup or postcss
356
+ const bundleUrlInfo = bundleUrlInfos[reference.url]
326
357
  if (bundleUrlInfo) {
327
- const buildUrl = buildUrlsGenerator.generate(
328
- reference.url,
329
- bundleUrlInfo,
330
- )
331
- reference.data.rawUrl = reference.url
332
- rawUrls[buildUrl] = reference.url
333
- return buildUrl
358
+ return reference.url
334
359
  }
335
- const rawUrlInfo = rawGraph.getUrlInfo(reference.url)
336
- // files from root directory but not given to rollup nor postcss
337
- if (rawUrlInfo) {
338
- const buildUrl = buildUrlsGenerator.generate(
339
- reference.url,
340
- rawUrlInfo,
341
- )
342
- reference.data.rawUrl = reference.url
343
- rawUrls[buildUrl] = reference.url
360
+ // from "js_module_as_js_classic":
361
+ // - injecting "?as_js_classic" for the first time
362
+ // - injecting "?as_js_classic" because the parentUrl has it
363
+ if (reference.original) {
364
+ const referenceOriginalUrl = reference.original.url
365
+ let originalBuildUrl
366
+ if (urlIsInsideOf(referenceOriginalUrl, buildDirectoryUrl)) {
367
+ originalBuildUrl = referenceOriginalUrl
368
+ } else {
369
+ originalBuildUrl = Object.keys(rawUrls).find(
370
+ (key) => rawUrls[key] === referenceOriginalUrl,
371
+ )
372
+ }
373
+ let rawUrl
374
+ if (urlIsInsideOf(reference.url, buildDirectoryUrl)) {
375
+ // rawUrl = rawUrls[reference.url] || reference.url
376
+ const originalBuildUrl =
377
+ buildUrlRedirections[referenceOriginalUrl]
378
+ rawUrl = originalBuildUrl
379
+ ? rawUrls[originalBuildUrl]
380
+ : reference.url
381
+ } else {
382
+ rawUrl = reference.url
383
+ }
384
+ // the url info do not exists yet (it will be created after this "normalize" hook)
385
+ // And the content will be generated when url is cooked by url graph loader.
386
+ // Here we just want to reserve an url for that file
387
+ const buildUrl = buildUrlsGenerator.generate(rawUrl, {
388
+ urlInfo: {
389
+ data: {
390
+ ...reference.data,
391
+ isWebWorkerEntryPoint:
392
+ isWebWorkerEntryPointReference(reference),
393
+ },
394
+ type: reference.expectedType,
395
+ subtype: reference.expectedSubtype,
396
+ filename: reference.filename,
397
+ },
398
+ })
399
+ buildUrlRedirections[originalBuildUrl] = buildUrl
400
+ rawUrls[buildUrl] = rawUrl
344
401
  return buildUrl
345
402
  }
346
403
  if (reference.isInline) {
347
- const rawUrl = Object.keys(rawGraph.urlInfos).find((url) => {
348
- const rawUrlInfo = rawGraph.urlInfos[url]
404
+ const rawUrlInfo = GRAPH.find(rawGraph, (rawUrlInfo) => {
349
405
  if (!rawUrlInfo.isInline) {
350
406
  return false
351
407
  }
352
408
  if (rawUrlInfo.content === reference.content) {
353
409
  return true
354
410
  }
411
+ if (rawUrlInfo.originalContent === reference.content) {
412
+ return true
413
+ }
355
414
  return false
356
415
  })
357
- if (!rawUrl) {
358
- throw new Error(`cannot find raw url`)
359
- }
360
- const rawUrlInfo = rawGraph.getUrlInfo(rawUrl)
361
416
  const parentUrlInfo = finalGraph.getUrlInfo(reference.parentUrl)
362
- const buildUrl = buildUrlsGenerator.generate(
363
- reference.url,
364
- rawUrlInfo,
417
+ if (!rawUrlInfo) {
418
+ // generated during final graph
419
+ // (happens for JSON.parse injected for import assertions for instance)
420
+ // throw new Error(`cannot find raw url for "${reference.url}"`)
421
+ return reference.url
422
+ }
423
+ const buildUrl = buildUrlsGenerator.generate(reference.url, {
424
+ urlInfo: rawUrlInfo,
365
425
  parentUrlInfo,
366
- )
426
+ })
427
+ rawUrls[buildUrl] = rawUrlInfo.url
428
+ return buildUrl
429
+ }
430
+ // from "js_module_as_js_classic":
431
+ // - to inject "s.js"
432
+ if (reference.injected) {
433
+ const buildUrl = buildUrlsGenerator.generate(reference.url, {
434
+ urlInfo: {
435
+ data: {},
436
+ type: "js_classic",
437
+ },
438
+ })
367
439
  rawUrls[buildUrl] = reference.url
368
- reference.data.rawUrl = rawUrl
440
+ return buildUrl
441
+ }
442
+ const rawUrlInfo = rawGraph.getUrlInfo(reference.url)
443
+ // files from root directory but not given to rollup nor postcss
444
+ if (rawUrlInfo) {
445
+ const buildUrl = buildUrlsGenerator.generate(reference.url, {
446
+ urlInfo: rawUrlInfo,
447
+ })
448
+ rawUrls[buildUrl] = rawUrlInfo.url
369
449
  return buildUrl
370
450
  }
371
451
  if (reference.type === "sourcemap_comment") {
372
452
  // inherit parent build url
373
453
  return generateSourcemapUrl(reference.parentUrl)
374
454
  }
375
- // files generated during the final graph (sourcemaps)
455
+ // files generated during the final graph:
456
+ // - sourcemaps
376
457
  // const finalUrlInfo = finalGraph.getUrlInfo(url)
377
458
  const buildUrl = buildUrlsGenerator.generate(reference.url, {
378
- data: {},
379
- type: "asset",
459
+ urlInfo: {
460
+ data: {},
461
+ type: "asset",
462
+ },
380
463
  })
381
464
  return buildUrl
382
465
  },
383
- formatReferencedUrl: (reference) => {
384
- if (!reference.url.startsWith("file:")) {
466
+ formatUrl: (reference) => {
467
+ if (!reference.generatedUrl.startsWith("file:")) {
385
468
  return null
386
469
  }
387
- if (!urlIsInsideOf(reference.url, buildDirectoryUrl)) {
470
+ if (!urlIsInsideOf(reference.generatedUrl, buildDirectoryUrl)) {
388
471
  throw new Error(
389
472
  `urls should be inside build directory at this stage, found "${reference.url}"`,
390
473
  )
391
474
  }
475
+ // remove eventual search params and hash
476
+ const urlUntilPathname = asUrlUntilPathname(reference.generatedUrl)
392
477
  // if a file is in the same directory we could prefer the relative notation
393
- // but to keep things simple let's keep the notation relative to baseUrl for now
478
+ // but to keep things simple let's keep the "absolutely relative" to baseUrl for now
394
479
  const specifier = `${baseUrl}${urlToRelativeUrl(
395
- reference.url,
480
+ urlUntilPathname,
396
481
  buildDirectoryUrl,
397
482
  )}`
398
- buildUrls[specifier] = reference.url
483
+ buildUrls[specifier] = reference.generatedUrl
399
484
  return specifier
400
485
  },
401
- load: (finalUrlInfo) => {
402
- const rawUrl = finalUrlInfo.data.rawUrl
403
- const bundleUrlInfo = bundleUrlInfos[rawUrl]
404
- const urlInfo = bundleUrlInfo || rawGraph.getUrlInfo(rawUrl)
405
- return {
406
- data: bundleUrlInfo ? bundleUrlInfo.data : undefined,
407
- originalContent: urlInfo.originalContent,
408
- contentType: urlInfo.contentType,
409
- content: urlInfo.content,
410
- sourcemap: urlInfo.sourcemap,
486
+ fetchUrlContent: async (finalUrlInfo, context) => {
487
+ if (!finalUrlInfo.url.startsWith("file:")) {
488
+ return { external: true }
411
489
  }
412
- },
413
- transform: {
414
- html: (urlInfo) => {
415
- const htmlAst = parseHtmlString(urlInfo.content, {
416
- storeOriginalPositions: false,
417
- })
418
- return {
419
- content: stringifyHtmlAst(htmlAst, {
420
- removeOriginalPositionAttributes: true,
421
- }),
490
+ const fromBundleOrRawGraph = (url) => {
491
+ const bundleUrlInfo = bundleUrlInfos[url]
492
+ if (bundleUrlInfo) {
493
+ return bundleUrlInfo
422
494
  }
423
- },
495
+ const rawUrl = rawUrls[url] || url
496
+ const rawUrlInfo = rawGraph.getUrlInfo(rawUrl)
497
+ if (!rawUrlInfo) {
498
+ const originalBuildUrl = buildUrlRedirections[url]
499
+ if (originalBuildUrl) {
500
+ return fromBundleOrRawGraph(originalBuildUrl)
501
+ }
502
+ throw new Error(`Cannot find url`)
503
+ }
504
+ if (rawUrlInfo.isInline) {
505
+ // Inline content, such as <script> inside html, is transformed during the previous phase.
506
+ // If we read the inline content it would be considered as the original content.
507
+ // - It could be "fixed" by taking into account sourcemap and consider sourcemap sources
508
+ // as the original content.
509
+ // - But it would not work when sourcemap are not generated
510
+ // - would be a bit slower
511
+ // - So instead of reading the inline content directly, we search into raw graph
512
+ // to get "originalContent" and "sourcemap"
513
+ finalUrlInfo.type = rawUrlInfo.type
514
+ finalUrlInfo.subtype = rawUrlInfo.subtype
515
+ return rawUrlInfo
516
+ }
517
+ return rawUrlInfo
518
+ }
519
+ // reference injected during "postbuild":
520
+ // - happens for "as_js_classic" injecting "s.js"
521
+ if (context.reference.injected) {
522
+ const [ref, rawUrlInfo] = rawGraphKitchen.injectReference({
523
+ type: context.reference.type,
524
+ expectedType: context.reference.expectedType,
525
+ expectedSubtype: context.reference.expectedSubtype,
526
+ parentUrl: rawUrls[context.reference.parentUrl],
527
+ specifier: context.reference.specifier,
528
+ injected: true,
529
+ })
530
+ await rawGraphKitchen.cook({
531
+ reference: ref,
532
+ urlInfo: rawUrlInfo,
533
+ })
534
+ return rawUrlInfo
535
+ }
536
+ // reference updated during "postbuild":
537
+ // - happens for "as_js_classic"
538
+ if (context.reference.original) {
539
+ return fromBundleOrRawGraph(context.reference.original.url)
540
+ }
541
+ return fromBundleOrRawGraph(finalUrlInfo.url)
424
542
  },
425
543
  },
426
544
  {
427
545
  name: "jsenv:optimize",
428
546
  appliesDuring: { build: true },
429
- transform: async (urlInfo, context) => {
430
- if (optimizeHooks.length) {
547
+ finalizeUrlContent: async (urlInfo, context) => {
548
+ if (optimizeUrlContentHooks.length) {
431
549
  await rawGraphKitchen.pluginController.callAsyncHooks(
432
- "optimize",
550
+ "optimizeUrlContent",
433
551
  urlInfo,
434
552
  context,
435
553
  async (optimizeReturnValue) => {
@@ -443,17 +561,24 @@ ${Object.keys(rawGraph.urlInfos).join("\n")}`,
443
561
  },
444
562
  },
445
563
  ],
446
- scenario: "build",
447
- sourcemaps,
448
564
  })
449
565
  const buildTask = createTaskLog(logger, "build")
566
+ const postBuildEntryUrls = []
450
567
  try {
451
568
  await loadUrlGraph({
452
569
  urlGraph: finalGraph,
453
570
  kitchen: finalGraphKitchen,
454
571
  outDirectoryUrl: new URL(".jsenv/postbuild/", rootDirectoryUrl),
455
- runtimeSupport,
456
- startLoading: loadEntryFiles,
572
+ startLoading: (cookEntryFile) => {
573
+ entryUrls.forEach((entryUrl) => {
574
+ const [, postBuildEntryUrlInfo] = cookEntryFile({
575
+ trace: `entryPoint`,
576
+ type: "entry_point",
577
+ specifier: entryUrl,
578
+ })
579
+ postBuildEntryUrls.push(postBuildEntryUrlInfo.url)
580
+ })
581
+ },
457
582
  })
458
583
  } catch (e) {
459
584
  buildTask.fail()
@@ -465,217 +590,105 @@ ${Object.keys(rawGraph.urlInfos).join("\n")}`,
465
590
  `graph urls pre-versioning:
466
591
  ${Object.keys(finalGraph.urlInfos).join("\n")}`,
467
592
  )
468
- if (versioning !== "none") {
469
- const versioningTask = createTaskLog(logger, "inject version in urls")
470
- try {
471
- const urlsSorted = sortUrlGraphByDependencies(finalGraph)
472
- urlsSorted.forEach((url) => {
473
- if (url.startsWith("data:")) {
474
- return
475
- }
476
- const urlInfo = finalGraph.getUrlInfo(url)
477
- if (urlInfo.type === "sourcemap") {
478
- return
479
- }
480
- if (urlInfo.isInline) {
481
- return
482
- }
483
- const urlVersionGenerator = createUrlVersionGenerator()
484
- urlVersionGenerator.augmentWithContent({
485
- content: urlInfo.content,
486
- contentType: urlInfo.contentType,
487
- lineBreakNormalization,
488
- })
489
- urlInfo.dependencies.forEach((dependencyUrl) => {
490
- const dependencyUrlInfo = finalGraph.getUrlInfo(dependencyUrl)
491
- if (dependencyUrlInfo.isInline) {
492
- // this content is part of the file, no need to take into account twice
493
- return
494
- }
495
- if (dependencyUrlInfo.data.version) {
496
- urlVersionGenerator.augmentWithDependencyVersion(
497
- dependencyUrlInfo.data.version,
498
- )
499
- } else {
500
- // because all dependencies are know, if the dependency has no version
501
- // it means there is a circular dependency between this file
502
- // and it's dependency
503
- // in that case we'll use the dependency content
504
- urlVersionGenerator.augmentWithContent({
505
- content: dependencyUrlInfo.content,
506
- contentType: dependencyUrlInfo.contentType,
507
- lineBreakNormalization,
508
- })
509
- }
510
- })
511
- urlInfo.data.version = urlVersionGenerator.generate()
512
- urlInfo.data.versionedUrl = injectVersionIntoBuildUrl({
513
- buildUrl: urlInfo.url,
514
- version: urlInfo.data.version,
515
- versioning,
516
- })
517
- })
518
- const versionMappings = {}
519
- const usedVersionMappings = []
520
- const versioningKitchen = createKitchen({
521
- logger,
522
- rootDirectoryUrl: buildDirectoryUrl,
523
- urlGraph: finalGraph,
524
- loadInlineUrlInfos: (versionedUrlInfo) => {
525
- const rawUrlInfo = rawGraph.getUrlInfo(versionedUrlInfo.data.rawUrl)
526
- const finalUrlInfo = finalGraph.getUrlInfo(versionedUrlInfo.url)
527
- return {
528
- originalContent: rawUrlInfo
529
- ? rawUrlInfo.originalContent
530
- : undefined,
531
- sourcemap: finalUrlInfo ? finalUrlInfo.sourcemap : undefined,
532
- contentType: versionedUrlInfo.contentType,
533
- content: versionedUrlInfo.content,
534
- }
535
- },
536
- plugins: [
537
- jsenvPluginInline({
538
- allowEscapeForVersioning: true,
539
- }),
540
- {
541
- name: "jsenv:versioning",
542
- appliesDuring: { build: true },
543
- resolve: ({ parentUrl, specifier }) => {
544
- const buildUrl = buildUrls[specifier]
545
- if (buildUrl) {
546
- return buildUrl
547
- }
548
- const url = new URL(specifier, parentUrl).href
549
- return url
550
- },
551
- formatReferencedUrl: (reference) => {
552
- if (reference.isInline) {
553
- return null
554
- }
555
- // specifier comes from "normalize" hook done a bit earlier in this file
556
- // we want to get back their build url to access their infos
557
- const referencedUrlInfo = finalGraph.getUrlInfo(reference.url)
558
- if (referencedUrlInfo.data.isEntryPoint) {
559
- return reference.specifier
560
- }
561
- // data:* urls and so on
562
- if (!referencedUrlInfo.url.startsWith("file:")) {
563
- return null
564
- }
565
- const versionedUrl = referencedUrlInfo.data.versionedUrl
566
- if (!versionedUrl) {
567
- // happens for sourcemap
568
- return `${baseUrl}${urlToRelativeUrl(
569
- referencedUrlInfo.url,
570
- buildDirectoryUrl,
571
- )}`
572
- }
573
- const versionedSpecifier = `${baseUrl}${urlToRelativeUrl(
574
- versionedUrl,
575
- buildDirectoryUrl,
576
- )}`
577
- versionMappings[reference.specifier] = versionedSpecifier
578
- const parentUrlInfo = finalGraph.getUrlInfo(reference.parentUrl)
579
- if (parentUrlInfo.jsQuote) {
580
- // the url is inline inside js quotes
581
- usedVersionMappings.push(reference.specifier)
582
- return () =>
583
- `${parentUrlInfo.jsQuote}+__v__(${JSON.stringify(
584
- reference.specifier,
585
- )})+${parentUrlInfo.jsQuote}`
586
- }
587
- if (
588
- reference.type === "js_import_meta_url_pattern" ||
589
- reference.subtype === "import_dynamic"
590
- ) {
591
- usedVersionMappings.push(reference.specifier)
592
- return () => `__v__(${JSON.stringify(reference.specifier)})`
593
- }
594
- return versionedSpecifier
595
- },
596
- load: ({ url }) => {
597
- const urlInfo = finalGraph.getUrlInfo(url)
598
- return {
599
- originalContent: urlInfo.originalContent,
600
- contentType: urlInfo.contentType,
601
- content: urlInfo.content,
602
- sourcemap: urlInfo.sourcemap,
603
- }
604
- },
605
- },
606
- ],
607
- scenario: "build",
608
- sourcemaps,
609
- })
610
- // arrange state before reloading all files
611
- Object.keys(finalGraph.urlInfos).forEach((url) => {
612
- const urlInfo = finalGraph.urlInfos[url]
613
- urlInfo.data.promise = null
614
- })
615
- await loadUrlGraph({
616
- urlGraph: finalGraph,
617
- kitchen: versioningKitchen,
618
- runtimeSupport,
619
- startLoading: loadEntryFiles,
620
- })
621
- if (usedVersionMappings.length) {
622
- const versionMappingsNeeded = {}
623
- usedVersionMappings.forEach((specifier) => {
624
- versionMappingsNeeded[specifier] = versionMappings[specifier]
625
- })
626
- await Promise.all(
627
- Object.keys(finalGraph.urlInfos).map(async (buildUrl) => {
628
- const buildUrlInfo = finalGraph.getUrlInfo(buildUrl)
629
- if (!buildUrlInfo.data.isEntryPoint) {
630
- return
631
- }
632
- await injectVersionMappings(buildUrlInfo, {
633
- kitchen: finalGraphKitchen,
634
- versionMappings: versionMappingsNeeded,
635
- })
636
- }),
637
- )
638
- }
639
- } catch (e) {
640
- versioningTask.fail()
641
- throw e
642
- }
643
- versioningTask.done()
593
+ if (versioning) {
594
+ await applyUrlVersioning({
595
+ logger,
596
+ buildDirectoryUrl,
597
+ rawUrls,
598
+ buildUrls,
599
+ baseUrl,
600
+ postBuildEntryUrls,
601
+ sourcemaps,
602
+ runtimeCompat,
603
+ rawGraph,
604
+ finalGraph,
605
+ finalGraphKitchen,
606
+ lineBreakNormalization,
607
+ versioningMethod,
608
+ })
644
609
  }
645
-
646
- const buildFileContents = {}
647
- const buildInlineFileContents = {}
648
- const buildManifest = {}
649
- Object.keys(finalGraph.urlInfos).forEach((url) => {
650
- if (!url.startsWith("file:")) {
610
+ GRAPH.forEach(finalGraph, (urlInfo) => {
611
+ if (!urlInfo.url.startsWith("file:")) {
651
612
  return
652
613
  }
653
- const buildUrlInfo = finalGraph.getUrlInfo(url)
654
- const versionedUrl = buildUrlInfo.data.versionedUrl
655
- const useVersionedUrl = versionedUrl && !buildUrlInfo.data.isEntryPoint
656
- const buildUrl = useVersionedUrl ? versionedUrl : buildUrlInfo.url
657
- if (!urlIsInsideOf(buildUrl, buildDirectoryUrl)) {
658
- throw new Error(`build url outside build directory`)
614
+ if (urlInfo.external) {
615
+ return
659
616
  }
660
- const buildRelativeUrl = urlToRelativeUrl(buildUrl, buildDirectoryUrl)
661
- if (buildUrlInfo.isInline) {
662
- buildInlineFileContents[buildRelativeUrl] = buildUrlInfo.content
663
- } else {
664
- buildFileContents[buildRelativeUrl] = buildUrlInfo.content
617
+ if (urlInfo.type === "html") {
618
+ const htmlAst = parseHtmlString(urlInfo.content, {
619
+ storeOriginalPositions: false,
620
+ })
621
+ urlInfo.content = stringifyHtmlAst(htmlAst, {
622
+ removeOriginalPositionAttributes: true,
623
+ })
665
624
  }
666
- if (useVersionedUrl) {
667
- const buildRelativeUrlWithoutVersioning = urlToRelativeUrl(
668
- buildUrlInfo.url,
669
- buildDirectoryUrl,
670
- )
671
- buildManifest[buildRelativeUrlWithoutVersioning] = buildRelativeUrl
625
+ const version = urlInfo.data.version
626
+ const useVersionedUrl = version && canUseVersionedUrl(urlInfo, finalGraph)
627
+ const buildUrl = useVersionedUrl ? urlInfo.data.versionedUrl : urlInfo.url
628
+ const buildUrlSpecifier = Object.keys(buildUrls).find(
629
+ (key) => buildUrls[key] === buildUrl,
630
+ )
631
+ urlInfo.data.buildUrl = buildUrl
632
+ urlInfo.data.buildUrlIsVersioned = useVersionedUrl
633
+ urlInfo.data.buildUrlSpecifier = buildUrlSpecifier
634
+ })
635
+ await resyncRessourceHints({
636
+ finalGraphKitchen,
637
+ finalGraph,
638
+ rawUrls,
639
+ buildUrls,
640
+ })
641
+ const cleanupActions = []
642
+ GRAPH.forEach(finalGraph, (urlInfo) => {
643
+ // nothing uses this url anymore
644
+ // - versioning update inline content
645
+ // - file converted for import assertion of js_classic conversion
646
+ if (
647
+ !urlInfo.data.isEntryPoint &&
648
+ urlInfo.type !== "sourcemap" &&
649
+ urlInfo.dependents.size === 0
650
+ ) {
651
+ cleanupActions.push(() => {
652
+ delete finalGraph.urlInfos[urlInfo.url]
653
+ })
672
654
  }
673
655
  })
656
+ cleanupActions.forEach((cleanupAction) => cleanupAction())
657
+ await injectServiceWorkerUrls({
658
+ finalGraphKitchen,
659
+ finalGraph,
660
+ lineBreakNormalization,
661
+ })
674
662
  logger.debug(
675
663
  `graph urls post-versioning:
676
664
  ${Object.keys(finalGraph.urlInfos).join("\n")}`,
677
665
  )
678
666
 
667
+ const buildManifest = {}
668
+ const buildFileContents = {}
669
+ const buildInlineContents = {}
670
+ GRAPH.forEach(finalGraph, (urlInfo) => {
671
+ if (urlInfo.external) {
672
+ return
673
+ }
674
+ if (urlInfo.url.startsWith("data:")) {
675
+ return
676
+ }
677
+ const buildRelativeUrl = urlToRelativeUrl(
678
+ urlInfo.data.buildUrl,
679
+ buildDirectoryUrl,
680
+ )
681
+ if (urlInfo.isInline) {
682
+ buildInlineContents[buildRelativeUrl] = urlInfo.content
683
+ } else {
684
+ buildFileContents[buildRelativeUrl] = urlInfo.content
685
+ }
686
+ const buildRelativeUrlWithoutVersioning = urlToRelativeUrl(
687
+ urlInfo.url,
688
+ buildDirectoryUrl,
689
+ )
690
+ buildManifest[buildRelativeUrlWithoutVersioning] = buildRelativeUrl
691
+ })
679
692
  if (writeOnFileSystem) {
680
693
  if (buildDirectoryClean) {
681
694
  await ensureEmptyDirectory(buildDirectoryUrl)
@@ -689,17 +702,252 @@ ${Object.keys(finalGraph.urlInfos).join("\n")}`,
689
702
  )
690
703
  }),
691
704
  )
705
+ if (versioning && assetManifest && Object.keys(buildManifest).length) {
706
+ await writeFile(
707
+ new URL(assetManifestFileRelativeUrl, buildDirectoryUrl),
708
+ JSON.stringify(buildManifest, null, " "),
709
+ )
710
+ }
692
711
  }
693
712
  logger.info(createUrlGraphSummary(finalGraph, { title: "build files" }))
694
713
  return {
695
714
  buildFileContents,
696
- buildInlineFileContents,
715
+ buildInlineContents,
697
716
  buildManifest,
698
717
  }
699
718
  }
700
719
 
701
- const injectVersionIntoBuildUrl = ({ buildUrl, version, versioning }) => {
702
- if (versioning === "search_param") {
720
+ const applyUrlVersioning = async ({
721
+ logger,
722
+ buildDirectoryUrl,
723
+ rawUrls,
724
+ buildUrls,
725
+ baseUrl,
726
+ postBuildEntryUrls,
727
+ sourcemaps,
728
+ runtimeCompat,
729
+ rawGraph,
730
+ finalGraph,
731
+ finalGraphKitchen,
732
+ lineBreakNormalization,
733
+ versioningMethod,
734
+ }) => {
735
+ const versioningTask = createTaskLog(logger, "inject version in urls")
736
+ try {
737
+ const urlsSorted = sortUrlGraphByDependencies(finalGraph)
738
+ urlsSorted.forEach((url) => {
739
+ if (url.startsWith("data:")) {
740
+ return
741
+ }
742
+ const urlInfo = finalGraph.getUrlInfo(url)
743
+ if (urlInfo.type === "sourcemap") {
744
+ return
745
+ }
746
+ // ignore:
747
+ // - inline files:
748
+ // they are already taken into account in the file where they appear
749
+ // - external files
750
+ // we don't know their content
751
+ // - unused files without reference
752
+ // File updated such as style.css -> style.css.js or file.js->file.es5.js
753
+ // Are used at some point just to be discarded later because they need to be converted
754
+ // There is no need to version them and we could not because the file have been ignored
755
+ // so their content is unknown
756
+ if (urlInfo.isInline) {
757
+ return
758
+ }
759
+ if (urlInfo.external) {
760
+ return
761
+ }
762
+ if (!urlInfo.data.isEntryPoint && urlInfo.dependents.size === 0) {
763
+ return
764
+ }
765
+
766
+ const urlContent =
767
+ urlInfo.type === "html"
768
+ ? stringifyHtmlAst(
769
+ parseHtmlString(urlInfo.content, {
770
+ storeOriginalPositions: false,
771
+ }),
772
+ { removeOriginalPositionAttributes: true },
773
+ )
774
+ : urlInfo.content
775
+ const versionGenerator = createVersionGenerator()
776
+ versionGenerator.augmentWithContent({
777
+ content: urlContent,
778
+ contentType: urlInfo.contentType,
779
+ lineBreakNormalization,
780
+ })
781
+ urlInfo.dependencies.forEach((dependencyUrl) => {
782
+ // this dependency is inline (data:) or remote (http://, https://)
783
+ if (!dependencyUrl.startsWith("file:")) {
784
+ return
785
+ }
786
+ const dependencyUrlInfo = finalGraph.getUrlInfo(dependencyUrl)
787
+ if (
788
+ // this content is part of the file, no need to take into account twice
789
+ dependencyUrlInfo.isInline ||
790
+ // this dependency content is not known
791
+ dependencyUrlInfo.external
792
+ ) {
793
+ return
794
+ }
795
+ if (dependencyUrlInfo.data.version) {
796
+ versionGenerator.augmentWithDependencyVersion(
797
+ dependencyUrlInfo.data.version,
798
+ )
799
+ } else {
800
+ // because all dependencies are know, if the dependency has no version
801
+ // it means there is a circular dependency between this file
802
+ // and it's dependency
803
+ // in that case we'll use the dependency content
804
+ versionGenerator.augmentWithContent({
805
+ content: dependencyUrlInfo.content,
806
+ contentType: dependencyUrlInfo.contentType,
807
+ lineBreakNormalization,
808
+ })
809
+ }
810
+ })
811
+ urlInfo.data.version = versionGenerator.generate()
812
+
813
+ urlInfo.data.versionedUrl = injectVersionIntoBuildUrl({
814
+ buildUrl: urlInfo.url,
815
+ version: urlInfo.data.version,
816
+ versioningMethod,
817
+ })
818
+ })
819
+ const versionMappings = {}
820
+ const usedVersionMappings = []
821
+ const versioningKitchen = createKitchen({
822
+ logger,
823
+ rootDirectoryUrl: buildDirectoryUrl,
824
+ urlGraph: finalGraph,
825
+ scenario: "build",
826
+ sourcemaps,
827
+ runtimeCompat,
828
+ plugins: [
829
+ jsenvPluginInline({
830
+ fetchInlineUrls: false,
831
+ analyzeConvertedScripts: true, // to be able to version their urls
832
+ allowEscapeForVersioning: true,
833
+ }),
834
+ {
835
+ name: "jsenv:versioning",
836
+ appliesDuring: { build: true },
837
+ resolveUrl: (reference) => {
838
+ if (reference.specifier[0] === "#") {
839
+ reference.external = true
840
+ }
841
+ const buildUrl = buildUrls[reference.specifier]
842
+ if (buildUrl) {
843
+ return buildUrl
844
+ }
845
+ const url = new URL(reference.specifier, reference.parentUrl).href
846
+ return url
847
+ },
848
+ formatUrl: (reference) => {
849
+ if (reference.isInline) {
850
+ return null
851
+ }
852
+ // specifier comes from "normalize" hook done a bit earlier in this file
853
+ // we want to get back their build url to access their infos
854
+ const referencedUrlInfo = finalGraph.getUrlInfo(reference.url)
855
+ if (!canUseVersionedUrl(referencedUrlInfo)) {
856
+ return reference.specifier
857
+ }
858
+ // data:* urls and so on
859
+ if (!referencedUrlInfo.url.startsWith("file:")) {
860
+ return null
861
+ }
862
+ const versionedUrl = referencedUrlInfo.data.versionedUrl
863
+ if (!versionedUrl) {
864
+ // happens for sourcemap
865
+ return `${baseUrl}${urlToRelativeUrl(
866
+ referencedUrlInfo.url,
867
+ buildDirectoryUrl,
868
+ )}`
869
+ }
870
+ const versionedSpecifier = `${baseUrl}${urlToRelativeUrl(
871
+ versionedUrl,
872
+ buildDirectoryUrl,
873
+ )}`
874
+ versionMappings[reference.specifier] = versionedSpecifier
875
+ buildUrls[versionedSpecifier] = versionedUrl
876
+
877
+ const parentUrlInfo = finalGraph.getUrlInfo(reference.parentUrl)
878
+ if (parentUrlInfo.jsQuote) {
879
+ // the url is inline inside js quotes
880
+ usedVersionMappings.push(reference.specifier)
881
+ return () =>
882
+ `${parentUrlInfo.jsQuote}+__v__(${JSON.stringify(
883
+ reference.specifier,
884
+ )})+${parentUrlInfo.jsQuote}`
885
+ }
886
+ if (
887
+ reference.type === "js_url_specifier" ||
888
+ reference.subtype === "import_dynamic"
889
+ ) {
890
+ usedVersionMappings.push(reference.specifier)
891
+ return () => `__v__(${JSON.stringify(reference.specifier)})`
892
+ }
893
+ return versionedSpecifier
894
+ },
895
+ fetchUrlContent: (versionedUrlInfo) => {
896
+ if (!versionedUrlInfo.url.startsWith("file:")) {
897
+ return { external: true }
898
+ }
899
+ if (versionedUrlInfo.isInline) {
900
+ const rawUrlInfo = rawGraph.getUrlInfo(
901
+ rawUrls[versionedUrlInfo.url],
902
+ )
903
+ const finalUrlInfo = finalGraph.getUrlInfo(versionedUrlInfo.url)
904
+ return {
905
+ originalContent: rawUrlInfo
906
+ ? rawUrlInfo.originalContent
907
+ : undefined,
908
+ sourcemap: finalUrlInfo ? finalUrlInfo.sourcemap : undefined,
909
+ contentType: versionedUrlInfo.contentType,
910
+ content: versionedUrlInfo.content,
911
+ }
912
+ }
913
+ return versionedUrlInfo
914
+ },
915
+ },
916
+ ],
917
+ })
918
+ await loadUrlGraph({
919
+ urlGraph: finalGraph,
920
+ kitchen: versioningKitchen,
921
+ startLoading: (cookEntryFile) => {
922
+ postBuildEntryUrls.forEach((postBuildEntryUrl) => {
923
+ cookEntryFile({
924
+ trace: `entryPoint`,
925
+ type: "entry_point",
926
+ specifier: postBuildEntryUrl,
927
+ })
928
+ })
929
+ },
930
+ })
931
+ if (usedVersionMappings.length) {
932
+ const versionMappingsNeeded = {}
933
+ usedVersionMappings.forEach((specifier) => {
934
+ versionMappingsNeeded[specifier] = versionMappings[specifier]
935
+ })
936
+ await injectGlobalVersionMapping({
937
+ finalGraphKitchen,
938
+ finalGraph,
939
+ versionMappings: versionMappingsNeeded,
940
+ })
941
+ }
942
+ } catch (e) {
943
+ versioningTask.fail()
944
+ throw e
945
+ }
946
+ versioningTask.done()
947
+ }
948
+
949
+ const injectVersionIntoBuildUrl = ({ buildUrl, version, versioningMethod }) => {
950
+ if (versioningMethod === "search_param") {
703
951
  return injectQueryParams(buildUrl, {
704
952
  v: version,
705
953
  })
@@ -735,3 +983,16 @@ const assertEntryPoints = ({ entryPoints }) => {
735
983
  }
736
984
  })
737
985
  }
986
+
987
+ const canUseVersionedUrl = (urlInfo) => {
988
+ if (urlInfo.data.isEntryPoint) {
989
+ return false
990
+ }
991
+ if (urlInfo.type === "webmanifest") {
992
+ return false
993
+ }
994
+ if (urlInfo.subtype === "service_worker") {
995
+ return !urlInfo.data.isWebWorkerEntryPoint
996
+ }
997
+ return true
998
+ }