es-module-shims 2.1.2 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -9,10 +9,11 @@ For the remaining ~4% of users, the highly performant (see [benchmarks](#benchma
9
9
  The following modules features are polyfilled:
10
10
 
11
11
  * [Import Maps](#import-maps) polyfill.
12
- * [JSON](#json-modules) and [CSS modules](#css-modules) with import assertions when enabled.
13
- * [Wasm modules](#wasm-modules) with support for Source Phase Imports when enabled.
14
- * [Import defer](#import-defer) via syntax stripping to allow usage in modern browsers with a polyfill fallback when enabled.
15
- * [TypeScript](#typescript-type-stripping) type stripping when enabled.
12
+ * [JSON](#json-modules) and [CSS modules](#css-modules) polyfill with import assertions.
13
+ * [Wasm modules](#wasm-modules) with support for Source Phase Imports, when enabled.
14
+ * [Import defer](#import-defer) via syntax stripping to allow usage in modern browsers with a polyfill fallback, when enabled.
15
+ * [TypeScript](#typescript-type-stripping) type stripping.
16
+ * [Hot Reloading](#hot-reloading) with a Vite-style `import.meta.hot` API.
16
17
 
17
18
  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.
18
19
 
@@ -29,7 +30,7 @@ Because we are still using the native module loader the edge cases work out comp
29
30
  Include ES Module Shims with a `async` attribute on the script, then include an import map and module scripts normally:
30
31
 
31
32
  ```html
32
- <script async src="https://ga.jspm.io/npm:es-module-shims@2.1.2/dist/es-module-shims.js"></script>
33
+ <script async src="https://ga.jspm.io/npm:es-module-shims@2.3.0/dist/es-module-shims.js"></script>
33
34
 
34
35
  <!-- https://generator.jspm.io/#U2NhYGBkDM0rySzJSU1hKEpNTC5xMLTQM9Az0C1K1jMAAKFS5w0gAA -->
35
36
  <script type="importmap">
@@ -188,22 +189,20 @@ If the polyfill is analyzing or applying to a module script that doesn't need to
188
189
 
189
190
  ### Polyfill Features
190
191
 
191
- If using more modern features like CSS Modules or JSON Modules, these need to be manually enabled via the [`polyfillEnable` init option](#polyfill-enable-option) to raise the native baseline from just checking import maps to also checking that browsers support these features:
192
+ If using more modern features like [Import Defer](#import-defer) or [Wasm Modules](#wasm-modules), these need to be manually enabled via the [`polyfillEnable` init option](#polyfill-enable-option) to raise the native baseline from just checking import maps to also checking that browsers support these features:
192
193
 
193
194
  ```html
194
195
  <script>
195
- window.esmsInitOptions = { polyfillEnable: ['css-modules', 'json-modules', 'wasm-modules', 'typescript'] }
196
+ window.esmsInitOptions = { polyfillEnable: ['wasm-module-sources', 'import-defer'] }
196
197
  </script>
197
198
  ```
198
199
 
199
- The above polyfill options correspond to `polyfillEnable: 'all'`.
200
-
201
- Alternatively options can be set via the `esms-options` script type:
200
+ Alternatively options can be set via the `esms-options` script type JSON:
202
201
 
203
202
  ```html
204
203
  <script type="esms-options">
205
204
  {
206
- "polyfillEnable": "all"
205
+ "polyfillEnable": ["wasm-module-sources", "import-defer"]
207
206
  }
208
207
  </script>
209
208
  ```
@@ -224,7 +223,7 @@ ES Module Shims is designed for production performance. A [comprehensive benchma
224
223
 
225
224
  Benchmark summary:
226
225
 
227
- * [ES Module Shims Chrome Passthrough](bench/README.md#chrome-passthrough-performance) (for [94% of users](https://caniuse.com/import-maps)) results in ~5ms extra initialization time over native for ES Module Shims fetching, execution and initialization, and on a slow connection the additional non-blocking bandwidth cost of its 10KB compressed download as expected.
226
+ * [ES Module Shims Chrome Passthrough](bench/README.md#chrome-passthrough-performance) (for [94% of users](https://caniuse.com/import-maps)) results in ~5ms extra initialization time over native for ES Module Shims fetching, execution and initialization, and on a slow connection the additional non-blocking bandwidth cost of its 13KB compressed download as expected.
228
227
  * [ES Module Shims Polyfilling](bench/README.md#native-v-polyfill-performance) (for the remaining [3% of users](https://caniuse.com/import-maps)) is on average 1.4x - 1.5x slower than native module loading, and up to 1.8x slower on slow networks (most likely due to the browser preloader), both for cached and uncached loads, and this result scales linearly up to 10MB and 20k modules loaded executing on the fastest connection in just over 2 seconds in Firefox.
229
228
  * [Very large import maps](bench/README.md#large-import-maps-performance) (100s of entries) cost only a few extra milliseconds upfront for the additional loading cost.
230
229
 
@@ -254,7 +253,7 @@ Browser compatibility **without** ES Module Shims:
254
253
  | [modulepreload](#modulepreload) | 66+ | 115+ | 17.5+ |
255
254
  | [Import Maps](#import-maps) | 89+ | 108+ | 16.4+ |
256
255
  | [Import Map Integrity](#import-map-integrity) | 127+ | :x: | :x: |
257
- | [Multiple Import Maps](#multiple-import-maps) | Pending | :x: | :x: |
256
+ | [Multiple Import Maps](#multiple-import-maps) | 135+ | :x: | :x: |
258
257
  | [JSON Modules](#json-modules) | 123+ | :x: | 17.2+ |
259
258
  | [CSS Modules](#css-modules) | 123+ | :x: | :x: |
260
259
  | [Wasm Modules](#wasm-modules) | Pending | :x: | :x: |
@@ -483,11 +482,13 @@ Note integrity can only be validated when in shim mode or when the polyfill is d
483
482
 
484
483
  ### JSON Modules
485
484
 
486
- > Stability: WhatWG Standard, Single Browser Implementer
485
+ > Stability: WhatWG Standard, Stable, Multiple Browser Implementers
487
486
 
488
- In shim mode, JSON modules are always supported. In polyfill mode, JSON modules require the `polyfillEnable: ['json-modules']` [init option](#polyfill-enable-option).
487
+ JSON modules are now enabled by default in ES Module Shims with 85% browser support for native where the polyfill won't engage at all.
489
488
 
490
- JSON Modules are currently supported in Chrome when using them via an import assertion:
489
+ In shim mode, JSON modules are always supported.
490
+
491
+ JSON Modules are supported in Chrome and Safari when using them via an import assertion:
491
492
 
492
493
  ```html
493
494
  <script type="module">
@@ -501,9 +502,9 @@ In addition JSON modules need to be served with a valid JSON content type.
501
502
 
502
503
  > Stability: WhatWG Standard, Single Browser Implementer
503
504
 
504
- In shim mode, CSS modules are always supported. In polyfill mode, CSS modules require the `polyfillEnable: ['css-modules']` [init option](#polyfill-enable-option).
505
+ CSS imports are fully supported in both polyfill and shim mode with native passthrough applying in Chrome.
505
506
 
506
- CSS Modules are currently supported in Chrome when using them via an import assertion:
507
+ Use them by adding the `type: 'css'` import assertion when importing a CSS file:
507
508
 
508
509
  ```html
509
510
  <script type="module">
@@ -511,7 +512,7 @@ import sheet from 'https://site.com/sheet.css' with { type: 'css' };
511
512
  </script>
512
513
  ```
513
514
 
514
- In addition CSS modules need to be served with a valid CSS content type.
515
+ In addition CSS files need to be served with a valid CSS content type.
515
516
 
516
517
  ### Wasm Modules
517
518
 
@@ -519,13 +520,11 @@ In addition CSS modules need to be served with a valid CSS content type.
519
520
 
520
521
  Implements the [WebAssembly ESM Integration](https://github.com/WebAssembly/esm-integration) spec, including support for source phase imports.
521
522
 
522
- In shim mode, Wasm modules are always supported. In polyfill mode, Wasm modules require the `polyfillEnable: ['wasm-modules']` [init option](#polyfill-enable-option).
523
+ In shim mode, Wasm modules are always supported. In polyfill mode, Wasm modules require the `polyfillEnable: ['wasm-module-sources']` (or `'wasm-modules-instances'` for instance imports) [init option](#polyfill-enable-option).
523
524
 
524
525
  WebAssembly module exports are made available as module exports and WebAssembly module imports will be resolved using the browser module loader.
525
526
 
526
- By default Wasm support will look for both source phase syntax as well as instance Wasm imports, resulting in full analysis of the module graph when either is unsupported.
527
-
528
- If only using Wasm modules in the source phase set `polyfillEnable: ['wasm-module-sources']` [init option](#polyfill-enable-option) to ensure full native passthrough without the extra code analysis when Chrome ships the source phase.
527
+ If only using Wasm modules in both the instance and source phase set `polyfillEnable: ['wasm-modules']` [init option](#polyfill-enable-option) to enable both modes.
529
528
 
530
529
  When enabling the source phase feature either way, `WebAssembly.Module` is also polyfilled to extend from `AbstractModuleSource` per the source phase proposal.
531
530
 
@@ -546,7 +545,7 @@ const instance = await WebAssembly.instantiate(mod, { /* ...imports */ });
546
545
  </script>
547
546
  ```
548
547
 
549
- If using CSP, make sure to add `'unsafe-wasm-eval'` to `script-src` which is needed when the shim or polyfill engages, note this policy is much much safer than eval due to the Wasm secure sandbox. See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src#unsafe_webassembly_execution.
548
+ If using CSP, make sure to add `'unsafe-wasm-eval'` to `script-src` which is needed when the shim or polyfill engages, note this policy is safer than normal eval due to the Wasm secure sandbox. See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src#unsafe_webassembly_execution.
550
549
 
551
550
  ### Import Defer
552
551
 
@@ -558,24 +557,100 @@ The polyfill is simply just a defer syntax stripping, allowing environments that
558
557
 
559
558
  ### TypeScript Type Stripping
560
559
 
561
- Node.js recently [added support for automatically executing TypeScript with type stripping](https://nodejs.org/api/typescript.html). We support the exact same approach in ES Module Shims.
560
+ TypeScript type stripping is supported like [in Node.js](https://nodejs.org/api/typescript.html).
562
561
 
563
- Once enabled, the separate `es-module-shims-typescript.js` extension must be available as a sibling asset to `es-module-shims.js` and will then be loaded on demand when a `.ts`, `.mts` file is loaded or when a file is served with the `application/typescript` MIME type.
562
+ To trigger TypeScript type stripping, make sure to either use shim mode, or to add the non-standard `lang="ts"` option to the top-level evaluator. This ensures that the polyfill processing will engage on this graph, while usually module graphs are not processed at all in browsers with full native support.
564
563
 
565
- Example:
564
+ Modules will then be interpreted as TypeScript when one of the following applied:
565
+
566
+ * It is served with the `application/typescript` MIME type.
567
+ * It ends in `.ts` or `.mts` and is not served with a valid module script MIME type.
568
+ * Or, if it is an inline `lang="ts"` module script.
569
+
570
+ For example the following are all valid TypeScript usage patterns:
571
+
572
+ Shim mode - no `lang=ts` is necessary:
566
573
 
567
574
  ```html
568
- <script async src="https://ga.jspm.io/npm:es-module-shims@2.1.2/dist/es-module-shims.js"></script>
569
- <script type="esms-options">
575
+ <script type="module-shim" src="app.ts">
576
+ ```
577
+
578
+ Polyfill mode via `lang=ts`:
579
+
580
+ ```html
581
+ <script type="module" lang="ts" src="app.ts"></script>
582
+ ```
583
+
584
+ Inline TypeScript with `lang=ts`:
585
+
586
+ ```html
587
+ <script type="module" lang="ts">
588
+ import './dep.ts';
589
+ const ts: boolean = true;
590
+ console.log('TypeScript!');
591
+ </script>
592
+ ```
593
+
594
+ Indirect static import to a TypeScript module via `lang="ts"`:
595
+
596
+ ```html
597
+ <script type="importmap">
570
598
  {
571
- "polyfillEnable": "all"
599
+ "imports": {
600
+ "app": "/app.mts"
601
+ }
572
602
  }
573
603
  </script>
574
- <script type="module" src="test.ts"></script>
604
+ <script type="module" lang="ts">
605
+ import 'app';
606
+ </script>
575
607
  ```
576
608
 
609
+ Loading TypeScript dynamically:
610
+
611
+ ```html
612
+ <script type="module" lang="ts">
613
+ importShim('./app.ts', { lang: 'ts' });
614
+ </script>
615
+ ```
616
+
617
+ When processing a TypeScript module, the `es-module-shims-typescript.js` extension must be available as a sibling asset to `es-module-shims.js`. It will then be loaded on-demand to provide the type stripping processing.
618
+
577
619
  Note that runtime TypeScript features such as enums are not supported, and type only imports should be used where possible, per the Node.js guidance for TypeScript.
578
620
 
621
+ ### Hot Reloading
622
+
623
+ Hot reloading is supported in both shim and polyfill modes, when explicitly enabled. To enable hot-reloading, enable the `hotReload` init option:
624
+
625
+ test.html
626
+ ```html
627
+ <script type="esms-options">
628
+ {
629
+ "hotReload": true,
630
+ "hotReloadInterval": 100
631
+ }
632
+ </script>
633
+ <script async src="es-module-shims.js"></script>
634
+ <script type="module" src="/app.js"></script>
635
+ ```
636
+
637
+ In polyfill mode, all modules will be initialized twice when hot reloading to reinitiate with `import.meta.hot`. To avoid this, shim mode is recommended for hot reloading workflows whenever possible.
638
+
639
+ The `hotReloadInterval` option can also be configured which is the interval at which hot reload events are batched together as a single reload operation, with the default of `100`.
640
+
641
+ When enabled, [native passthrough](#native-passthrough) will be automatically disabled, and all modules will be provided with the `import.meta.hot` API fully supporting [Vite's `import.meta.hot`](https://vite.dev/guide/api-hmr), supporting the following methods except for the event handlers:
642
+
643
+ * `hot.accept(cb)`: Accept a hot update.
644
+ * `hot.accept(dep, cb)`: Accept a hot update of a dependency specifier string.
645
+ * `hot.accept(deps, cb)`: Accept a hot update of a list of dependency specifier strings.
646
+ * `hot.dispose(cb)`: Provide a dispose function for when this module is expected to be accepted by others.
647
+ * `hot.data`: Shared data object between hot reload instances.
648
+ * `hot.invalidate()`: Fully invalidate the current module, without accepting. Can be called within accept itself.
649
+
650
+ To trigger a hot reload, call the `importShim.hotReload(url)` API with the URL of the module that has changed. All of CSS, JSON, Wasm and TypeScript imports are supported in hot reloading.
651
+
652
+ This hot reload API can then be attached to a Web Socket, Server Side Events emitter or any other event source to provide a native hot reloading development environment.
653
+
579
654
  ### Module Workers
580
655
 
581
656
  ES Module Shims can be used in module workers in browsers that provide dynamic import in worker environments, which at the moment are Chrome(80+), Edge(80+), Firefox(~113+) and Safari(15+).
@@ -615,6 +690,7 @@ Provide a `esmsInitOptions` on the global scope before `es-module-shims` is load
615
690
  * [enforceIntegrity](#enforce-integrity)
616
691
  * [fetch](#fetch-hook)
617
692
  * [mapOverrides](#overriding-import-map-entries)
693
+ * [nativePassthrough](#native-passthrough)
618
694
  * [modulepreload](#modulepreload)
619
695
  * [noLoadEventRetriggers](#no-load-event-retriggers)
620
696
  * [globalLoadEventRetrigger](#global-load-event-retrigger)
@@ -632,7 +708,7 @@ window.esmsInitOptions = {
632
708
  // Enable Shim Mode
633
709
  shimMode: true, // default false
634
710
  // Enable newer modules features
635
- polyfillEnable: ['css-modules', 'json-modules'], // default empty
711
+ polyfillEnable: ['wasm-module-sources'], // default empty
636
712
  // Custom CSP nonce
637
713
  nonce: 'n0nce', // default is automatic detection
638
714
  // Don't retrigger load events on module scripts (DOMContentLoaded, domready, window 'onload')
@@ -646,6 +722,9 @@ window.esmsInitOptions = {
646
722
  enforceIntegrity: true, // default false
647
723
  // Permit overrides to import maps
648
724
  mapOverrides: true, // default false
725
+ // Whether es-module-shims will defer to the native module loader whenever it can
726
+ // Automatically disabled in hot reloading workflows
727
+ nativePassthrough: false, // default true
649
728
 
650
729
  // -- Hooks --
651
730
  // Module load error
@@ -671,7 +750,7 @@ window.esmsInitOptions = {
671
750
  <script type="esms-options">
672
751
  {
673
752
  "shimMode": true,
674
- "polyfillEnable": ["css-modules", "json-modules"],
753
+ "polyfillEnable": ["wasm-module-sources"],
675
754
  "nonce": "n0nce",
676
755
  "onpolyfill": "polyfill"
677
756
  }
@@ -700,14 +779,14 @@ DOM `load` events are fired for all `"module-shim"` scripts both for success and
700
779
 
701
780
  The `polyfillEnable` option allows enabling polyfill features which are newer and would otherwise result in unnecessary polyfilling in modern browsers that haven't yet updated.
702
781
 
703
- This options supports `"css-modules"`, `"json-modules"`, `"wasm-modules"`, `"wasm-module-sources"`, `"wasm-module-instances"` and `"import-defer"`.
782
+ This options supports `"wasm-modules"`, `"wasm-module-sources"`, `"wasm-module-instances"` and `"import-defer"`.
704
783
 
705
- In adddition, the `"all"` option will enable all features and the `"latest"` option will implement the latest supported browser features (currently `"css-modules"` and `"json-modules"`).
784
+ In adddition, the `"all"` option will enable all features.
706
785
 
707
786
  ```html
708
787
  <script type="esms-options">
709
788
  {
710
- "polyfillEnable": ["latest", "typescript"]
789
+ "polyfillEnable": ["all"]
711
790
  }
712
791
  </script>
713
792
  ```
@@ -863,6 +942,17 @@ document.body.appendChild(Object.assign(document.createElement('script'), {
863
942
 
864
943
  This can be useful for HMR workflows.
865
944
 
945
+ ### Native Passthrough
946
+
947
+ By default, ES Module Shims will always use the native passthrough of calling the native `import()` mechanism to load module graphs, when it has analyzed that that module graph is fully supported in the current environment. This way, the native module registry is fully shared between polyfilled and non-polyfilled graphs,
948
+ and we lean into the native support as much as popssible.
949
+
950
+ In Shim mode, ES Module Shims never uses native pass through regardless of this option - it only applies to polyfill mode.
951
+
952
+ This option is enabled by default, so by turning it off it is possible to ensure that ES Module Shims is rewriting and processing all sources itself.
953
+
954
+ Native passthrough is automatically disabled when using [hot reloading](#hot-reloading).
955
+
866
956
  ### Hooks
867
957
 
868
958
  #### Polyfill hook