-
Notifications
You must be signed in to change notification settings - Fork 340
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
Migrate to import { initAll }
from ES module bundle
#3833
Conversation
@@ -4,6 +4,10 @@ | |||
<link rel="stylesheet" href="/stylesheets/app.min.css"> | |||
|
|||
{% block styles %}{% endblock %} | |||
|
|||
<script type="importmap"> | |||
{ "imports": { "govuk-frontend": "/javascripts/all.bundle.min.mjs" } } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An import map has been added to resolve govuk-frontend
to /javascripts/all.bundle.min.mjs
when run inside Puppeteer page.evaluate()
like this:
await page.evaluate(async (exportName) => {
const { CharacterCount } = await import('govuk-frontend')
const $module = document.querySelector('[data-module]')
const component = new CharacterCount($module)
component.init()
})
It also ensures that our on-page evaluated JavaScript can be type checked
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question Is that importmap used outside of the test boilerplate? If not, I'd suggest moving it to that template specifically (even if it lives at the top of the <body>
tag) as it's a feature to help with the tests 😊
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's used by renderAndInitialise()
via /tests/boilerplate
govuk-frontend/shared/helpers/puppeteer.js
Line 101 in bf728fc
const namespace = await import('govuk-frontend') |
(Few other tests also use boilerplate)
But all the globals tests (now "exports" rather than globals) use the home page /
const namespace = await import('govuk-frontend') |
const namespace = await import('govuk-frontend') |
Object.keys(await import('govuk-frontend')) |
Let me just double check they'd all work from the boilerplate too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@romaricpascal Yeah all fine, I've moved it to the boilerplate only
@@ -15,6 +19,9 @@ | |||
{% set mainClasses = 'govuk-main-wrapper--auto-spacing' %} | |||
|
|||
{% block bodyEnd %} | |||
<script type="module" src="/javascripts/all.min.js"></script> | |||
<script type="module">window.GOVUKFrontend.initAll()</script> | |||
<script type="module" src="/javascripts/all.bundle.min.mjs"></script> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keeping the <script>
tag allows browser preload scanners to download our ES module bundle early
It's optional and can be replaced with modulepreload
in future (Safari 17+)
<link rel="modulepreload" href="/javascripts/all.bundle.min.mjs">
a67967a
to
091afe1
Compare
091afe1
to
bf728fc
Compare
@romaricpascal We're 100% "double download" free in Safari 11.1 ☝️ Both browsers show concurrent download alongside the CSS Additional checks in Internet Explorer 11 and Safari 10.1 show components without JavaScript |
These tests appear to use dynamic `import()` but really they’re transformed to `require()` by Jest to clear the “require cache” between test runs Since we’d like to start using _real_ dynamic `import()` in our Puppeteer tests (to import `govuk-frontend` as an ES module) the task arguments must be converted back to CommonJS See: https://jestjs.io/docs/ecmascript-modules
This fixes an issue running `import()` via Puppeteer by turning off dynamic import `require()` transforms that use Babel runtime helper
bf728fc
to
1392b23
Compare
An import map has been added to resolve `govuk-frontend` to `/javascripts/all.bundle.min.mjs` when run inside Puppeteer `page.evaluate()`
1392b23
to
f1a0637
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice to totally take advantage of the ES modules for import
ing our API 🥳
I think the review app and its tests are in a bit of a wonky state, though, as it neither follows:
- an
import
version of https://frontend.design-system.service.gov.uk/importing-css-assets-and-javascript/#add-the-javascript-file-to-your-html, where we would servenode_modules/govuk-frontend/dist/govuk/all.mjs
without bundling - https://frontend.design-system.service.gov.uk/importing-css-assets-and-javascript/#import-javascript-using-a-bundler, where the bundled file would be the one initialising the components
So we're not quite testing that GOV.UK Frontend does what it's meant to in our tests, more that our review app bundle does what GOV.UK Frontend is meant to do (in a closer way than before so that's a win, though 🥳 ).
Let's merge this step forward and I'll add a note on #3508 to update how the review app serves/bundles govuk-frontend so we do test govuk-frontend and not the review app bundle (I'd say in favour of 1 so we actually test govuk-frontend
through the review app).
This PR follows our switch to ES modules:
<script type="module">
#3769It changes our review app to use ES module
import
notwindow.GOVUKFrontend.*
for #3508Before
We include our JavaScript as an IIFE via
<script type="module">
After
We import our JavaScript as an ES module bundle via
<script type="module">
Whilst the first
<script>
is optional we've kept it for the browser preload scanner (see comment)