alphagov / govuk-frontend

GOV.UK Frontend contains the code you need to start building a user interface for government platforms and services.
https://frontend.design-system.service.gov.uk/
MIT License
1.18k stars 323 forks source link

Use polyfills from npm package #3082

Open colinrotherham opened 1 year ago

colinrotherham commented 1 year ago

What

This issue has been created to investigate using polyfills from an npm package

We currently copy polyfills from:

  1. https://polyfill.io web service
  2. polyfill-library npm package
  3. MDN Web Docs examples

We avoid unnecessary govuk-frontend dependencies but may have missed important bug fixes since ~2018:

Why

There is a performance impact if we're shipping duplicate polyfills that service teams already install. There's also a potential usability impact should older browsers be running our out-of-date polyfills with unknown issues (bugs, performance)

We can ask some questions:

  1. Could we import polyfills from npm via polyfill-library or core-js?
  2. Could we use Rollup to bundle our polyfills to maintain a dependency-free govuk-frontend?
  3. Should we skip polyfill bundling and instead add our first dependency to govuk-frontend?
  4. Should we do this without any breaking changes?

Update: Looks like core-js only provides ES5+ polyfills so we'd be lacking the ES3+ upgrades like [].indexOf(), .addEventListener(), Date.now(), document.querySelector() etc from polyfill-library

This may be considered a step towards:

Who needs to work on this

Developers

Who needs to review this

Developers

Done when

colinrotherham commented 1 year ago

For example

Before

import '../../vendor/polyfills/Event.mjs'
import '../../vendor/polyfills/Function/prototype/bind.mjs'
import '../../vendor/polyfills/String/prototype/trim.mjs'

After

Where polyfill-library could be core-js or any other polyfill provider

import 'polyfill-library/polyfills/__dist/Event/min.js'
import 'polyfill-library/polyfills/__dist/Function.prototype.bind/min.js'
import 'polyfill-library/polyfills/__dist/String.prototype.trim/min.js'

Note: We'd need to swap our *.mjs file copy step to a second Rollup run in format: 'es' mode

colinrotherham commented 1 year ago

Alternatively, could we skip straight to automating our polyfills via:

  1. Babel with @babel/preset-env in useBuiltIns: 'usage' mode
  2. Babel with @babel/plugin-transform-runtime to alias globals versus modifying window
  3. Using the Browserlist config to determine polyfills by browser support
colinrotherham commented 1 year ago

Example spike for 2) + 3) https://github.com/colinrotherham/polyfill-playground