├── CODE_OF_CONDUCT.md
├── proposals
├── 000-template.md
├── 001-use-rfcs-and-adrs-to-discuss-proposals-and-record-decisions.md
├── README.md
├── 006-initialise-javascript-using-govuk-namespaced-data-module-attributes.md
├── 008-simplifying-imports-to-improve-compilation-performance.md
├── 005-namespace-govuk-frontend-nunjucks-sass-using-a-nested-folder-structure.md
├── 003-make-override-classes-consistent.md
├── 004-enable-importing-css-modules-via-filename-convention-used-in-common-frameworks.md
└── 002-publish-one-npm-package-instead-of-multiple-npm-packages.md
├── README.md
├── decision-records
├── 000-template.md
├── README.md
├── 004-new-version-font.md
├── 002-restructure-based-on-single-package.md
├── 009-throw-errors-component-constructors.md
├── 001-javascript-for-less-capable-browsers.md
├── 008-reset-the-javascript-api.md
├── 010-remove-init-method.md
├── 007-javascript-file-formats.md
├── 003-templating-languages.md
├── 005-repository-organisation-for-v5.md
└── 006-javascript-compatibility.md
└── LICENSE
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | ## Code of Conduct
2 |
3 | This project follows the ['alphagov' GitHub organisation Code of Conduct][coc].
4 |
5 | [coc]: https://github.com/alphagov/code-of-conduct
6 |
--------------------------------------------------------------------------------
/proposals/000-template.md:
--------------------------------------------------------------------------------
1 | # Proposal Title
2 |
3 | **Closing date:**
4 |
5 | **Status:**
6 |
7 | ## Summary
8 |
9 |
10 |
11 | ## Problem
12 |
13 |
14 |
15 | ## Proposal
16 |
17 |
20 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # GOV.UK Design System Architecture
2 |
3 | We use this repository as a forum to discuss and record technical decisions that
4 | affect the products supported by the GOV.UK Design System team, including:
5 |
6 | - GOV.UK Design System
7 | - GOV.UK Frontend
8 | - GOV.UK Prototype Kit
9 |
10 | This repository is open to enable involvement from the wider community and as a
11 | reference for other teams within GDS and wider government.
12 |
13 | There are 2 types of documentation:
14 |
15 | - [Proposals](/proposals), often referred to as 'requests for comments', which
16 | allow us and the wider community to suggest and refine ideas.
17 | - [Decision Records](/decision-records), which document decisions that have been
18 | made, along with any context.
19 |
20 | ## Code of Conduct
21 |
22 | This project follows the ['alphagov' GitHub organisation Code of Conduct][coc].
23 |
24 | [coc]: https://github.com/alphagov/code-of-conduct
25 |
--------------------------------------------------------------------------------
/decision-records/000-template.md:
--------------------------------------------------------------------------------
1 | # [Decision Title]
2 |
4 |
5 | **Date:**
6 |
7 | **Status:**
8 |
9 | ## Decision
10 |
11 |
12 |
13 | ## Rationale
14 |
15 |
16 |
17 | ## Risks and constraints
18 |
19 |
20 |
21 | ## Alternatives considered
22 |
23 |
24 |
25 | ## Implications
26 |
27 |
28 |
29 | ## Contributors
30 |
31 |
32 |
33 | ## Associated issues and pull requests (PRs)
34 |
35 |
36 |
37 | ## Outcomes
38 |
39 |
40 |
--------------------------------------------------------------------------------
/decision-records/README.md:
--------------------------------------------------------------------------------
1 | # Decision Records
2 |
3 | Records of the architectural decisions that affect one or more of our products.
4 |
5 | These records could reflect the outcomes of the accepted proposals but they
6 | might also reflect ad-hoc decisions or decisions made without going through the
7 | RFC process.
8 |
9 | ## Process
10 |
11 | 1. Create a new branch on this repository and copy
12 | `decision-records/000-template.md` to a new file with the next free number,
13 | such as `001-my-decision-record.md`.
14 | 2. Modify the template to add detail about the decision.
15 | 3. Include any images etc in a separate directory with the same name as your
16 | record (`000-my-decision-record`) and link to them.
17 | 4. Make a Pull Request (PR) for your branch.
18 | 5. The record will be reviewed. As decision records are documenting a decision
19 | that has already been made, any reviews should be focus on ensuring that the
20 | documentation is clear and understandable. If you disagree with the decision,
21 | you should raise a proposal instead.
22 | 6. Once approved using the Github review system, the PR can be merged.
23 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Crown Copyright (Government Digital Service)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/proposals/001-use-rfcs-and-adrs-to-discuss-proposals-and-record-decisions.md:
--------------------------------------------------------------------------------
1 | # Use RFCs and ADRs to discuss proposals and record decisions
2 |
3 | **Closing date:** 2018-03-16
4 | **Status:** Accepted
5 |
6 | ## Summary
7 |
8 | Use the Request for Comments (RFC) and Architecture Decision Record (ADR)
9 | formats to discuss and record technical decisions for the products we support.
10 |
11 | ## Problem
12 |
13 | We need to make and record decisions in the open, because:
14 |
15 | - it will help us to answer questions from our users as to why things are the
16 | way they are
17 | - it makes it less likely that approaches will be changed in the future without
18 | a full understanding of the context or the rationale for the original decision
19 | - it provides a valuable resource to others, both in government and the wider
20 | community, who are embarking on similar projects
21 |
22 | Whilst some of this is recorded in documents in e.g. Google Drive, this is
23 | not publicly available; there is no consistent approach to how this
24 | documentation is written; and there is no consistent approach to how it is
25 | filed.
26 |
27 | ## Proposal
28 |
29 | We will create a new public repository on GitHub
30 | (`alphagov/govuk-design-system-architecture`) as a place to discuss proposals
31 | and record decisions.
32 |
33 | We will use a simplified version of the existing Request for Comments (RFC)
34 | publication format as a platform for suggesting and refining ideas whilst
35 | involving the wider community.
36 |
37 | We will use the existing Architecture Decision Records (ADR) publication format
38 | as a way to document decisions that have been made.
39 |
40 | We will use markdown for both of these publication types.
41 |
42 | We will aim to simplify the language where possible to reduce the barrier of
43 | entry to contribution and involvement. For example, we will refer to RFCs as
44 | proposals unless we are talking specifically about the format used; we will
45 | simplify 'architecture decision records' to 'decision records'.
46 |
47 | ## Related links
48 |
49 | - [Inspiration: React RFCs](https://github.com/reactjs/rfcs)
50 | - [Inspiration: Swift Evolution](https://github.com/apple/swift-evolution)
51 |
--------------------------------------------------------------------------------
/proposals/README.md:
--------------------------------------------------------------------------------
1 | # Proposals
2 |
3 | Most changes to GOV.UK Design System, GOV.UK Frontend or GOV.UK Prototype Kit
4 | can be implemented and reviewed via the normal GitHub pull request workflow
5 | without raising a proposal.
6 |
7 | Where changes would represent a substantial change to the architecture of a
8 | product or the way the products work together we would expect a proposal to be
9 | raised to gather feedback from the community and to ensure that the consequences
10 | of the change are fully thought-out.
11 |
12 | ## Process
13 |
14 | 1. Create a new branch on this repository and copy `proposals/000-template.md`
15 | to a new file with the next free number, such as `001-my-proposal.md`.
16 | 2. Modify the template to add detail about your proposal.
17 | 3. Include any images etc in a separate directory with the same name as your
18 | proposal (`000-my-proposal`) and link to them.
19 | 4. Make a Pull Request (PR) for your branch.
20 | 5. Post a link to your PR in #govuk-design-system channel on Slack.
21 | 6. The Design System team and the wider community are able to discuss your
22 | proposal using both inline comments against your document and the general PR
23 | comments section. You will need to create a free GitHub account in order to
24 | comment.
25 | 7. As changes are requested and agreed in comments, make the changes in your RFC
26 | and push them as new commits.
27 | 8. Stay active in the discussion and encourage and remind other relevant people
28 | to participate. If you start a proposal it’s up to you to push it through the
29 | process and engage people.
30 | 9. Once consensus is reached and approvals given using the Github review system,
31 | the PR can be merged.
32 |
33 | ## Rejecting proposals
34 |
35 | A proposal can be rejected by the Design System team. This can happen for many
36 | reasons, including if a consensus isn’t reached, or if people agree that
37 | rejecting it is the right thing to do. It might be that there are already plans
38 | to address a given problem in a different way, or that it's just not the right
39 | time to make the change. In this case the PR should be closed with a suitable
40 | comment.
41 |
42 | ## Recording changes
43 |
44 | Proposals should be considered an immutable record of a point in time. If we
45 | want to change a decision that was made in a previous proposal, a new proposal
46 | should be raised. If that proposal is accepted, the old proposal may be updated
47 | to reflect the fact that it has been superseded, but should otherwise be left
48 | intact.
49 |
--------------------------------------------------------------------------------
/proposals/006-initialise-javascript-using-govuk-namespaced-data-module-attributes.md:
--------------------------------------------------------------------------------
1 | # Consistently initialise JavaScript using `govuk-` namespaced data-module attributes
2 |
3 | **Closing date:** 2019-06-11
4 |
5 | **Status:** accepted
6 |
7 | ## Summary
8 |
9 | We want to change the way that JavaScript in GOV.UK Frontend is initialised against elements in the DOM.
10 |
11 | We're doing this to help users avoid conflicts in their application.
12 |
13 | This would be a breaking change in the 3.0.0 release.
14 |
15 | ## Problem
16 |
17 | Currently to initialise the JavaScript for a component we look for a
18 | `data-module` attribute on the element.
19 |
20 | For example, the accordion HTML looks like this:
21 |
22 | ```html
23 |
24 | [..]
25 |
26 | ```
27 |
28 | And we initialise the JavaScript like this:
29 |
30 | ```javascript
31 | // Find all global accordion components to enhance.
32 | var $accordions = scope.querySelectorAll('[data-module="accordion"]')
33 | $accordions.forEach($accordion => {
34 | new Accordion($accordion).init()
35 | })
36 | ```
37 |
38 | This works, but there's a risk of conflict if `[data-module="accordion"]` is used by anything else in the application.
39 |
40 | This [happened on GOV.UK](https://github.com/alphagov/collections/pull/1042), resulting in two 'open all' links appearing on a single accordion.
41 |
42 | ---
43 |
44 | Not all components are initialised in this way. The JavaScript for the button component, for example, sets up event listeners against the `scope` (usually `document`).
45 |
46 | This is inconsistent, and means that some components have a higher chance of conflicting as they e.g. affect anything with `role="button"`
47 |
48 | ## Proposal
49 |
50 | We intend to move to using a `govuk-` namespace for the `data-module` attribute.
51 |
52 | ```html
53 |
54 | [..]
55 |
56 | ```
57 |
58 | ```javascript
59 | // Find all global accordion components to enhance.
60 | var $accordions = scope.querySelectorAll('[data-module="govuk-accordion"]')
61 | $accordions.forEach($accordion => {
62 | new Accordion($accordion).init()
63 | })
64 | ```
65 |
66 | We also intend to initialise all components that use JavaScript in the same way.
67 |
68 | For example, the JavaScript for buttons would be updated to initialise against `[data-module="govuk-button"]`.
69 |
70 | ```html
71 | Continue
72 | ```
73 |
74 | ```js
75 | var $buttons = scope.querySelectorAll('[data-module="govuk-button"]')
76 | $buttons.forEach($button => {
77 | new Button($button).init()
78 | })
79 | ```
80 |
--------------------------------------------------------------------------------
/decision-records/004-new-version-font.md:
--------------------------------------------------------------------------------
1 | # New version of font
2 |
3 | **Date:** 2019-07-29
4 |
5 | **Status:** Accepted
6 |
7 | ## Context
8 |
9 | There were a [number of issues with "NTA"](https://github.com/alphagov/govuk-frontend/issues/1012), the previous version of the font:
10 |
11 | 1. The file size for all versions of the font was larger than it needed to be.
12 | 2. A separate font was required for tabular numbers.
13 | 3. The glyphs sat too high in the fonts bounding box (baseline) which led to the need for adjustments in CSS.
14 | 4. Hinting requirement for oldIE (EOT) increased the file size even further.
15 |
16 | ## Decision
17 |
18 | - Replace the "NTA" font with a new version, called "GDS Transport", which fixes the above issues.
19 | - Specifically, stop serving Transport font to IE8 due to a [large file required for hinting](https://designnotes.blog.gov.uk/2019/07/29/weve-updated-the-gov-uk-colours-and-font/). The font now [falls back to Arial](https://github.com/alphagov/govuk-frontend/blob/master/CHANGELOG.md#gds-transport-now-falls-back-to-arial-in-internet-explorer-8-ie8) for IE8.
20 |
21 | ## Consequences
22 | - Font files are now smaller: WOFF2 files are ~33kb and ~31kb, compared with ~66kb and ~54kb of the previous version of the font 🎉
23 | - The vertical alignment of the font has been corrected. This removes the need for manually adjusting the baseline of the font.
24 | - Tabular numbers are now part of the [`govuk-font` mixin](http://govuk-frontend-review.herokuapp.com/docs/#helpers-mixin-govuk-font), instead of a separate font family.
25 | - The previous version of the font is now deprecated. Service teams using the legacy code bases [can still use the previous version in compatibility mode](https://github.com/alphagov/govuk-frontend/blob/master/docs/installation/compatibility.md).
26 |
27 | ## Advantages
28 |
29 | - Improved page performance due to smaller font files.
30 | - No need to adjust the font baseline manually. This means simpler code and less design / development work.
31 | - With the baseline adjustments removed, the font can be swapped for a different one such as Arial without manually having to remove the baseline adjustments. An example would be if [the service is not on gov.uk](https://www.gov.uk/service-manual/design/making-your-service-look-like-govuk#if-your-service-isnt-on-govuk).
32 | - Simpler documentation for using tabular numbers which are now part of the `govuk-font` mixin. Using tabular numbers no longer requires loading in a separate font, leading to performance gains.
33 | - IE8 will not download the font files but falls back to a default font, leading to performance gains.
34 |
35 | ## Disadvantages
36 |
37 | - Service teams might need to make adjustments in their custom components which contain corrections to the baseline of the font.
38 |
--------------------------------------------------------------------------------
/decision-records/002-restructure-based-on-single-package.md:
--------------------------------------------------------------------------------
1 | # Restructure single GOV.UK Frontend package
2 |
3 | **Date:** 2018-05-10
4 |
5 | **Status:** Accepted
6 |
7 | ## Context
8 |
9 | We implemented the [002 Proposal](https://github.com/alphagov/govuk-design-system-architecture/blob/master/proposals/002-publish-one-npm-package-instead-of-multiple-npm-packages.md) in https://github.com/alphagov/govuk-frontend/pull/680
10 |
11 | We have then restructured the code base in https://github.com/alphagov/govuk-frontend/pull/693
12 |
13 | This is to:
14 |
15 | - solve issues around components importing files that export CSS
16 | - take advantage of the single package - the old structure was based around each folder being it's own package.
17 | - make the entry points to files clearer.
18 | - better reflect conventions by giving each layer it's own folder, this moves them out of a confusingly named 'global' parent folder.
19 |
20 | ## Decision
21 |
22 | ### Structure
23 |
24 | GOV.UK Frontend is broken into a number of layers in order to help provide a
25 | logical structure, loosely following the conventions of [ITCSS].
26 |
27 | 1. [Settings](#settings)
28 | 2. [Tools](#tools)
29 | 3. [Helpers](#helpers)
30 | 4. [Core](#core)
31 | 5. [Objects](#objects)
32 | 6. [Components](#components)
33 | 7. [Utilities](#utilities)
34 | 8. [Overrides](#overrides)
35 |
36 | Each folder has its own entry point (`_all.scss`).
37 |
38 | ### Settings
39 |
40 | Global variables for the project, for example colour palettes and spacing and
41 | typography scales.
42 |
43 | This layer should not output any CSS.
44 |
45 | ### Tools
46 |
47 | Mixins or functions that implement either logic (e.g. conditionally outputting
48 | CSS) or calculations, and that need to be made available globally.
49 |
50 | This layer should not output any CSS.
51 |
52 | ### Helpers
53 |
54 | Mixins that abstract common styling (for example, focus states or visually
55 | hidden content)
56 |
57 | This layer should not output any CSS.
58 |
59 | ### Core
60 |
61 | Basic content styles for typography, links etc. The classes defined in this
62 | layer would generally correspond to an HTML element - for example paragraphs,
63 | headings, lists or links.
64 |
65 | ### Objects
66 |
67 | Objects can range from something as simple as a wrapper element, to layout
68 | systems.
69 |
70 | They may be used in any number of unrelated contexts to the one you can
71 | currently see it in. This means that making modifications to these types of
72 | class could potentially have knock-on effects in other places.
73 |
74 | ### Components
75 |
76 | Discrete pieces of UI. In most cases these will map to the components in the
77 | Design System.
78 |
79 | ### Utilities
80 |
81 | Utility classes – for example clearing floats, visually hiding content.
82 |
83 | ### Overrides
84 |
85 | Classes that map to a specific property – for example margin or font weight -
86 | and override all other layers. Rules in this layer will generally be marked as
87 | !important.
88 |
89 | Class names within this layer use an additional prefix `-!-`, for example
90 | `.govuk-!-w-regular`.
91 |
92 | [ITCSS]: (http://www.creativebloq.com/web-design/manage-large-css-projects-itcss-101517528)
93 |
94 | ## Consequences
95 |
96 | The paths to import the project are changed, this has been detailed in the release notes for GOV.UK Frontend.
97 |
--------------------------------------------------------------------------------
/decision-records/009-throw-errors-component-constructors.md:
--------------------------------------------------------------------------------
1 | # Throw errors from component constructors
2 |
3 | **Date:** 2023-07-20
4 |
5 | **Status:** Accepted
6 |
7 | ## Decision
8 |
9 | In v5.0, we will update the constructor of every component to throw errors if the arguments passed to the constructor are invalid, rather than silently returning.
10 |
11 | ## Rationale
12 |
13 | Currently, if we encounter something unexpected during instantiation of an object we return early. For example:
14 |
15 | ```js
16 | if (!($module instanceof HTMLElement) || !document.body.classList.contains('govuk-frontend-supported')) {
17 | return this
18 | }
19 | ```
20 |
21 | This can make unexpected behaviour difficult to debug for users – because we silently return, the user has no idea why the accordion isn't doing anything.
22 |
23 | The user also has a reference to an instantiated component in an invalid state.
24 |
25 | As we introduce new methods to the public API, we would need to handle the possibility that the component is in an invalid state as part of every individual method:
26 |
27 | ```js
28 | const accordion = new Accordion(aNonExistentElement)
29 | accordion.openAllSections() // what do we do here?!
30 | ```
31 |
32 | Throwing an error from the constructor means that:
33 |
34 | - we are following the 'fail fast' principle
35 | - any unexpected behaviour is easier to debug
36 | - the user can never have a reference to an instantiated component that threw exceptions from the constructor (because the assignment will fail), which means we can assume the component is in a valid state when writing other public methods
37 |
38 | ## Risks and constraints
39 |
40 | ### Changes prevent some users from upgrading
41 |
42 | Users who are relying on being able to access now private class or instance properties from from their own code will need to either:
43 |
44 | - wait until we introduce an equivalent way to achieve the same thing using the public API before they can upgrade beyond v5
45 | - continue to use the private properties 'at risk', and manually test or verify changes between releases
46 |
47 | ### Changes cause unhandled JavaScript errors in services
48 |
49 | If thrown exceptions are left unhandled this will stop script execution, including JavaScript for other components on the page. Some of our components can [fail closed if JavaScript is enabled in the browser but the script fails to run](https://github.com/alphagov/govuk-frontend/issues/999).
50 |
51 | We will treat this as a breaking change and ensure that it is well documented in the release notes.
52 |
53 | This doesn't mean that introducing additional scenarios where the constructor may throw will always be breaking changes. The breaking change is that it's now possible that the constructor may throw, when it never would before.
54 |
55 | ## Alternatives considered
56 |
57 | None.
58 |
59 | ## Implications
60 |
61 | If we see users struggling with error handling when instantiating instances we may consider introducing a 'fail-safe' way of instantiating, for example using a static method on the class that simply logs errors to the console.
62 |
63 | ## Contributors
64 |
65 | - Brett Kyle (@domoscargin)
66 | - Colin Rotherham (@colinrotherham)
67 | - Oliver Byford (@36degrees)
68 | - Romaric Pascal (@romaricpascal)
69 |
70 | ## Associated issues and pull requests (PRs)
71 |
72 |
73 |
74 | ## Outcomes
75 |
76 | - Update the constructors of each component to throw errors if the arguments passed to the constructor are invalid
77 |
--------------------------------------------------------------------------------
/decision-records/001-javascript-for-less-capable-browsers.md:
--------------------------------------------------------------------------------
1 | # JavaScript for less-capable browsers
2 |
3 | **Date:** 2018-05-16
4 |
5 | **Status:** Superseded by [006 - JavaScript browser compatibility](https://github.com/alphagov/govuk-design-system-architecture/blob/main/decision-records/006-javascript-compatibility.md)
6 |
7 | ## Note
8 |
9 | polyfill.io was reported as compromised on 25th June 2024 and we are no longer recommending it as a polyfilling service. Additionally, we have removed the polyfills we created with it from govuk-frontend v5+.
10 |
11 | ## Context
12 |
13 | Before GOV.UK Frontend, our projects used jQuery for DOM interactions, events and data manipulation.
14 |
15 | We’re taking a step back from jQuery due to its lack of support for the browsers we support, its large file size, lack of security updates and from conversations with the community.
16 |
17 | ## Decision
18 |
19 | We’re now writing standard ES5 JavaScript instead, that we polyfill where necessary.
20 |
21 | This means that in places where we would have previously used [`$.each`](http://api.jquery.com/jquery.each/) we’re using [`.forEach`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach) instead, and polyfilling the missing gaps.
22 |
23 | We use polyfills provided by the Financial Times’ [Polyfill service](https://polyfill.io).
24 |
25 | This approach ensures that multiple polyfills can be sourced from this service with greater confidence that they’ll work without conflicting with each other.
26 |
27 | The Polyfill service does not do runtime detection in browsers and instead opts to do this on the server via user-agent sniffing. It only ships the code needed for that browser, which means newer browsers don’t have to run anything. We may investigate lazy-loading in the future, but for now we’re using a bundled approach based on the lowest common denominator.
28 |
29 | We are vendoring these polyfills to avoid any [single point of failure](https://en.wikipedia.org/wiki/Single_point_of_failure) issues that could arise from relying on a CDN. By doing this, we can detect if polyfills are needed at runtime, which results in all browsers getting the same polyfill bundle.
30 |
31 | We hope that our approach can be automated or moved into a reusable npm package, based on the Financial Times [npm package](https://github.com/Financial-Times/polyfill-service#library).
32 |
33 | Here is an [example of polyfilling `addEventListener`](https://github.com/alphagov/govuk-frontend/blob/master/docs/polyfilling.md).
34 |
35 | Any polyfills included in GOV.UK Frontend will be tested to work in supported browsers and devices, including assistive technology. Any community discussion and documentation around potential bugs or downsides will also be considered before deciding to include a polyfill in GOV.UK Frontend.
36 |
37 | ## Consequences
38 |
39 | ### Advantages
40 |
41 | - We’re not forcing projects to include and rely on a specific library
42 | - Developers don’t need to know or learn a specific library
43 | - The JavaScript code is standard and transferable
44 | - It’s very easy to remove the polyfills when older browser support is dropped while keeping the same JavaScript code
45 | - Approach can be easily maintained and used by the community
46 | - Polyfills are widely maintained by the industry
47 |
48 | ### Disadvantages
49 |
50 | - There are risks modifying globals or native object prototypes
51 | - https://www.w3.org/2001/tag/doc/polyfills/#always-encapsulate
52 | - http://perfectionkills.com/whats-wrong-with-extending-the-dom/
53 | - We cannot be sure if our polyfills work with other third party code
54 |
55 | ## References
56 |
57 | - [Polyfills and the evolution of the Web](https://www.w3.org/2001/tag/doc/polyfills/)
58 | - [Polyfill approach discussion on GitHub](https://github.com/alphagov/govuk-frontend/issues/676)
59 |
--------------------------------------------------------------------------------
/decision-records/008-reset-the-javascript-api.md:
--------------------------------------------------------------------------------
1 | # Reset the JavaScript API for our components
2 |
3 | **Date:** 2023-07-20
4 |
5 | **Status:** Accepted
6 |
7 | ## Decision
8 |
9 | In v4.x, for each component class, we will mark all class and instance properties other than the constructor and the `init` method as deprecated.
10 |
11 | In v5.0 we will then add JSDoc annotations to mark the deprecated properties as private. We will also annotate any 'internal' classes or functions (like the `I18n` class and the `mergeConfigs` function) as internal.
12 |
13 | In future releases we will then gradually introduce a new public JavaScript API for components, which is:
14 |
15 | - based on the needs of users
16 | - clearly defined and documented
17 | - comprehensively tested
18 |
19 | ## Rationale
20 |
21 | The JavaScript API for our components has not been designed to be called externally and does not clearly differentiate between public and private methods.
22 |
23 | Many of the methods exposed on the classes or objects can only be called internally as they need to be passed internal state, or are designed to be used internally by the component as event handlers.
24 |
25 | We also have little or no test coverage for calling these methods externally.
26 |
27 | This means that:
28 |
29 | - it's unclear for users whether they are allowed to call or interact with each property
30 | - it's difficult for us to judge what constitutes a breaking change
31 |
32 | 'Resetting' the public API by marking everything else as private gives us the freedom to refactor the internals of the component before then introducing a properly designed, tested and documented public API.
33 |
34 | ## Risks and constraints
35 |
36 | Users who are relying on being able to access now private class or instance properties from from their own code will need to either:
37 |
38 | - wait until we introduce an equivalent way to achieve the same thing using the public API before they can upgrade beyond v5
39 | - continue to use the private properties 'at risk', and manually test or verify changes between releases
40 |
41 | ## Alternatives considered
42 |
43 | ### Do nothing
44 |
45 | We could leave the API as ambiguous, however we know that following other recent major changes to the way that we write JavaScript, we will want to be able to refactor the components to take advantage of newer JavaScript features and to reduce the amount of duplication between components.
46 |
47 | Doing this without a clear definition of the public API will be difficult, as it will be hard to reason whether a particular change is breaking or not.
48 |
49 | ### Maintain the existing API
50 |
51 | We could aim to introduce a new full-featured public API before we remove any of the existing properties. However, it would be difficult to do this without significant refactoring of the existing code, which would almost certainly require the removal or renaming of existing methods and variables. We would also need to introduce comprehensive testing of the existing methods to ensure their behaviour was maintained.
52 |
53 | Aside from the constructor and the `init`` method, none of the existing class or object properties have been designed to be called externally or documented. We believe that the vast majority of our users only interact with the constructor and init methods.
54 |
55 | Therefore we believe the additional engineering effort required to preserve the existing 'accidental' API is not justified.
56 |
57 | ## Contributors
58 |
59 | - Brett Kyle (@domoscargin)
60 | - Colin Rotherham (@colinrotherham)
61 | - Oliver Byford (@36degrees)
62 | - Romaric Pascal (@romaricpascal)
63 |
64 | ## Associated issues and pull requests (PRs)
65 |
66 | - [#3478: Clarify our JavaScript components' public API](https://github.com/alphagov/govuk-frontend/issues/3478)
67 |
68 | ## Outcomes
69 |
70 | 1. In v4.x, deprecate all properties except the constructor and the init method.
71 | 2. In v5.0, mark the deprecated properties as private.
72 | 3. In v5.0, mark internal classes and functions as internal.
73 | 4. In future releases, gradually introduce a properly designed API.
74 |
--------------------------------------------------------------------------------
/proposals/008-simplifying-imports-to-improve-compilation-performance.md:
--------------------------------------------------------------------------------
1 | # Simplifying imports within GOV.UK Frontend to improve compilation performance
2 |
3 | **Closing date:** 1 May 2020
4 |
5 | **Status:** Accepted
6 |
7 | ## Summary
8 |
9 | **This is an iteration of [proposal #7](https://github.com/alphagov/govuk-design-system-architecture/pull/21), based on the feedback we received from that proposal.**
10 |
11 | We’re making changes to the way that the base layers (settings, tools and helpers) are imported within different parts of GOV.UK Frontend’s Sass, to reduce the time it takes to compile to CSS.
12 |
13 | Most of you will not be affected by these changes, and if you import "node_modules/govuk-frontend/govuk/all" you will not need to do anything to benefit from these performance improvements.
14 |
15 | It will have the most impact on you if you import only specific parts of GOV.UK Frontend.
16 |
17 | ## Problem
18 |
19 | It can take a long time to compile GOV.UK Frontend’s Sass to CSS. This is because many of the individual files within GOV.UK Frontend import their own dependencies, even if they would usually have already been imported. We originally did this so that you could import specific bits of GOV.UK Frontend without having to separately import their dependencies.
20 |
21 | Reducing the number of imports within GOV.UK Frontend has been shown to significantly improve the compilation time, as demonstrated in [#1671 Slow compilation of SCSS files in Rails apps](https://github.com/alphagov/govuk-frontend/issues/1671).
22 |
23 | This should particularly improve things for you if you use Sprockets to package your assets, although we expect these changes to improve the compilation time for everyone.
24 |
25 | ## Proposal
26 |
27 | We will implement changes in two stages.
28 |
29 | 1. We can make changes to the imports within components without it being a breaking change, so we’ll do this as part of a v3.x release.
30 | 2. We’ll make the breaking changes to the core, objects and overrides layers in the v4.0 release.
31 |
32 | ### Changes in GOV.UK Frontend v3.x
33 |
34 | We’ll add a new file called `_index.scss` to each component, which contains the component’s styles but does not import the settings, helpers and tools layers.
35 |
36 | We’ll update the existing _[component].scss files to import the settings, helpers and tools layers and import _index.scss. This will preserve the existing behaviour, and continue to provide a single entry point for individual components that can be used in contexts such as React.
37 |
38 | We’ll update `components/_all.scss` to include every component’s `_index.scss` file, avoiding the unnecessary imports of the settings, helpers and tools layers within each component.
39 |
40 | You can still import `/govuk-frontend/govuk/all`, and if you’re doing this you will not need to make any changes to benefit from these improvements.
41 |
42 | You can still import components individually (for example `govuk-frontend/govuk/components/button/button`), but you should update your code to import the index file for each component (instead of the [component].scss) if you want to benefit from the performance improvements:
43 |
44 | ```scss
45 | @import "govuk/settings/all";
46 | @import "govuk/tools/all";
47 | @import "govuk/helpers/all";
48 |
49 | @import "govuk/components/accordion/index";
50 | @import "govuk/components/button/index";
51 | ```
52 |
53 | In preparation for GOV.UK Frontend v4.0, we’ll add deprecation warnings if you import files from the core and overrides layers without first importing the settings, helpers and tools layers.
54 |
55 | ### Changes in GOV.UK Frontend v4.0
56 |
57 | We’ll move the template styles from the core/_template.scss to objects/_template.scss, so that we treat it as an object rather than core styling.
58 |
59 | We’ll remove the imports of the settings, helpers and tools layers from files in core and overrides.
60 |
61 | If you selectively import individual files from core or overrides, you’ll need to import the settings, tools and helpers layers first:
62 |
63 | ```scss
64 | @import "govuk/settings/all";
65 | @import "govuk/tools/all";
66 | @import "govuk/helpers/all";
67 |
68 | @import "core/typography";
69 | ```
70 |
71 | We’ll continue to import the settings, helpers and tools layers from files within the objects layer, so that they can act as single entry points that can be used in contexts such as React.
72 |
--------------------------------------------------------------------------------
/proposals/005-namespace-govuk-frontend-nunjucks-sass-using-a-nested-folder-structure.md:
--------------------------------------------------------------------------------
1 | # Namespace GOV.UK Frontend Nunjucks and Sass using a nested folder structure
2 |
3 | **Closing date:** 2019-06-12
4 |
5 | **Status:** accepted
6 |
7 | ## Summary
8 |
9 | We want to namespace `govuk-frontend` by changing the folder structure for the `govuk-frontend` npm package.
10 |
11 | We are doing this to make it easier for users to import things, in a way that is explicit and avoids conflicts in their application.
12 |
13 | This would be a breaking change in the 3.0.0 release.
14 |
15 | ## Problem
16 |
17 | To import things from GOV.UK Frontend, your application needs to know where to find those things in the filesystem.
18 |
19 | You can do this by providing the full path to the file, for example
20 |
21 | ```javascript
22 | {% from "node_modules/govuk-frontend/components/accordion/macro.njk" import govukAccordion %}
23 | ```
24 |
25 | You can also tell your application which 'include paths' to look in to find things, which allows you to simplify the import path.
26 |
27 | In GOV.UK Frontend, you add the following paths to your 'include paths':
28 |
29 | - `node_modules/govuk-frontend/`
30 | - `node_modules/govuk-frontend/components/`
31 |
32 | You can then import things like this:
33 |
34 | ```javascript
35 | {% from "accordion/macro.njk" import govukAccordion %}
36 | ```
37 |
38 | However, there are 2 issues with this approach at the minute.
39 |
40 | 1. It's no longer clear where the thing is coming from. Those new to the codebase may not realise that it's being imported from an external dependency, because it's not explicit.
41 |
42 | 2. If you create your own accordion component, your application will not know which one to import (or it'll just try and import the first one it finds) as there will be two paths that both match.
43 |
44 | There are 2 ways to get around these issues at the moment:
45 |
46 | 1. You could add the `node_modules` path to your 'include paths'.
47 |
48 | This then allows you to include things referencing govuk-frontend, like this:
49 |
50 | ```javascript
51 | {% from "govuk-frontend/components/accordion/macro.njk" import govukAccordion %}
52 | ```
53 |
54 | However, this is not practical since your application has to search all of the packages in the `node_modules` folder to try and find the thing, which can be very slow.
55 |
56 | 2. Using a custom namespacing in the your codebase, for example:
57 |
58 | ```javascript
59 | {% from "app-accordion/macro.njk" import appAccordion %}
60 | ```
61 |
62 | ## Proposal
63 |
64 | Create a new folder called `govuk/` and move all the GOV.UK Frontend source files into it.
65 |
66 | ```bash
67 | .
68 | ├── README.md
69 | ├── govuk
70 | │ ├── all-ie8.scss
71 | │ ├── all.js
72 | │ ├── all.scss
73 | │ ├── assets
74 | │ ├── common.js
75 | │ ├── components
76 | │ ├── core
77 | │ ├── helpers
78 | │ ├── objects
79 | │ ├── overrides
80 | │ ├── settings
81 | │ ├── template.njk
82 | │ ├── tools
83 | │ ├── utilities
84 | │ └── vendor
85 | ├── govuk-prototype-kit.config.json
86 | └── package.json
87 | ```
88 |
89 | Then you could add the following path to your 'include paths':
90 |
91 | - `node_modules/govuk-frontend/`
92 |
93 | You could then import components like this:
94 |
95 | **Nunjucks:**
96 | ```javascript
97 | {% from "govuk/components/accordion/macro.njk" import govukAccordion %}
98 | ```
99 |
100 | **Sass:**
101 |
102 | ```scss
103 | @import "govuk/components/accordion/accordion"
104 | ```
105 |
106 | **JavaScript:**
107 |
108 | ```javascript
109 | import Accordion from "govuk/components/accordion/accordion"
110 | ```
111 |
112 | Because we can specify [the primary entry point in the package.json](https://docs.npmjs.com/files/package.json#main), you could also import components like this:
113 |
114 | ```javascript
115 | import { Accordion } from "govuk-frontend"
116 | ```
117 |
118 | You can see the [proposed package folder structure](https://github.com/alphagov/govuk-frontend/tree/fb0476423e28eb0410c6810d4ff6ef4ef17d2df2) on GitHub.
119 |
120 | If you'd like to try this out in your application, you can install a pre-release:
121 |
122 | ```bash
123 | npm install --save alphagov/govuk-frontend#fb047642
124 | ```
125 |
126 | ## Acknowledgements / Further reading
127 |
128 | This proposal builds on the contributions from the community.
129 |
130 | Specifically [this proposal is also based on an investigation by HMRC](https://gist.github.com/rpowis/71f3782166e7d835b12ffe7740f6b23e#3-prepend-a-directory-at-the-package-root)
131 |
132 | You can see the [original discussion on GitHub](https://github.com/alphagov/govuk-frontend/issues/870).
133 |
--------------------------------------------------------------------------------
/decision-records/010-remove-init-method.md:
--------------------------------------------------------------------------------
1 | # Remove `init()` method from JavaScript components
2 |
4 |
5 | **Date:** 2023-07-20
6 |
7 | **Status:** Accepted
8 |
9 | ## Decision
10 |
11 |
12 |
13 | We'll be removing the `init()` method from our JavaScript components,
14 | in favour of them initialising automatically during instantiation.
15 |
16 | This simplifies individual component's initialisation from:
17 |
18 | ```js
19 | new Accordion($element).init()
20 | ```
21 |
22 | To:
23 |
24 | ```js
25 | new Accordion($element)
26 | ```
27 |
28 | ## Rationale
29 |
30 | The `init()` method adds an unnecessary step for our components' initialisation, without tangible benefits for what our components do. Without it we can simplify both how our components are initialised, as well as their internal implementation as we're looking to [throw errors at instantiation](./009-throw-errors-component-constructors.md).
31 |
32 | The `init()` method enables the following, that none of our components benefit from, so we can remove that extra step:
33 |
34 | - delaying the initialisation of the component after its instantiation
35 | - allowing the initialisation code to be `async` (which a `constructor` cannot be)
36 |
37 | With our intent to [throw errors at construction](./009-throw-errors-component-constructors.md), having a separate `init()` method requires careful separation between validation of the component in the `constructor()` and initialisation code in a subsequent call. By having only the constructor, the initialisation code can simply `throw` from within `constructor()` to ensure users always get functional instances of our components.
38 |
39 |
40 |
41 | ## Risks and constraints
42 |
43 | ### Reduce or delay the adoption of v5
44 |
45 | This change requires code changes from our users, that they may not have the capacity to implement.
46 |
47 | This is mitigated by the changes being quite small (removing a `.init()` call following the current instantiation of the component) and [only affects a portion of our users](#users-need-to-update-their-code), who use our component classes directly rather than through `initAll()`.
48 |
49 |
50 |
51 | ## Alternatives considered
52 |
53 | ### Deprecating the init method in v5 for future removal in v6
54 |
55 | Because there wasn't really an alternative for users to switch to if we'd deprecated in v4 (if people stopped calling `init()`, there'd be no initialisation), we couldn't make the deprecation in v4.
56 |
57 | Implementing an empty `init()` to document its deprecation in v5 would only delay the update users need to make in their code. This will come at the detriment of the next release: on top of focusing on the topic of that new release, people will also have to update their JavaScript (which is the focus of v5).
58 |
59 | The scope of the change users have to make, which will be documented, as well as our continued support for v4 during a year after we ship v5 seems enough of a mitigation to directly remove the method.
60 |
61 | ### Keeping the `init` method to make use of `async`
62 |
63 | The `init()` method could be made asynchronous, which would isolate the initialisation of each component and allow it to wait for asynchronous calls without blocking the main thread.
64 |
65 | However, since:
66 |
67 | - Asynchronous code requires a deeper understanding of concurrency
68 | - Deferred errors from Promises must be awaited before they throw
69 | - None of our components make asynchronous calls
70 |
71 | We can currently consider the `init()` method unnecessary. That said, we may add asynchronous methods to our components in future.
72 |
73 |
74 |
75 | ## Implications
76 |
77 |
78 |
79 | ### Users need to update their code
80 |
81 | Component initialisation will be reduced to `new Example()` instead of `new Example().init()`. Only users that call component `init()` themselves will need to update their code to reflect this.
82 |
83 | The `initAll()` method will not be affected.
84 |
85 | ## Contributors
86 |
87 | - Brett Kyle (@domoscargin)
88 | - Colin Rotherham (@colinrotherham)
89 | - Oliver Byford (@36degrees)
90 | - Romaric Pascal (@romaricpascal)
91 |
92 | ## Associated issues and pull requests (PRs)
93 |
94 |
95 |
96 | ## Outcomes
97 |
98 |
99 | - Implement the removal of the `init()` method for each of our component
100 | - Document the code update `govuk-frontend` users will need to implement following our removal
101 |
--------------------------------------------------------------------------------
/proposals/003-make-override-classes-consistent.md:
--------------------------------------------------------------------------------
1 | # Make override classes consistent
2 |
3 | **Closing date:** N/A
4 |
5 | **Status:** Accepted (originally raised as a [gist](https://gist.github.com/nickcolley/f135e89ed4b679355b0ab47135b38ee8))
6 |
7 | ## Summary
8 |
9 | We're getting close to 1.0.0 and are tidying up and loose ends for the public API.
10 |
11 | One of the final things we're auditing is the consistency between class names,
12 | we believe if they're more consistent they'll be easier to remember and more intuative.
13 |
14 | ## Problem
15 |
16 | Right now our override classes look like:
17 |
18 | ```
19 | .govuk-!-display-inline {}
20 | .govuk-!-display-inline-block {}
21 | .govuk-!-display-block {}
22 | .govuk-!-m-rN {}
23 | .govuk-!-p-rN {}
24 | .govuk-!-f-N {}
25 | .govuk-!-w-regular {}
26 | .govuk-!-w-bold {}
27 | .govuk-!-width-three-quarters {}
28 | .govuk-!-width-two-thirds {}
29 | .govuk-!-width-one-half {}
30 | .govuk-!-width-one-third {}
31 | .govuk-!-width-one-quarter {}
32 | ```
33 |
34 | (Note for sake of demonstration I've not included all the [spacing classes](https://design-system.service.gov.uk/styles/spacing/#using-the-override-classes))
35 |
36 | Some examples of the short hand classes are:
37 |
38 | - `.govuk-!-w-bold` which sets the font weight to 'bold')
39 | - `.govuk-!-f-30` which sets the font size to 24 (responsively)
40 | - `.govuk-!-mb-r3` which sets the margin bottom to the spacing scale of 3 (responsively)
41 |
42 | ## Proposal
43 |
44 | We're considering making all overrides consistent, this would look like either:
45 |
46 | ### Option 1: Consistently longhand
47 |
48 | ```
49 | .govuk-!-display-inline {}
50 | .govuk-!-display-inline-block {}
51 | .govuk-!-display-block {}
52 | .govuk-!-margin-5 {}
53 | .govuk-!-margin-bottom-5 {}
54 | .govuk-!-padding-0 {}
55 | .govuk-!-padding-bottom-0 {}
56 | .govuk-!-font-size-30 {}
57 | .govuk-!-font-weight-regular {}
58 | .govuk-!-font-weight-bold {}
59 | .govuk-!-width-three-quarters {}
60 | .govuk-!-width-two-thirds {}
61 | .govuk-!-width-one-half {}
62 | .govuk-!-width-one-third {}
63 | .govuk-!-width-one-quarter {}
64 | ```
65 |
66 | #### Pros
67 | - easier to understand what the classes are doing when seeing them for the first time
68 |
69 | #### Cons
70 | - since override classes tend to be used together, verbose class names could make markup verbose
71 |
72 | ### Option 2: Consistently shorthand
73 |
74 | ```
75 | .govuk-!-d-i {}
76 | .govuk-!-d-ib {}
77 | .govuk-!-d-b {}
78 | .govuk-!-m-5 {}
79 | .govuk-!-mb-5 {}
80 | .govuk-!-p-0 {}
81 | .govuk-!-pb-0 {}
82 | .govuk-!-fs-30 {}
83 | .govuk-!-fw-regular {}
84 | .govuk-!-fw-bold {}
85 | .govuk-!-w-3/4 {}
86 | .govuk-!-w-2/3 {}
87 | .govuk-!-w-1/2 {}
88 | .govuk-!-w-1/3 {}
89 | .govuk-!-w-1/4 {}
90 | ```
91 |
92 | #### Pros
93 | - once the naming convention is understood, it is faster to type
94 | - less verbose when composing classes together.
95 |
96 | #### Cons
97 | - higher overhead to learn and remember this naming convention
98 |
99 | ### Composing classes
100 | To explore what it would look like to use the long hand I took some real examples of using overrides from the GOV.UK Design System and put them side by side.
101 |
102 |
103 | #### Service unavailable pages example
104 |
105 | No change:
106 |
107 | ```html
108 | Service unavailable
109 | The submit an employment intermediary report service has closed.
110 | Contact us if you need to speak to someone about the service and your reports.
111 | Telephone:
112 | 0808 157 3900
113 | Opening times:
114 | Monday to Friday: 8:30am to 4:30pm
115 | ```
116 |
117 | Expanded:
118 |
119 | ```html
120 | Service unavailable
121 | The submit an employment intermediary report service has closed.
122 | Contact us if you need to speak to someone about the service and your reports.
123 | Telephone:
124 | 0808 157 3900
125 | Opening times:
126 | Monday to Friday: 8:30am to 4:30pm
127 | ```
128 |
129 | #### Phase banner example
130 |
131 | https://github.com/alphagov/govuk-design-system/blob/cf049adba070d349513313af43ad962fde16914c/views/partials/_banner.njk
132 |
133 |
134 | No change:
135 |
136 | ```javascript
137 | {{ govukPhaseBanner({
138 | tag: {
139 | text: "preview",
140 | classes: "app-tag--review"
141 | },
142 | classes: "govuk-!-pl-r3 govuk-!-pr-r3",
143 | html: phaseBannerText
144 | }) }}
145 | ```
146 |
147 | Expanded:
148 |
149 | ```javascript
150 | {{ govukPhaseBanner({
151 | tag: {
152 | text: "preview",
153 | classes: "app-tag--review"
154 | },
155 | classes: "govuk-!-padding-left-3 govuk-!-padding-right-3",
156 | html: phaseBannerText
157 | }) }}
158 | ```
159 |
160 | #### Start page example
161 |
162 | https://github.com/alphagov/govuk-design-system/blob/cf049adba070d349513313af43ad962fde16914c/src/design-system/patterns/start-pages/default/index.njk
163 |
164 | No change:
165 |
166 | ```html
167 | Registering takes around 5 minutes.
168 |
169 | {{ govukButton({
170 | text: "Start now",
171 | href: "#",
172 | classes: "govuk-button--start govuk-!-mt-r2 govuk-!-mb-r8"
173 | }) }}
174 |
175 | Before you start
176 | ```
177 |
178 | Expanded:
179 |
180 | ```html
181 | Registering takes around 5 minutes.
182 |
183 | {{ govukButton({
184 | text: "Start now",
185 | href: "#",
186 | classes: "govuk-button--start govuk-!-margin-top-2 govuk-!-margin-bottom-8"
187 | }) }}
188 |
189 | Before you start
190 | ```
191 |
192 | ### Related
193 | - https://tachyons.io/ (https://github.com/tachyons-css/tachyons-verbose)
194 | - http://basscss.com
195 |
196 | What do you think? Should we keep these overrides as they are? Or should we make them consistent one way or the other?
197 |
--------------------------------------------------------------------------------
/proposals/004-enable-importing-css-modules-via-filename-convention-used-in-common-frameworks.md:
--------------------------------------------------------------------------------
1 | # Enable importing CSS Modules via filename convention used in common frameworks
2 |
3 | **Closing date:** 2019-02-06
4 | **Status:** Rejected
5 |
6 | ## Summary
7 |
8 | This proposal is a continuation of the [initial conversation raised on the GOV.UK Frontend repository](https://github.com/alphagov/govuk-frontend/issues/1052).
9 |
10 | [CSS Modules](https://github.com/css-modules/css-modules) is a standard way to allow users to import CSS into JavaScript files (commonly known as CSS-in-JS).
11 |
12 | Files imported as CSS Modules automatically are encapsulated by the build tool.
13 |
14 | In order to differentiate between files that should be imported as regular CSS and CSS modules some popular frameworks use a filename convention ‘filename.module.css’.
15 |
16 | This means that end users do not need to provide custom setup to a build tool such as webpack to import the file as a CSS Module.
17 |
18 | Examples of these projects include:
19 |
20 | - [create-react-app](https://facebook.github.io/create-react-app/docs/adding-a-css-modules-stylesheet)
21 | - [Neutrino](https://neutrinojs.org/packages/web/)
22 | - [Gatsby](https://github.com/gatsbyjs/gatsby)
23 |
24 | This may become a standard convention recommended by the CSS Modules specification: [css-modules/css-modules#229](https://github.com/css-modules/css-modules/issues/229)
25 |
26 | ## Problem
27 |
28 | Users can currently import GOV.UK Frontend files into components using a standard import, for example using the [webpack css loader](https://github.com/webpack-contrib/css-loader).
29 |
30 | Downstream projects such as [govuk-react](https://github.com/govuk-react/govuk-react) want to import only the files necessary for each component, then publish these components as separate npm packages.
31 |
32 | If a project like this imported CSS with a default loader conflicts would appear if the components use different versions of GOV.UK Frontend.
33 |
34 | In popular frameworks this is the default unless you use the `filename.module.css` convention, which automatically encapsulates classes.
35 |
36 | Multiple packages is something we [decided against when publishing GOV.UK Frontend](https://github.com/alphagov/govuk-design-system-architecture/blob/master/proposals/002-publish-one-npm-package-instead-of-multiple-npm-packages.md) as we are not sure people having inconsistent parts of the system would be a good idea, and multiple packages is not a requirement to have modular builds (including code splitting).
37 |
38 | However we can’t anticipate how people might want to use GOV.UK Frontend in the future.
39 |
40 | One issue that may arise from a project such as govuk-react trying to use CSS Modules will be that [some of our component CSS selectors reference other components](https://github.com/penx/govuk-frontend/blob/37e44dd2dacecb956299a129c5766aebaed40c06/src/components/character-count/_character-count.scss#L9) CSS selectors, which may not work.
41 |
42 | After speaking to Alasdair McLeay (lead of govuk-react) we agreed that to make components like the Character Count work correctly with CSS Modules we’d have to change the markup, resulting in a breaking change for our other users.
43 |
44 | With this in mind we think CSS Modules will for the most part still be useful for projects in the future and if this form of using CSS becomes more popular in the future we can consider making breaking changes to improve interoperability with CSS Modules but this should not block implementing an imperfect support.
45 |
46 | ## Proposal
47 |
48 |
49 | We would broadly implement support for CSS Modules by doing the following:
50 |
51 | ### 1a. Option 1: Manually create new `.module.scss` entry points for all SCSS files that output CSS
52 |
53 | - Core
54 | - Objects
55 | - Components
56 | - Utilities
57 | - Overrides
58 |
59 | For example:
60 |
61 | ```scss
62 | // header.module.scss
63 |
64 | @import “./header.scss”
65 | ```
66 |
67 | Benefit of this options is it avoids any opaque build step transforms and allows for reasonable adjustments to the module files in the future if necessary.
68 |
69 | ### 1b. Option 2: Automatically create new `.module.scss` entry points for all SCSS files that output CSS with duplicate content
70 |
71 | - Core
72 | - Objects
73 | - Components
74 | - Utilities
75 | - Overrides
76 |
77 | Benefit of this option is the source directory is simpler.
78 |
79 | ### 2. Write guidance in the govuk-frontend installation documentation indicating that we support this CSS Modules filename convention
80 |
81 | ### Guidance
82 |
83 | Since we’re worried that many tools that use CSS Modules also do not support [building projects to the standards we expect](https://www.gov.uk/service-manual/technology/using-progressive-enhancement), we will take a neutral stance in any guidance detailing this functionality to avoid accidentally promoting specific frameworks.
84 |
85 | We would also make a note that this is an alpha / experimental feature.
86 |
87 | ### Pros
88 | - Projects such as govuk-react can have more confidence when their projects are used in common tools that support the CSS Modules file name convention.
89 | - Adds additional future proofing to GOV.UK Frontend
90 |
91 | ### Cons
92 |
93 | #### GOV.UK Frontend is not designed to be imported via CSS Modules
94 |
95 | Some parts of GOV.UK Frontend are not written in a way that work out the box with css modules, and the fixes necessary would be breaking changes for all users.
96 |
97 | #### Duplicate files in published package could be confusing
98 |
99 | If we ensure the guidance is clear we don’t have to make users make a decision and only make CSS Modules a feature for people looking for it.
100 |
101 | #### Risk that recommend tools that don't meet our standards
102 |
103 | We are going to have a neutral stance on css modules in relation to frameworks/tools/bundlers, and leave it to teams to pick the right tools for what they’re building.
104 |
105 | #### Option 2 only: A bigger npm package could mean slower npm installs for all users
106 |
107 | We think the risk of this is low as the files uploaded to npm are first compressed.
108 |
109 | Since duplicated plain text files are easy to compress we hope this would mean the increased size would not impact install time by a large amount.
110 |
111 | We can confirm this by investigating using `npm pack` will create a compressed zip which is the same as published to npm.
112 |
113 | #### Option 2 only: makes the build pipeline more complicated: takes longer, src gets further away from package
114 |
115 | While it does add complexity, it would mostly involve copying and renaming files so we think it’s not a big risk.
116 |
--------------------------------------------------------------------------------
/decision-records/007-javascript-file-formats.md:
--------------------------------------------------------------------------------
1 | # JavaScript file names and formats
2 |
3 | **Date:** 2023-06-27
4 |
5 | **Status:** Accepted
6 |
7 | ## Decision
8 |
9 | We will consolidate all published JavaScript in the [`govuk-frontend` npm package](https://www.npmjs.com/package/govuk-frontend) into a single `govuk` directory.
10 |
11 | We will publish JavaScript in the following formats:
12 |
13 | 1. ECMAScript (ES) modules
14 | 2. ECMAScript (ES) modules, bundled
15 | 3. Universal Module Definition (UMD), bundled
16 |
17 | We will use ECMAScript (ES) modules by default and only bundle JavaScript files that are considered "entry points" into GOV.UK Frontend, such as `all.mjs` and exported components (for example `accordion.mjs`).
18 |
19 | We will change our [GitHub release](https://github.com/alphagov/govuk-frontend/releases) JavaScript `govuk-frontend-${version}.min.js` to ECMAScript (ES) modules format and add it to the published [`govuk-frontend` npm package](https://www.npmjs.com/package/govuk-frontend) without a version number.
20 |
21 | For consistency, we will clearly update our file extensions to:
22 |
23 | 1. Add prefix `.bundle` to bundled JavaScript file extensions
24 | 2. Add prefix `.min` to minified JavaScript file extensions
25 | 3. Always use `*.mjs` for ES modules (except for our [GitHub release](https://github.com/alphagov/govuk-frontend/releases), see constraints below)
26 |
27 | See the example directory listing below to show how files in `govuk-frontend/dist` will be named, further to our [decision to restructure `govuk-frontend`](./005-repository-organisation-for-v5.md):
28 |
29 | ```shell
30 | govuk-frontend/dist
31 | └── govuk
32 | ├── govuk-frontend.min.js # ECMAScript (ES) module bundle, minified
33 | │
34 | ├── all.mjs # ECMAScript (ES) module
35 | ├── all.bundle.mjs # ECMAScript (ES) module bundle
36 | ├── all.bundle.js # Universal Module Definition (UMD) bundle
37 | │
38 | └── components
39 | ├── accordion
40 | │ ├── accordion.mjs # ECMAScript (ES) module
41 | │ ├── accordion.bundle.mjs # ECMAScript (ES) module bundle
42 | │ └── accordion.bundle.js # Universal Module Definition (UMD) bundle
43 | │
44 | └── button
45 | ├── button.mjs # ECMAScript (ES) module
46 | ├── button.bundle.mjs # ECMAScript (ES) module bundle
47 | └── button.bundle.js # Universal Module Definition (UMD) bundle
48 | ```
49 |
50 | ## Rationale
51 |
52 | We can avoid future breaking changes by changing file names and extensions to clearly show:
53 |
54 | * different "flavours" of JavaScript like ES modules
55 | * which files are standalone, bundled or minified
56 |
57 | For example, as explained in our [**JavaScript browser compatibility** decision](./006-javascript-compatibility.md) we may need to add polyfills or transpilation helpers in future.
58 |
59 | Service users can optionally either import `*.bundle.mjs` (ES modules, bundled) or require `*.bundle.js` (UMD, bundled) to include all the polyfills they need, or alternatively import `*.mjs` (ES modules) to use their own bundler.
60 |
61 | ## Risks and constraints
62 |
63 | ### Browser Content-Type headers and `*.mjs` extensions
64 |
65 | Due to poor web server `Content-Type` header support for `*.mjs` files, we've kept the `*.js` extension for our [GitHub release](https://github.com/alphagov/govuk-frontend/releases) JavaScript `govuk-frontend-${version}.min.js` bundle.
66 |
67 | For reference:
68 |
69 | * [Apache issue, resolved May 2022](https://bz.apache.org/bugzilla/show_bug.cgi?id=61383)
70 | * [Nginx issue, unresolved](https://trac.nginx.org/nginx/ticket/2216)
71 |
72 | ### GitHub release format changed to ES modules
73 |
74 | We've changed our [GitHub release](https://github.com/alphagov/govuk-frontend/releases) JavaScript `govuk-frontend-${version}.min.js` bundle format from Universal Module Definition (UMD) to ES modules, but there is a risk that service users will still require UMD.
75 |
76 | ### Maintaining CommonJS compatibilty
77 |
78 | We know that CommonJS compatibility is important for both [Node.js `require('govuk-frontend')` package resolution](https://github.com/alphagov/govuk-frontend/issues/3755) and for test runners that do not support ES modules yet.
79 |
80 | For example, by making our npm package "ESM only" we'd hit issues such as:
81 |
82 | 1. [Jest ECMAScript modules support](https://jestjs.io/docs/ecmascript-modules) needing `--experimental-vm-modules`
83 | 2. [Mocha current limitations](https://mochajs.org/#current-limitations) like [`--watch` mode](https://github.com/mochajs/mocha/issues/4374) only works with CommonJS
84 |
85 | Due to this constraint we've maintained CommonJS support by continuing to package Universal Module Definition (UMD) bundles.
86 |
87 | ## Alternatives considered
88 |
89 | ### Using directories for JavaScript formats
90 |
91 | We considered using directories to show different JavaScript formats but preferred file names and extensions:
92 |
93 | ```shell
94 | govuk-frontend/dist
95 | └── govuk
96 | ├── cjs
97 | ├── mjs
98 | └── umd
99 | ```
100 |
101 | ### Using file extension prefixes for JavaScript formats
102 |
103 | We considered always using `*.js` file extensions and adding JavaScript formats as prefixes, but preferred using prefixes to clearly show standalone, bundled or minified files instead:
104 |
105 | ```shell
106 | govuk-frontend/dist
107 | └── govuk
108 | ├── all.cjs.js
109 | ├── all.mjs.js
110 | └── all.umd.js
111 | ```
112 |
113 | ### Separate CommonJS modules
114 |
115 | We acknowledge the Node.js support constraint above prevents us from removing CommonJS support. That said, we chose not to publish separate `*.cjs` (CommonJS modules) since CommonJS support is still provided by our Universal Module Definition (UMD) bundles.
116 |
117 | ## Implications
118 |
119 | - Users that follow our [**Add the JavaScript file to your HTML**](https://frontend.design-system.service.gov.uk/importing-css-assets-and-javascript/#add-the-javascript-file-to-your-html) or [**Importing JavaScript**](https://github.com/alphagov/govuk-frontend/blob/main/packages/govuk-frontend/README.md#importing-javascript) documentation will need to replace `govuk/all.js` with `govuk/all.bundle.js`.
120 | - Users that directly import/require `govuk/**/*.js` UMD bundles will need to add the `.bundle` extension prefix as `govuk/**/*.bundle.js`.
121 | - Users that directly import `govuk-esm/**/*.mjs` ES modules will need to remove the `-esm` directory suffix as `govuk/**/*.mjs`.
122 |
123 | **Note:** Users that import/require `govuk-frontend` by name are unaffected.
124 |
125 | ## Contributors
126 |
127 | - Brett Kyle (@domoscargin)
128 | - Colin Rotherham (@colinrotherham)
129 | - Oliver Byford (@36degrees)
130 | - Romaric Pascal (@romaricpascal)
131 |
132 | ## Associated issues and pull requests (PRs)
133 |
134 | - https://github.com/alphagov/govuk-frontend/issues/3721
135 | - https://github.com/alphagov/govuk-frontend/pull/3726
136 | - https://github.com/alphagov/govuk-design-system-architecture/pull/28
137 |
138 | ## Outcomes
139 |
140 |
141 |
--------------------------------------------------------------------------------
/decision-records/003-templating-languages.md:
--------------------------------------------------------------------------------
1 | # Templating languages
2 |
3 | **Date:** 2018-07-05 (Historical)
4 |
5 | **Status:** Accepted
6 |
7 | ## Context
8 |
9 | Before GOV.UK Frontend, you needed to use 3 different libraries to build a
10 | service that looked like GOV.UK:
11 |
12 | - GOV.UK Frontend Toolkit
13 | - GOV.UK Template
14 | - GOV.UK Elements
15 |
16 | GOV.UK Template provides the boilerplate, header, footer and related assets like
17 | the favicon, and is available in a number of different formats:
18 |
19 | - a gem containing a Rails engine
20 | - a tarball containing Play Framework templates
21 | - a folder containing Mustache templates
22 | - a tarball containing Liquid templates
23 | - a tarball containing Mustache Inheritance templates
24 | - a tarball containing Jinja templates
25 | - a tarball containing plain HTML and assets
26 | - a tarball containing Embedded JavaScript (EJS) templates
27 | - a JAR file containing assets but no templates, structured as per WebJars
28 | - a tarball containing Django templates
29 |
30 | Making GOV.UK Template available in a number of formats provides a convenient
31 | way for service teams across government to start a new GOV.UK project, despite
32 | the number of different tech-stacks being used.
33 |
34 | These different formats are automatically generated from a base ruby ERB
35 | template through the use of different '[compilers][template-compilers]',
36 | '[packagers][template-packagers]' and '[publishers][template-publishers]' for
37 | each target format.
38 |
39 | GOV.UK Elements, which contains the rest of the UI Elements that you would need
40 | to use, does not support any sort of templating language. The only thing that it
41 | provides is an [npm package containing the Sass][elements-sass]. It relies on
42 | users copying and pasting HTML from the examples in the online documentation.
43 |
44 | The way that the different formats in GOV.UK Template are generated is fairly
45 | simple. It supports the substitution of blocks and variables, but is unable to
46 | handle loops, complex logic or many of the other features provided by most
47 | templating languages. For this reason, we do not think that we could use the
48 | same technique to provide the components in GOV.UK Frontend in multiple formats.
49 | We investigated other ways of doing this in alpha, which are outlined below, but
50 | found that doing so in a reliable way would involve significant work.
51 |
52 | Overall we do not think that the pain points involved in maintaining a setup of
53 | this nature are worth the benefit if we are only able to provide the 'header,
54 | footer and boilerplate in multiple formats, given how rarely they change. The
55 | [HTML in GOV.UK Template has not changed very much][template-changes] in the
56 | years it has existed.
57 |
58 |
59 | ### Pain points
60 |
61 | - The team do not have working knowledge of a number of the target languages and
62 | frameworks. This would make it difficult to fix issues that might be reported,
63 | or to update the template to work with new versions of the different
64 | frameworks that might be released.
65 |
66 | - There are integration tests for some of the target languages and frameworks,
67 | but not all. This makes it difficult to make substantial changes to Template
68 | whilst being confident that those changes will work everywhere unless you do
69 | substantial manual testing. It would be possible to set up test harnesses for
70 | every target language and framework, but this would be significant work.
71 |
72 | - The build pipeline is reasonably complex with a number of downstream builds
73 | being kicked off in other repositories, making it hard to diagnose when issues
74 | arise. It also publishes to a number of different package managers using a
75 | variety of different methods.
76 |
77 | ### Transpiling templates
78 |
79 | [Transpilation][transpilation] is the act of taking source code written in one
80 | language and producing an equivalent version in another language.
81 |
82 | In [alpha][alpha] the team explored ways of doing this by using [shawnbot/meta-
83 | template][meta-template] which converts the source template into an [abstract
84 | syntax tree][ast] and uses that to generate the destination template. We created
85 | a [working example][alpha-transpilation] which involved [adding an ERB
86 | formatter][meta-template-pr] to meta-template.
87 |
88 | However, meta-template was in its infancy and not something we could adopt
89 | without doing significant work. It was also difficult to establish which
90 | templating language features, for example, default variables for variables, were
91 | going to be available in every templating language we wanted or might want to
92 | support, and therefore which features were safe to use in the source template.
93 |
94 | There is also the risk of making contribution more difficult, as contributors
95 | may discover issues with transpilation during development that they do not know
96 | how to solve. For example, tests may fail because they're using a new feature
97 | that either doesn't work in another templating language, or that the transpiler
98 | doesn't know how to transpile.
99 |
100 |
101 | ## References
102 |
103 | There's a [talk by Alice Bartlett from Patterns Day 2017][alice-talk] that
104 | touches on some of these challenges (the most relevant section starts at
105 | around 10 minutes in).
106 |
107 |
108 | ## Decision
109 |
110 | We will use a single templating language which will allow us to define the
111 | markup for a component in a single place.
112 |
113 | We will not build integrations into other languages or frameworks. Our
114 | 'deliverable' will be in the form of one or more npm packages containing the
115 | Sass and JavaScript.
116 |
117 | We may decide to look at transpilation again in the future, based on the
118 | feedback that we get from our users.
119 |
120 | ## Consequences
121 |
122 | We think there is still going to be a need for either libraries or example apps
123 | to help users integrate GOV.UK Frontend into their project, but we hope that
124 | they can:
125 |
126 | - be built and supported by teams and individuals within the community who have
127 | a good working knowledge of the framework or language in question.
128 | - be built in such a way that they do not vendor GOV.UK Frontend, so that they
129 | do not need to be updated every time GOV.UK Frontend is updated.
130 |
131 |
132 | [template-compilers]: https://github.com/alphagov/govuk_template/tree/master/build_tools/compiler
133 | [template-packagers]: https://github.com/alphagov/govuk_template/tree/master/build_tools/packager
134 | [template-publishers]: https://github.com/alphagov/govuk_template/tree/master/build_tools/publisher
135 | [elements-sass]: https://www.npmjs.com/package/govuk-elements-sass
136 | [template-changes]: https://github.com/alphagov/govuk_template/commits/master/source/views/layouts/govuk_template.html.erb
137 | [transpilation]: https://en.wikipedia.org/wiki/Source-to-source_compiler
138 | [ast]: https://en.wikipedia.org/wiki/Abstract_syntax_tree
139 | [meta-template]: https://github.com/shawnbot/meta-template
140 | [meta-template-pr]: https://github.com/shawnbot/meta-template/pull/6
141 | [alpha]: https://github.com/alphagov/govuk_frontend_alpha
142 | [alpha-transpilation]: https://github.com/alphagov/govuk_frontend_alpha/tree/master/lib/transpilation
143 | [alice-talk]: https://vimeo.com/226575101
144 |
145 |
146 |
--------------------------------------------------------------------------------
/decision-records/005-repository-organisation-for-v5.md:
--------------------------------------------------------------------------------
1 | # Restructure govuk-frontend repository for v5
2 |
3 | **Date:** 2023-04-21
4 |
5 | **Status:** Accepted
6 |
7 | ## Decision
8 |
9 |
10 |
11 | To prepare the codebase for v5, we've agreed to make the following changes to the files in our repository and their location:
12 |
13 | 1. Create `govuk-frontend` and `govuk-frontend-review` packages
14 | - Create a `govuk-frontend` npm package.
15 | - Move source files (currently `src` ) and built package files (currently `package`) to this package.
16 | - Keep shipping only the built files to npm for now. We'll use the `files` field of `package.json` to include directories in the shipped package, and `.npmignore` to exclude specific files (like tests)
17 | - Create a `govuk-frontend-review` package for the review app
18 | - Store these in a `packages` folder
19 | 2. Create shared `config`, `lib`, `tasks` and `helpers` packages
20 | 3. Remove the built package files (currently `package`) from version control
21 | 4. Update our release process to make sure we keep checking the changes (possibly manually) between the package to be released and the previous version
22 | 5. Leave `dist` in its current location for now (we may revisit whether it's in version control or at the root in the future). These are compiled files for use without npm.
23 |
24 | This will yield the following structure for our repository:
25 |
26 | ```
27 | govuk-frontend // Repository root
28 | ├── ...
29 | ├── dist // Built files for use without npm
30 | ├── packages // Parent folder for packages
31 | │ ├── govuk-frontend // The GOV.UK Frontend package
32 | │ │ ├── dist // [Previously `/package`] Generated build files, not in version control, ships to npm
33 | │ │ ├── src // [Previously `/src`] Source files, in version control, not shipped to npm
34 | │ │ ├── tasks // Build, release and Gulp tasks for the GOV.UK Frontend Package
35 | │ │ ├── package.json // Ensures dependencies of src, dist and tasks are in-sync
36 | │ │ └── ...
37 | │ ├── govuk-frontend-review // The Review App package
38 | │ │ ├── dist // Not in version control. Some tasks need the review app to build (tests, for example)
39 | │ │ ├── src // [Previously `app/src`] Source files for review app
40 | │ │ ├── tasks // Build and watch tasks for the review app
41 | │ │ ├── package.json
42 | │ │ └── ...
43 | ├── shared // Parent folder for packages shared across the monorepo
44 | │ ├── config // [Previously `/config`] Stores config info like filepaths and ports
45 | │ ├── helpers // Helper functions for development
46 | │ ├── lib // [Previously `/lib`] Shared libraries
47 | │ └── tasks // [Previously `/tasks`] Shared tasks
48 | ├── src // Contains symlinks to new source file locations
49 | └── package.json // Workspaces configuration and top-level dependencies
50 | ```
51 |
52 | ## Rationale
53 |
54 |
55 |
56 | ### Creating `govuk-frontend` and `govuk-frontend-review` packages
57 |
58 | #### **Overview**
59 | These are the packages we "ship" in some form (we publish `govuk-frontend` to npm, and we deploy `govuk-frontend-review` to Heroku), so it makes sense to group them, and the `packages` folder is a convention seen across other repos. This also allows us to better organise our dependencies between the two.
60 |
61 | #### **`govuk-frontend`**
62 | We may need to ship with dependencies in the future. For example:
63 |
64 | - peer dependencies to a polyfill library if we shipped a version compiled with `import` statements for the polyfills (rather than having the polyfills bundled in)
65 | - dependencies to other libraries, if we were shipping a Babel preset or PostCSS configuration
66 |
67 | Moving the source and built files within the same package helps us ensure these dependencies are resolved consistently.
68 |
69 | While we don't yet have any dependencies, moving these files changes the shape of our package, requiring users to update their import paths for Nunjucks, making it a breaking change. Taking advantage of the breaking nature of the v5 release sets us up so we don't have to worry about future dependencies.
70 |
71 | This doesn't force us to ship the source files, which we've decided to exclude (at least for now). We can choose which folders to include via the `files` field in `package.json`, and use `.npmignore` to exclude specific files.
72 |
73 | #### **`govuk-frontend-review`**
74 | The review app uses relative paths (`../../src/...`) to access the components of GOV.UK Frontend. While we cannot make it consume `govuk-frontend` the exact same way our users do (downloading from an `npm` registry), we can get pretty close using workspaces. Making it use `govuk-frontend` directly helps ensure that:
75 | - we're consuming the built files, not rebuilding from source with a process that we have to keep in sync with how the `govuk-frontend` package is built
76 | - the actual files work as intended
77 | - `entries` in `package.json` are properly configured
78 | - dependencies get resolved as expected (we'll still need a different route to test `peerDependency` if we introduce them, though)
79 |
80 | ### Creating config, helpers, lib and tasks packages
81 |
82 | These are all internal tooling packages which we don't ship, which are used across our shipped packages. Grouping them in a `shared` folder is a convenience; the main benefit of splitting them this way is dependency organisation.
83 |
84 | ### Removing built package files from version control
85 |
86 | Since we will be consuming `govuk-frontend` from the `govuk-frontend-review` app, we need to rebuild the `govuk-frontend` package regularly, rather than only at the point of release.
87 |
88 | If we were to leave these built files in version control, we'd risk committing built files that are somewhere between the previous release and the next one. Removing them ensures we can rebuild at will.
89 |
90 | ### Updating our release process
91 |
92 | Including the built files in version control serves as a way to check that there's no weird code sneaking in. Changes to the package get highlighted during the review of the pull request raised to commit the new build of the package and the release.
93 |
94 | We'll need to keep checking for unexplained changes to the package as we release, even if it is by manually diffing for a while (before further automation).
95 |
96 | ### Leaving `dist` in its current location
97 |
98 | `dist` doesn't need to move to enable the previous points, and with the amount of changes in v5, we'll leave it out of the equation for now.
99 |
100 | ## Risks and constraints
101 |
102 |
103 |
104 | - There may be some named-based confusion.
105 | - We previously used `package` as folder to build into, rather than manually edit files. Now, the `packages` folder contains sources.
106 | - Similarly, we'll have a `dist` folder at root, as well as in each package's folder. This will be mitigated somewhat by removing the non-root `dist` folders from version control, but we might want to consider renaming the root `dist` folder to something like `release`.
107 | - External contributors may be used to the current structure of the repository and confused by the relocation. We will help with this by leaving hints in README files and symlinks to the new locations.
108 |
109 | ## Alternatives considered
110 |
111 |
112 |
113 | ### Creating `govuk-frontend` and `govuk-frontend-review` packages
114 |
115 | - Keeping the review app in the `app` folder and repurposing the `package` folder for the `govuk-frontend` package
116 | - This would create some naming confusion since we previously used `package` for automatically built code
117 | - We'd be splitting packages across the base directory, `shared` and `package`, which might be a bit confusing
118 | - Holding off on `govuk-frontend` source files and built package files within the same package
119 | - This would mean waiting for the next breaking change to do it. We may need to have peer dependencies before that release
120 |
121 | ### Creating config, helpers, lib and tasks packages
122 |
123 | - Moving the `shared` folder into the `packages` folder
124 | - The location of the shared folder was kept to root to distinguish it from the "shipped" packages in the `packages` folder
125 |
126 | ### Removing built package files from version control
127 |
128 | - We could also have built the package to a separate folder that's not in version control (for ex. `govuk-frontend-local-build`) to ensure we consume the built files without impacting `package`. We'd have to duplicate efforts to maintain two `package.json` files and lose testing our dependency resolution, package exports and complicate the linting and Dependabot updates.
129 | - Each PR could get a package deployed to the [Github npm registry](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-npm-registry) allowing its installation by the review app down the line. This requires extra infrastructure though, and doesn't help when running locally.
130 |
131 | ## Implications
132 |
133 |
134 |
135 | - Users will need to update their import paths when migrating to v5, which we can document as part of the release notes/migration docs.
136 | - Ongoing new components (Exit This Page, Tasklist) will need to have their sources relocated before they can be merged in the new code structure. We can help with moving things and can release Exit This Page from a support branch if it needs to go before v5.
137 | - We need to keep making sure our configuration for the GOV.UK Prototype Kit gets recognised by the Kit and picks up our files as necessary.
138 |
139 | ## Contributors
140 |
141 |
142 | - Brett Kyle (@domoscargin)
143 | - Colin Rotherham (@colinrotherham)
144 | - Oliver Byford (@36degrees)
145 | - Romaric Pascal (@romaricpascal)
146 |
147 | ## Associated issues and pull requests (PRs)
148 |
149 |
150 | - https://github.com/alphagov/govuk-frontend/issues/3291
151 | - https://github.com/alphagov/govuk-frontend/issues/2886
152 | - https://github.com/alphagov/govuk-frontend/issues/3547
153 | - https://github.com/alphagov/govuk-frontend/issues/3548
154 | - https://github.com/alphagov/govuk-frontend/pull/3498
155 |
156 |
157 | ## Outcomes
158 |
159 |
160 |
161 | Part of the discussion around this decision clarified that the review `app` does not need to take responsibility for all development processes. Performance monitoring, for example, can happily happen in its own workspace and feed the app something to serve if necessary. Same could go for testing that the different compiled versions work appropriately if/when we start shipping more than one variant of compiled files.
162 |
163 | It was also mentioned, discussing the possibility of dependencies, that we'll need to be mindful of the implications of the dependencies we add (provenance, maintenance...).
164 |
--------------------------------------------------------------------------------
/proposals/002-publish-one-npm-package-instead-of-multiple-npm-packages.md:
--------------------------------------------------------------------------------
1 | # Publish one npm package instead of multiple npm packages
2 |
3 | **Closing date:** 2018-03-27
4 |
5 | **Status:** Accepted
6 |
7 | ## Contents
8 | - [Summary](#summary)
9 | - [Current architecture](#current-architecture)
10 | - [Problems associated with publishing individual packages](#problems-associated-with-publishing-individual-packages)
11 | - [Versioning](#versioning)
12 | - [Conflicts](#conflicts)
13 | - [Pancake](#pancake)
14 | - [Proposal: Publishing one package](#proposal-publishing-one-package)
15 | - [Currently](#currently)
16 | - [Steps to build everything](#steps-to-build-everything)
17 | - [Steps to build only one component](#steps-to-build-only-one-component)
18 | - [After proposed change](#after-proposed-change)
19 | - [Steps to build everything](#steps-to-build-everything)
20 | - [Steps to build only one component](#steps-to-build-only-one-component)
21 | - [Risks with moving to a single package](#risks-with-moving-to-a-single-package)
22 | - [Breaking changes that impact many packages could make it difficult to upgrade only parts at a time.](#breaking-changes-that-impact-many-packages-could-make-it-difficult-to-upgrade-only-parts-at-a-time)
23 | - [Options](#options)
24 | - [Reference](#reference)
25 | - [Examples of modular projects that use single packages](#examples-of-modular-projects-that-use-single-packages)
26 | - [Examples of modular projects that use multiple packages](#examples-of-modular-projects-that-use-multiple-packages)
27 | - [With thanks to](#with-thanks-to)
28 |
29 |
30 | ## Summary
31 |
32 | Publish one package with all of GOV.UK Frontend while still allowing for building individual components only.
33 |
34 | GOV.UK Frontend is currently made up of multiple npm packages such as “date-input” and “footer” (see [packages/](https://github.com/alphagov/govuk-frontend/tree/master/packages)).
35 |
36 | This proposal is interested in doing the minimum in order to ship a public release of GOV.UK Frontend.
37 | With the hope that this decision can be changed in the future given more time or better evidence of the need for this.
38 |
39 | ### Current architecture
40 |
41 | GOV.UK Frontend can be consumed in two main ways:
42 | - All at once
43 | - By individual components
44 |
45 | Allowing for individual components is important to:
46 | - Test that they are isolated and do not 'leak' and break other components / elements on a page.
47 | - Makes it easier to deprecate and remove in the future.
48 | - Easier to port to [insert your favourite templating approach here]
49 | - Make it easy to upgrade parts at a time, for example only the new(er) radio components.
50 | - Have smaller builds that only include what is used.
51 |
52 | We have two main aspects of the architecture that allows for this.
53 |
54 | 1. Modular project structure
55 | 2. Individually published packages to npm
56 |
57 | ## Problems associated with publishing individual packages
58 |
59 | ### Versioning
60 | We do not currently have a process to version our individual components before publishing them. If we decide we want to persist with the multiple packages approach, we’ll need to work this out.
61 |
62 | Our current process is to give all packages the same version in lockstep.
63 |
64 | This means all our packages have the same version number, regardless if they have actually changed in a release.
65 |
66 | ### Conflicts
67 |
68 | This is explained really well in [npm and the front end] (thanks Dominik Wilkowski! 💌)
69 |
70 | Currently `button` component and `input` component both depend on the `label` component.
71 |
72 | ```bash
73 | label
74 | ├── button
75 | └── input
76 | ```
77 |
78 | In the current case, these are all versioned in lock-step so when you install the button and input you get a dependency tree that looks like the following:
79 |
80 | ```bash
81 | npm install --save button input
82 | ```
83 | ```bash
84 | label@1.0.0
85 | ├── button@1.0.0
86 | └── input@1.0.0
87 | ```
88 |
89 | However if we made a breaking change to the `label` component, the `button` and `input` component may also require a breaking version update.
90 |
91 | If a user then installs only the `input` component update, this is where we run into issues:
92 |
93 | ```bash
94 | npm install --save button@1.0.0 input@2.0.0
95 | ```
96 | ```bash
97 | label@1.0.0
98 | └── button@1.0.0
99 |
100 | label@2.0.0
101 | └── input@2.0.0
102 | ```
103 |
104 | Now we have a duplication of the label component, and since CSS is a global language depending on how they are imported into a project it'd result in a broken behaviour.
105 |
106 | We use an 'export' pattern that ensures an imported scss partial is only included once (https://github.com/alphagov/govuk-frontend/blob/e583c8b3e4038c09c53d4ffbbc129ea8495efbe9/src/globals/tools/_exports.scss)
107 |
108 | ```css
109 | .govuk-c-label { ... } /* @2.0.0 */
110 | .govuk-c-input { ... } /* @2.0.0 */
111 | .govuk-c-button { ... } /* @1.0.0 */
112 | ```
113 |
114 | As explained in [npm and the front end] npm was designed in a world where this is not a huge concern.
115 | Since backend code can have different versions of the same dependency and not have any global conflicts.
116 | This duplicate backend code is also not sent over the wire and run by users.
117 |
118 | ### Pancake
119 | [Pancake] is a really interesting solution to the above problem built on top of npm, it works around the many issues around `peerDependencies` (see the [npm blog post])
120 |
121 | However, we found in research that many people have big existing build pipelines so adding more tools could be a problem.
122 |
123 | We’d need to do more research to see if pancake would make these problems worse.
124 |
125 | At the moment we’re not clear that the time invested would be worth the problems it solves, however this proposal assumes we could move towards a system like pancake from a single package if a clearer need was presented to us.
126 |
127 | See below for ‘problems with a single package’.
128 |
129 | ## Proposal: Publishing one package
130 |
131 | ### Currently
132 |
133 | #### Steps to build everything
134 | ```bash
135 | $ npm install --save @govuk-frontend/all
136 | ```
137 |
138 | ```scss
139 | // application.scss
140 | @import "@govuk-frontend/all/all";
141 | ```
142 |
143 | ```bash
144 | $ node-sass --include-path=node_modules application.scss > application.css
145 | ```
146 |
147 | #### Steps to build only one component
148 | ```bash
149 | $ npm install --save @govuk-frontend/button
150 | ```
151 |
152 | ```scss
153 | // button.scss
154 | @import "@govuk-frontend/button/button";
155 | ```
156 |
157 | ```bash
158 | $ node-sass --include-path=node_modules button.scss > button.css
159 | ```
160 |
161 | ### After proposed change
162 |
163 | https://github.com/alphagov/govuk-frontend/compare/spike-rfc-packages
164 |
165 | #### Steps to build everything
166 | ```bash
167 | $ npm install --save @govuk-frontend
168 | ```
169 |
170 | ```scss
171 | // application.scss
172 | @import "@govuk-frontend/all/all.scss";
173 | ```
174 |
175 | ```bash
176 | $ node-sass --include-path=node_modules application.scss > application.css
177 | ```
178 |
179 | #### Steps to build only one component
180 | ```bash
181 | $ npm install --save @govuk-frontend
182 | ```
183 |
184 | ```scss
185 | // button.scss
186 | @import "@govuk-frontend/button/button.scss";
187 | ```
188 |
189 | ```bash
190 | $ node-sass --include-path=node_modules button.scss > button.css
191 | ```
192 |
193 | This also means when moving from individual components to multiple components,
194 | you only need to add additional `@import` statements, and would not need to run `npm install` again.
195 |
196 | ### Risks with moving to a single package
197 |
198 | The time it takes to install a big package is longer than individual packages.
199 | Individual packages force us to keep code modular, we would need to ensure our testing makes up for this.
200 | Mental model of custom builds may not be as well understood, we need to do more to make it clear you don’t need the whole project.
201 |
202 | #### Breaking changes that impact many packages could make it difficult to upgrade only parts at a time.
203 |
204 | > “If you’re still creating one version for the entire thing, then when you fix an accessibility bug in one component everyone will have to update the entire thing.” - Dominik Wilkowski GOV.AU
205 |
206 | > “We come from a monolithic CSS (Bootstrap), and the reason for us moving to individual components was that it reduces ‘upgrade anxiety’ and helps with adoption. “ - Dominik Wilkowski GOV.AU
207 |
208 | > "Each component has an API. This API is a combination of CSS classes, HTML structure, Sass mixins, and JavaScript methods. Whenever any of these APIs needs to be deprecated, we release a new Node module with a new version by following semantic versioning.
209 |
210 | > These sorts of breaking changes require our clients to change THEIR code before they can upgrade to the new version.
211 |
212 | >By versioning each component separately....YOU are in control of when you upgrade each component. This gives you flexibility in your timeline. If you are under some time constraint to launch a new feature, then you might wait to upgrade the component.
213 |
214 | > You don't have to feel pressured to upgrade everything right away." - Lynn Jespen, Tech Lead for Material Components Web (via Jani Kraner)
215 |
216 | This has come up multiple times, potentially the risk of this could be improved by releasing often and not ‘save all the big changes’ for a breaking change.
217 |
218 | For example, if we know we’ll be making a breaking change to Component 1 and Component 2. Release Component 1 as a new breaking change, then do another release for Component 2.
219 |
220 | Note: In this case if you only want updates for Component 2, you’ll be forced to also bring in updates for Component 1.
221 |
222 | With a release process that encourages releasing after merging to master this could be possible.
223 |
224 | Without this it would require careful orchestration of releases which could create blockers in our workflow.
225 |
226 | It would also mean we would need to do more to communicate breaking changes that are big fundamental changes, this could be done with release names (see ubuntu for example of ‘code names’ https://wiki.ubuntu.com/Releases)
227 |
228 | This seems to be the biggest risk to publishing one package.
229 |
230 | Please contribute with any risks we have not considered here.
231 |
232 | ## Options
233 |
234 | - Continue with current approach: Flatten and remove conflicts after install ([pancake])
235 | - Approve the proposed change: Publish one package
236 |
237 | ### Reference
238 |
239 | - Transcript of the conversation with the GOV.AU team: https://gist.github.com/nickcolley/eb61fedb20d273a5266cdf4f71cfbb30
240 | - npm blog post introducing the problems relating to the issues described in this RFC: http://blog.npmjs.org/post/101775448305/npm-and-front-end-packaging
241 | - Blog post from Dominik explaining their solution to this problem: https://medium.com/dailyjs/npm-and-the-front-end-950c79fc22ce
242 | - Pancake: https://github.com/govau/pancake/
243 |
244 | #### Examples of modular projects that use single packages
245 | - Bootstrap - High barrier to entry https://getbootstrap.com/docs/4.0/getting-started/build-tools/#tooling-setup
246 | - Foundation - Much better documentation https://foundation.zurb.com/sites/docs/sass.html#adjusting-css-output
247 | - Carbon Design System - http://carbondesignsystem.com/getting-started/developers
248 |
249 | #### Examples of modular projects that use multiple packages
250 | - https://github.com/primer/primer
251 | - https://github.com/ElemeFE/mint-ui - Instructions make no mention of installing individual packages
252 | - https://github.com/fyndiq/fyndiq-ui
253 | - https://github.com/material-components/material-components-web
254 | - https://github.com/govau/uikit
255 |
256 | ## With thanks to
257 | - GOV.AU team for spending time with us to talk through their decisions for their project.
258 | - Lynn Jespen, Tech Lead for Material Components Web
259 | - GOV.UK Design System team
260 |
261 | [npm blog post]: http://blog.npmjs.org/post/101775448305/npm-and-front-end-packaging
262 | [npm and the front end]: https://medium.com/dailyjs/npm-and-the-front-end-950c79fc22ce
263 | [pancake]: https://github.com/govau/pancake/
264 |
--------------------------------------------------------------------------------
/decision-records/006-javascript-compatibility.md:
--------------------------------------------------------------------------------
1 | # JavaScript browser compatibility
2 |
3 | Date: 27/06/23
4 |
5 | Status: Accepted
6 |
7 | ## Decision
8 |
9 | We will publish JavaScript that can be parsed without errors in browsers supporting `