Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Babel transforms for older browsers are not applied #1127

Open
colinrotherham opened this issue Feb 11, 2025 · 2 comments · May be fixed by #1135
Open

Babel transforms for older browsers are not applied #1127

colinrotherham opened this issue Feb 11, 2025 · 2 comments · May be fixed by #1135
Labels
🐛 bug Something isn't working the way it should (including incorrect wording in documentation)

Comments

@colinrotherham
Copy link
Contributor

Bug Report

What is the issue?

Babel is not applying the required transforms for ES2015+ features such as class fields and destructuring

Each Node.js bump to .nvmrc will accidentally reduce browser support as a side effect

What steps are required to reproduce the issue?

Running npm run build sees only Node.js transforms applied to the nhsuk.js output

It's currently set to target node: 'current' in babel.config.js

Current

When adding debug: true to the @babel/preset-env config we can see only Node.js transforms are applied:

Using targets:
{
  "node": "20.18.2"
}

Using modules transform: auto

Using plugins:
  transform-duplicate-named-capturing-groups-regex { node < 23 }
  transform-regexp-modifiers { node < 23 }
  syntax-class-static-block
  syntax-private-property-in-object
  syntax-class-properties
  syntax-numeric-separator
  syntax-nullish-coalescing-operator
  syntax-optional-chaining
  syntax-json-strings
  syntax-optional-catch-binding
  syntax-async-generators
  syntax-object-rest-spread
  proposal-export-namespace-from { }
  syntax-dynamic-import
  syntax-top-level-await
  syntax-import-meta

Using polyfills: No polyfills were added, since the `useBuiltIns` option was not set.

Expected

Versus the following when configured for all browsers matching supports es6-module

Using targets:
{
  "android": "61",
  "chrome": "61",
  "edge": "16",
  "firefox": "60",
  "ios": "10.3",
  "opera": "48",
  "opera_mobile": "80",
  "safari": "10.1",
  "samsung": "8.2"
}

Using modules transform: auto

Using plugins:
  transform-duplicate-named-capturing-groups-regex { android, chrome < 126, edge < 126, firefox < 129, ios < 17.4, opera < 112, opera_mobile, safari < 17.4, samsung }
  transform-regexp-modifiers { android, chrome < 125, edge < 125, firefox < 132, ios, opera < 111, opera_mobile, safari, samsung }
  transform-unicode-sets-regex { android, chrome < 112, edge < 112, firefox < 116, ios < 17, opera < 98, safari < 17, samsung }
  proposal-class-static-block { android, chrome < 94, edge < 94, firefox < 93, ios < 16.4, opera < 80, safari < 16.4, samsung < 17 }
  proposal-private-property-in-object { android, chrome < 91, edge < 91, firefox < 90, ios < 15, opera < 77, safari < 15, samsung < 16 }
  proposal-class-properties { android, chrome < 74, edge < 79, firefox < 90, ios < 14.5, opera < 62, safari < 14.1, samsung < 11 }
  proposal-private-methods { android, chrome < 84, edge < 84, firefox < 90, ios < 15, opera < 70, safari < 15, samsung < 14 }
  proposal-numeric-separator { android, chrome < 75, edge < 79, firefox < 70, ios < 13, opera < 62, safari < 13, samsung < 11 }
  proposal-logical-assignment-operators { android, chrome < 85, edge < 85, firefox < 79, ios < 14, opera < 71, safari < 14, samsung < 14 }
  proposal-nullish-coalescing-operator { android, chrome < 80, edge < 80, firefox < 72, ios < 13.4, opera < 67, safari < 13.1, samsung < 13 }
  proposal-optional-chaining { android, chrome < 80, edge < 80, firefox < 74, ios < 13.4, opera < 67, safari < 13.1, samsung < 13 }
  proposal-json-strings { android, chrome < 66, edge < 79, firefox < 62, ios < 12, opera < 53, safari < 12, samsung < 9 }
  proposal-optional-catch-binding { android, chrome < 66, edge < 79, ios < 11.3, opera < 53, safari < 11.1, samsung < 9 }
  proposal-async-generator-functions { android, chrome < 63, edge < 79, ios < 12, opera < 50, safari < 12 }
  proposal-object-rest-spread { edge < 79, ios < 11.3, safari < 11.1 }
  transform-dotall-regex { android, chrome < 62, edge < 79, firefox < 78, ios < 11.3, opera < 49, safari < 11.1 }
  proposal-unicode-property-regex { android, chrome < 64, edge < 79, firefox < 78, ios < 11.3, opera < 51, safari < 11.1, samsung < 9 }
  transform-named-capturing-groups-regex { android, chrome < 64, edge < 79, firefox < 78, ios < 11.3, opera < 51, safari < 11.1, samsung < 9 }
  transform-unicode-regex { ios < 12, safari < 12 }
  proposal-export-namespace-from { android < 72, chrome < 72, edge < 79, firefox < 80, ios < 14.5, opera < 60, safari < 14.1, samsung < 11.0 }
  bugfix/transform-async-arrows-in-class { ios < 11, safari < 11 }
  bugfix/transform-edge-default-parameters { edge < 18 }
  bugfix/transform-edge-function-name { edge < 79 }
  bugfix/transform-safari-block-shadowing { ios < 11, safari < 11 }
  bugfix/transform-safari-for-shadowing { ios < 11, safari < 11 }
  bugfix/transform-safari-id-destructuring-collision-in-function-expression { ios < 16.3, safari < 16.3 }
  bugfix/transform-tagged-template-caching { ios < 13, safari < 13 }
  syntax-dynamic-import
  syntax-top-level-await
  syntax-import-meta

What was the environment where this issue occurred?

  • Device:
  • Operating System:
  • Browser:
  • Browser version:
  • NHS.UK frontend package version:
  • Node version:
  • npm version:

Is there anything else you think would be useful in recreating the issue?

@colinrotherham colinrotherham added the 🐛 bug Something isn't working the way it should (including incorrect wording in documentation) label Feb 11, 2025
@colinrotherham
Copy link
Contributor Author

To explain using diffs

Button

Modern browsers lacking class field support would need Babel to apply changes such as:

 class Button {
-  KEY_SPACE = 32;
-  DEBOUNCE_TIMEOUT_IN_SECONDS = 1;
   constructor($module) {
+    this.KEY_SPACE = 32;
+    this.DEBOUNCE_TIMEOUT_IN_SECONDS = 1;
     this.$module = $module;
     this.debounceFormSubmitTimer = null;
   }

Character Count

But Internet Explorer 11 would need const var and prototype methods to return:

   // Initialize component
-  init() {
+  var _proto = CharacterCount.prototype;
+  _proto.init = function init() {
     // Check that required elements are present
     if (!this.$textarea) {
       return;
@@ -183,13 +187,9 @@
     }
 
     // Check for module
-    const {
-      $module
-    } = this;
-    const {
-      $textarea
-    } = this;
-    const $fallbackLimitMessage = document.getElementById(`${$textarea.id}-info`);
+    var $module = this.$module;
+    var $textarea = this.$textarea;
+    var $fallbackLimitMessage = document.getElementById($textarea.id + "-info");

@colinrotherham
Copy link
Contributor Author

I've done a bit more investigation

We've got two groups affected:

JavaScript bundles

E.g. NHS Prototype Kit includes dist/nhsuk.min.js directly

JavaScript modules

E.g. NHS.UK Digital Campaigns CMS bundles packages/nhsuk.js

Problems:

  1. Published modules lack *.mjs extensions without package.json "type": "module"
  2. Published modules lack mandatory file extensions in their imports
  3. Publishes package has no CommonJS or Universal Module Definition (UMD) support (see #937)

This means teams must opt in to Babel transforms themselves (see example)

@colinrotherham colinrotherham linked a pull request Feb 13, 2025 that will close this issue
@colinrotherham colinrotherham linked a pull request Feb 13, 2025 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🐛 bug Something isn't working the way it should (including incorrect wording in documentation)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant