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.17k stars 320 forks source link

Concatenating multiple UMD files only exports the last component in `window.GOVUKFrontend` #5047

Open romaricpascal opened 3 months ago

romaricpascal commented 3 months ago

Description of the issue

When concatenating multiple UMD files (<COMPONENT_NAME>.bundle.js), for example using Rails Assets Pipeline, only the last component will get exported in window.GOVUKFrontend

Steps to reproduce the issue

  1. In a brand new folder, install the latest version of GOV.UK Frontend

    npm install govuk-frontend
  2. As a replication of concatenating files, create the following HTML file that adds two components to a page and logs the content of window.GOVUKFrontend:
<!DOCTYPE html>
<meta charset=utf-8>
<title>Multiple UMD component issues</title>
<script src="node_modules/govuk-frontend/dist/govuk/components/accordion/accordion.bundle.js"></script>
<script src="node_modules/govuk-frontend/dist/govuk/components/button/button.bundle.js"></script>
<script>
    console.log(window.GOVUKFrontend)
</script>
  1. Open the index.html file in your browser and open the devtools console

Actual vs expected behaviour

The logs will show only one property in window.GOVUKFrontend: Button. It should list both Accordion and Button as both are listed on the page.

This is likely due to the UMD wrapper inside the .bundle.js files that resets window.GOVUKFrontend in each file. Notice the global.GOVUKFrontend = {} at the end of the 4th line which will reset window.GOVUKFrontend as an empty object:

(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
  typeof define === 'function' && define.amd ? define(['exports'], factory) :
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.GOVUKFrontend = {}));
})(this, (function (exports) { 'use strict';

Environment (where applicable)