es-module-shims 2.5.1 → 2.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -14,6 +14,7 @@ The following modules features are polyfilled:
14
14
  * [Import defer](#import-defer) via syntax stripping to allow usage in modern browsers with a polyfill fallback, when enabled.
15
15
  * [TypeScript](#typescript-type-stripping) type stripping.
16
16
  * [Hot Reloading](#hot-reloading) with a Vite-style `import.meta.hot` API.
17
+ * [Loader Hooks](#hooks) custom loader hooks for customizing module resolution and sources, including support for [virtual module sources](#source-hook).
17
18
 
18
19
  When running in shim mode, module rewriting is applied for all users and custom [resolve](#resolve-hook) and [fetch](#fetch-hook) hooks can be implemented allowing for custom resolution and streaming in-browser transform workflows.
19
20
 
@@ -30,7 +31,7 @@ Because we are still using the native module loader the edge cases work out comp
30
31
  Include ES Module Shims with a `async` attribute on the script, then include an import map and module scripts normally:
31
32
 
32
33
  ```html
33
- <script async src="https://ga.jspm.io/npm:es-module-shims@2.5.1/dist/es-module-shims.js"></script>
34
+ <script async src="https://ga.jspm.io/npm:es-module-shims@2.6.1/dist/es-module-shims.js"></script>
34
35
 
35
36
  <!-- https://generator.jspm.io/#U2NhYGBkDM0rySzJSU1hKEpNTC5xMLTQM9Az0C1K1jMAAKFS5w0gAA -->
36
37
  <script type="importmap">
@@ -215,7 +216,7 @@ Shim mode is an alternative to polyfill mode and doesn't rely on native modules
215
216
 
216
217
  In shim mode, only the above `importmap-shim` and `module-shim` tags will be parsed and executed by ES Module Shims.
217
218
 
218
- Shim mode also provides some additional features that aren't yet natively supported such as supporting multiple import maps, [external import maps](#external-import-maps) with a `"src"` attribute, [dynamically injecting import maps](#dynamic-import-maps), and [reading current import map state](#reading-current-import-map-state), which can be useful in certain applications.
219
+ Shim mode also provides some additional features that aren't yet natively supported such as [external import maps](#external-import-maps) with a `"src"` attribute and [reading current import map state](#reading-current-import-map-state), which can be useful in certain applications.
219
220
 
220
221
  ## Benchmarks
221
222
 
@@ -231,7 +232,7 @@ Benchmark summary:
231
232
 
232
233
  ### Browser Support
233
234
 
234
- Works in all browsers with [baseline ES module support](https://caniuse.com/#feat=es6-module).
235
+ Works in all browsers with [ES module dynamic import support](https://caniuse.com/es6-module-dynamic-import).
235
236
 
236
237
  Browser Compatibility on baseline ES modules support **with** ES Module Shims:
237
238
 
@@ -252,8 +253,8 @@ Browser compatibility **without** ES Module Shims:
252
253
  | --------------------------------------------- | ------------------ | ------------------ | ------------------ |
253
254
  | [modulepreload](#modulepreload) | 66+ | 115+ | 17.5+ |
254
255
  | [Import Maps](#import-maps) | 89+ | 108+ | 16.4+ |
255
- | [Import Map Integrity](#import-map-integrity) | 127+ | :x: | :x: |
256
- | [Multiple Import Maps](#multiple-import-maps) | 135+ | :x: | :x: |
256
+ | [Import Map Integrity](#import-map-integrity) | 127+ | 138+ | 18+ |
257
+ | [Multiple Import Maps](#multiple-import-maps) | 135+ | :x: | 18.4+ |
257
258
  | [JSON Modules](#json-modules) | 123+ | :x: | 17.2+ |
258
259
  | [CSS Modules](#css-modules) | 123+ | :x: | :x: |
259
260
  | [Wasm Modules](#wasm-modules) | Pending | :x: | :x: |
@@ -686,7 +687,8 @@ const worker = new Worker(getWorkerScriptURL('myEsModule.js'));
686
687
 
687
688
  Provide a `esmsInitOptions` on the global scope before `es-module-shims` is loaded to configure various aspects of the module loading process:
688
689
 
689
- * [polyfillEnable](#polyfill-enable)
690
+ * [polyfillEnable](#polyfill-enable-option)
691
+ * [polyfillDisable](#polyfill-disable-option)
690
692
  * [enforceIntegrity](#enforce-integrity)
691
693
  * [fetch](#fetch-hook)
692
694
  * [mapOverrides](#overriding-import-map-entries)
@@ -697,7 +699,7 @@ Provide a `esmsInitOptions` on the global scope before `es-module-shims` is load
697
699
  * [onerror](#error-hook)
698
700
  * [onpolyfill](#polyfill-hook)
699
701
  * [resolve](#resolve-hook)
700
- * [revokeBlobURLs](#revoke-blob-urls)
702
+ * [source](#source-hook)
701
703
  * [shimMode](#shim-mode-option)
702
704
  * [skip](#skip)
703
705
  * [version](#version)
@@ -709,14 +711,14 @@ window.esmsInitOptions = {
709
711
  shimMode: true, // default false
710
712
  // Enable newer modules features
711
713
  polyfillEnable: ['wasm-module-sources'], // default empty
714
+ // Disable features that are unused
715
+ polyfillDisable: ['css-modules'], // default empty
712
716
  // Custom CSP nonce
713
717
  nonce: 'n0nce', // default is automatic detection
714
718
  // Don't retrigger load events on module scripts (DOMContentLoaded, domready, window 'onload')
715
719
  noLoadEventRetriggers: true, // default false
716
720
  // Skip source analysis of certain URLs for full native passthrough
717
721
  skip: /^https:\/\/cdn\.com/, // defaults to null
718
- // Clean up blob URLs after execution
719
- revokeBlobURLs: true, // default false
720
722
  // Secure mode to not support loading modules without integrity
721
723
  // (integrity is always verified even when disabled though)
722
724
  enforceIntegrity: true, // default false
@@ -733,6 +735,8 @@ window.esmsInitOptions = {
733
735
  onpolyfill: () => {}, // default logs to the console
734
736
  // Hook all module resolutions
735
737
  resolve: (id, parentUrl, resolve) => resolve(id, parentUrl), // default is spec resolution
738
+ // Hook module source loading
739
+ source: (url, options, parentUrl, defaultSourceHook) => ({ type: 'js', source: 'export var p = 5' }),
736
740
  // Hook source fetch function
737
741
  fetch: (url, options) => fetch(url, options), // default is native
738
742
  // Hook import.meta construction
@@ -793,15 +797,27 @@ In adddition, the `"all"` option will enable all features.
793
797
  </script>
794
798
  ```
795
799
 
796
- The above is necessary to enable CSS modules and JSON modules alongside TypeScript type stripping support.
800
+ The reason the `polyfillEnable` option is needed is because ES Module Shims implements a performance optimization where if a browser supports modern modules features to an expected baseline of import maps support, it will skip all polyfill source analysis resulting in full native passthrough performance.
797
801
 
798
- #### Baseline Support Analysis Opt-Out
802
+ ### Pollyfill Disable Option
799
803
 
800
- The reason the `polyfillEnable` option is needed is because ES Module Shims implements a performance optimization where if a browser supports modern modules features to an expected baseline of import maps support, it will skip all polyfill source analysis resulting in full native passthrough performance.
804
+ Conversely to `polyfillEnable` it can be beneficial to dissable unused features where excluding those features from the baseline allows avoiding unnecessary feature detections or unnecessary analysis of module graphs.
805
+
806
+ This option effectively lowers the baseline support allowing wider passthrough cases.
801
807
 
802
- If the application code then tries to use modern features like CSS modules beyond this baseline it won't support those features. As a result all modules features which are considered newer or beyond the recommended baseline require explicit enabling. This common baseline itself will change to track the common future modules baseline supported by this project for each release cycle.
808
+ The supported options currently are just `css-modules` and `json-modules`.
809
+
810
+ For example:
811
+
812
+ ```html
813
+ <script type="esms-options">
814
+ {
815
+ "polyfillDisable": ["css-modules", "json-modules"]
816
+ }
817
+ </script>
818
+ ```
803
819
 
804
- This option can also be set to `true` to entirely disable the native passthrough system and ensure all sources are fetched and analyzed through ES Module Shims. This will still avoid duplicate execution since module graphs are still only reexecuted when they use unsupported native features, but there is a small extra cost in doing the analysis.
820
+ will disable the CSS and JSON feature detections, and lower the baseline passthrough modules support from Chrome 123, Firefox 138 and Safari 17.2 down to Chrome 64, Safari 11.1 and Firefox 67.
805
821
 
806
822
  ### Enforce Integrity
807
823
 
@@ -988,6 +1004,8 @@ Overriding this hook with an empty function will disable the default polyfill lo
988
1004
 
989
1005
  In the above, running in latest Chromium browsers, nothing will be logged, while running in an older browser that does not support newer features like import maps the console log will be output.
990
1006
 
1007
+ > As this hook does not affect execution, it is recommended for use in polyfill mode.
1008
+
991
1009
  #### Error hook
992
1010
 
993
1011
  You can provide a function to handle errors during the module loading process by providing an `onerror` option:
@@ -1001,6 +1019,8 @@ You can provide a function to handle errors during the module loading process by
1001
1019
  <script async src="es-module-shims.js"></script>
1002
1020
  ```
1003
1021
 
1022
+ > As this hook does not affect execution, it is recommended for use in polyfill mode.
1023
+
1004
1024
  #### Import Hook
1005
1025
 
1006
1026
  The import hook is supported for both shim and polyfill modes and provides an async hook which can ensure any necessary work is done before a top-level module import or dynamic `import()` starts further processing.
@@ -1018,15 +1038,12 @@ The import hook is supported for both shim and polyfill modes and provides an as
1018
1038
  </script>
1019
1039
  ```
1020
1040
 
1041
+ > It is usually recommended to use shim mode with module customization hooks. When the resolve hook is enabled in polyfill mode (or any other hooks), native passthrough will be disabled and modules may be executed twice if they correctly execute without the hook.
1042
+
1021
1043
  #### Resolve Hook
1022
1044
 
1023
1045
  The resolve hook is supported for both shim and polyfill modes and allows full customization of the resolver, while still having access to the original resolve function.
1024
1046
 
1025
- Note that in polyfill mode the resolve hook may not be called for all modules when native passthrough is occurring and that it still will not affect
1026
- the native passthrough executions.
1027
-
1028
- If the resolve hook should apply for all modules in the entire module graph, make sure to set `polyfillEnable: true` to [disable the baseline support analysis opt-out](#baseline-support-analysis-opt-out).
1029
-
1030
1047
  ```js
1031
1048
  <script>
1032
1049
  window.esmsInitOptions = {
@@ -1042,6 +1059,59 @@ If the resolve hook should apply for all modules in the entire module graph, mak
1042
1059
  </script>
1043
1060
  ```
1044
1061
 
1062
+ > It is usually recommended to use shim mode with module customization hooks. When the resolve hook is enabled in polyfill mode (or any other hooks), native passthrough will be disabled and modules may be executed twice if they correctly execute without the hook.
1063
+
1064
+ #### Source Hook
1065
+
1066
+ The source hook used to obtain the module source for a given URL, allowing for the implementation
1067
+ of virtual module sources.
1068
+
1069
+ Note that only valid fetch scheme URLs are supported - `http:` / `https:` / `data:` / `blob:` / `file:`.
1070
+ `https:` or `file:` is therefore recommended for virtual module paths.
1071
+
1072
+ For example:
1073
+
1074
+ ```html
1075
+ <script>
1076
+ const virtualFs = {
1077
+ 'index.js': `import './src/dep.js';`,
1078
+ 'src/dep.js': 'console.log("virtual source execution!")'
1079
+ };
1080
+ esmsInitOptions = {
1081
+ source (url, fetchOpts, parent, defaultSourceHook) {
1082
+ // Only virtualize sources under the URL file:///virtual-pkg/ (i.e. via
1083
+ // `import 'file:///virtual-pkg/index.js'`.
1084
+ if (!url.startsWith('file:///virtual-pkg/')) return defaultSourceHook(url, fetchOpts, parent);
1085
+
1086
+ // Strip the query string prefix for hot reloading workflow support
1087
+ const versionQueryParam = url.match(/\?v=\d+$/);
1088
+ if (versionQueryParam) url = url.slice(0, -versionQueryParam[0].length);
1089
+
1090
+ // Lookup the virtual source from the virtual filesystem and return if found
1091
+ const virtualSource = virtualFs[url.slice('file:///virtual-pkg/'.length)];
1092
+ if (!virtualSource) throw new Error(`Virtual module ${url} not found, imported from ${parent}`);
1093
+ return {
1094
+ type: 'js',
1095
+ source: virtualSource
1096
+ };
1097
+ }
1098
+ };
1099
+ </script>
1100
+ ```
1101
+
1102
+ For support in hot reloading workflows, note that the ?v={Number} version query
1103
+ string suffix will be passed so needs to be checked and removed if applicable.
1104
+
1105
+ For JS, CSS, JSON and TypeScript, it provides the source text string.
1106
+ For WebAssembly, it provides the compiled WebAssembly.Module record.
1107
+
1108
+ The default implementation uses globalThis.fetch to obtain the response and then
1109
+ the 'content-type' MIME type header to infer the module type, per HTML semantics.
1110
+
1111
+ URL may be returned differently from the request URL because responseURL
1112
+ is allowed to be distinct from requestURL in the module system even thoough
1113
+ requestURL is used as the registry key only.
1114
+
1045
1115
  #### Meta Hook
1046
1116
 
1047
1117
  The meta hook allows customizing the `import.meta` object in each module scope.
@@ -1068,6 +1138,8 @@ import assert from 'assert';
1068
1138
  assert.ok(import.meta.custom.startsWith('custom value'));
1069
1139
  ```
1070
1140
 
1141
+ > It is usually recommended to use shim mode with module customization hooks. When the resolve hook is enabled in polyfill mode (or any other hooks), native passthrough will be disabled and modules may be executed twice if they correctly execute without the hook.
1142
+
1071
1143
  #### Fetch Hook
1072
1144
 
1073
1145
  The fetch hook is supported for shim mode only.
@@ -1125,6 +1197,8 @@ window.esmsInitOptions = {
1125
1197
  }
1126
1198
  ```
1127
1199
 
1200
+ > It is usually recommended to use shim mode with module customization hooks. When the resolve hook is enabled in polyfill mode (or any other hooks), native passthrough will be disabled and modules may be executed twice if they correctly execute without the hook.
1201
+
1128
1202
  ## Implementation Details
1129
1203
 
1130
1204
  ### Import Rewriting