Skip to content

Instantly share code, notes, and snippets.

@NickColley
Last active March 28, 2020 19:35
Show Gist options
  • Save NickColley/c5a2e5f8dccc67fc938c843a5580789a to your computer and use it in GitHub Desktop.
Save NickColley/c5a2e5f8dccc67fc938c843a5580789a to your computer and use it in GitHub Desktop.
JavaScript in GOV.UK Frontend - Request For Comments

Proposal: GOV.UK Frontend - How we write JavaScript

Who are our users?

GOV.UK Design System projects is designed to work with a distributed ecosystem that is the UK Government. Even if we wanted to we can not force a certain framework or approach on teams distributed in different departments across the UK.

With this in mind we need to support the lowest denominator and be technology agnostic.

Any approach that relies on HTML being identical on both the client and server will mean our JavaScript will only work with a framework that we have chosen. (See virtual dom hydration)

This means a more hands-on approach is required. As Stimulus refers to it 'sprinkling' some attributes onto pre-existing HTML that then can be used to enhance components.

Examples of approaches:

Browser support

Functional experience

This section refers to 'cutting the mustard' as coined by the BBC Responsive News team.

Our current strategy when enhancing our interfaces is to enhance any browser that can run JavaScript.

This includes using:

  • jQuery 1.x (with legacy browser IE 6+ support)
  • Writing ES3 JavaScript (making use of jQuery for 'utility' functions, for example $.each())

'Functional experience' on the other hand describes a distinction between older 'functional browsers' and newer 'compliant browsers'.

In practice this means the HTML experience that we include in our services would be intentionally extended beyond reliability by 'cutting the mustard' with only 'compliant browsers' receiving the enhanced experience.

The GOV.UK Template Consolidation team did some research on older browsers outside of the service manual's recommended browser matrix and found that browsers that are 'not supported' still recieve enhancements to the determent of the user experience. Specifically older browsers tend to have trouble doing DOM manipulation and have rudimentary JavaScript engines.

With this in mind it's important that browser we do not test in do not receive expensive bundles of assets, and instead receive a lightweight 'functional experience'.

Legacy browsers 'no supported'

Similar to 'functional browsers' with the cavet that we do not test in these browsers. Try to make sure these browsers get the 'functional experience'.

Functional browsers

If a browser is assigned a ‘functional’ level of support, it means your service might not look perfect in that browser but must still be usable without errors.

For functional browsers they should receive the 'functional experience'.

This means not running JavaScript to enhance the interface and relying on the no-JavaScript fallback. It's important we test in this browsers to ensure no barriers are encountered.

Exception: If JavaScript overcomes barriers that cannot be avoided, for example shimming HTML5 elements or shimming anchor buttons. (Note: These should be standalone libraries, vendor any polyfills, which will allow us to publish these shims widely. Use common sense here.)

(question: what is the best way to short circuit JavaScript, should it be shipped at all, or just return early?)

Compliant browsers

‘Compliant’ means your service must look as good as it does in other modern browsers.

Compliant browsers can make use of newer browser features.

JavaScript

Modules

We should ensure our JavaScript can be easily built by a build tool such as Browserify/Webpack/ParcelJS etc. This will make it easy for users of GOV.UK Frontend to produce small builds with only what they need.

CommonJS? ES6 Modules? (question: What impact does transpiling ES6 with ES6 Modules have on users?)

Recommendation: More discussion needed

ES6? ES5

  • ES5 would require dropping IE 8 minimum.
  • ES6 would need more discussion.

https://caniuse.com/#search=es5 http://kangax.github.io/compat-table/es5/

Recommendation: Ship ES5 and avoid running in IE 8 - IE 10

jQuery

  • jQuery 1.x and 2.x no longer receive patches, this is true even for security issues.
  • jQuery 3.x supports IE9+

http://youmightnotneedjquery.com/

➜ ~ curl -L https://code.jquery.com/jquery-git.js | grep -n Support: | wc -l

  • 109 browser issues
  • 60 IE issues (a lot are older than IE 9)
  • 20 issues in IE 11

jQuery utils should be replaced by polyfills of native vanilla features.

For example use forEach polyfill instead of using $.each()

Recommendation: Drop jQuery in replace of polyfilling native features in compliant where necessary.

Polyfill.io

https://polyfill.io/v2/docs/

  • reliance on CDN, single point of failure?
  • assumption: tries to run big bundles on potentially slow browsers?

Recommendation: Avoid

Linting

We have had some success using 'standardjs', which has avoided bikeshedding around style and kept our projects consistent.

However the wider community at GDS have been interested in standardising on a similar project 'XO' which includes more detailed linting rules.

Main real benefit we can see from this is that it defaults that are closer to a less controversial stance on semi-colons. Which tends to be frustrating for new-commers to standardjs, this is more inclusive and feels like a good reason to change.

See https://github.com/xojs/xo#why-not-standard

Porting

An ecosystem requires the collaboration and support of teams outside of the GOV.UK Design System core team.

Porting is the process of taking a source project and making it work in a specific technology.

A form of porting (or transpilation) can be seen in the GOVUK Template project, however this has proven unsustainable due to the fact the core team does not have needs for the different variations.

Instead by giving downstream users of GOV.UK Frontend the tools and trust to make GOV.UK Frontend work for them we can split the burden of maintenance across the ecosystem and in turn create a greater sense of community.

Some users of GOV.UK Frontend will find our approach difficult to use in their specific templating language, for example users of React may want to repackage our Nunjuck's macro as a React component, and by extension want to port our JavaScript.

We should make this easy by:

  • making sure to keep reuse in mind
  • writing our tests in a way that they can be easily reused and used as a 'specification' in which to build to.
  • encouraging users to use our Nunjucks Macro interface for their port.

Simple components

Examples include: Details (progressive disclosure), Error summary

  • should instantiate from data attributes applied to existing HTML (unless polyfilling a native feature)
  • should be easy to port in necessary (see porting)

Complex components

Examples include: Datepicker, Autocomplete

Complex components should be written with a framework that makes it easy to:

  • handle component state
  • handle complicated DOM manipulation
  • handle complicated event interaction

Fallbacks for complex components are typically entirely different interactions, for example with an Autocomplete the fallback is a select element.

We would not expect these components to be ported so ideally we would wrap these components with a Web Component interface, which should stand the test of time and be compatible with a lot of the popular frameworks.

At the moment we are using Preact for accessible-autocomplete this is compatible with the popular React ecosystem and is very lightweight (3kb).

(See below, investigation needed)

Conclusion

  • Do not ship JavaScript to functional browsers: IE8 - IE10 (unless barriers)

  • Feature detect for complex components, with per component 'mustard cuts'

  • Drop jQuery

  • Use Preact for complex components

  • Use a html 'data-api' for simple components

  • Investigate Web Components to wrap or replace preact

  • Redefine 'cutting the mustard' in standard english

Investigation needed: Web Components

<govuk-datepicker>
  <label for="datepicker">Datepicker label</label>
  <input type="text" id="datepicker">
  <input type="text" id="datepicker">
  <input type="text" id="datepicker">
</govuk-datepicker>
<govuk-autocomplete>
  <select name="" id="">
    <option value=""></option>
    <option value=""></option>
    <option value=""></option>
    <option value=""></option>
    <option value=""></option>
    <option value=""></option>
  </select>
</govuk-autocomplete>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment