Govuk-frontend: Allow importing Nunjucks macros with a namespace without mounting 'node_modules'

Created on 4 Jul 2018  ·  16Comments  ·  Source: alphagov/govuk-frontend

I've just moved from the beta to v1.0.0 of the Frontend and I am wondering why you moved from the @ namespace in npm?

I was setting my nunjucks path to the @govuk-frontend folder and then my import path would be, for example, frontend/components/error-summary/macro.njk. I liked this as it was clear where the macro was coming from and it kind of namespaced the govuk stuff, which allowed me to use the same naming conventions, like a components folder etc (and worked the same for SASS frontend/settings/_colours.scss to import the govuk one and then settings/_colours.scss for my project one)

To get around this for nunjucks I just made the include path node_modules so I can specify govuk-frontend/components/... this works fine except for my tests have now gone from ~2s to ~13s. I assume this is because of the vast amount of folders in node_modules, so does anyone have any solutions for this?

submitted by user 🕔 days

Most helpful comment

Hey Graham,

Sorry for the delay, we've spoken about this as a team.

We want to make this easier so you don't have to do work around in your own code, but we think doing any of these suggestions will result in a breaking change.

So we're going to assign this to the 3.0.0 release, let us know if this is blocking you as it may be a while before we do a 3.0.0 release.

Nick

All 16 comments

A quick work around for this is to name any conflicting components folders with app-.

Longer term possible solutions:

  1. We use the @govuk namespace
    This would bring it back to what we had before, but without a confusing scope.

{% from "frontend/components/button/macro.njk" import govukButton %}

Then ask users to mount only node_modules/@govuk


  1. We give each component folder a govuk- namespace
    package/components/govuk-button/macro.njk

{% from "govuk-button/macro.njk" import govukButton %}

Then users could mount the components folder without conflicting.


  1. We give the component folder itself a namespace component
    package/govuk-components/button/macro.njk

{% from "govuk-components/button/macro.njk" import govukButton %}

Then ask users to mount only node_modules/govuk-frontend


  1. We nested everything inside a 'govuk' directory.

{% from "govuk/components/button/macro.njk" import govukButton %}

Then ask users to mount only node_modules/govuk-frontend/

Tbh after thinking about it I don't see any naming conflicts as my project components won't have the same folder structure components/<name>/macro.njk vs components/<name>.njk so I assume nunjucks can handle this.

A quick work around for this is to name any conflicting components folders with app-.

For now I may take a mix of this and option 3 above and apply it to my project, so:

{% from "app-components/button.njk" import button %}

My biggest concern for this is making it clear that some of these components are project ones and some are govuk-frontend ones. Having the same components/ at the start seems too confusing and magical.

From a consumer of govuk frontend point of view I like option 2 and 3 as it's clear in the templates that this is a govuk import. I realise it then makes the folder structure weird from a govuk-frontend developer point of view, but maybe it is a nice compromise?

I think option 2 is probably the best:

1) You can keep the components as the folder name in the govuk project
2) It makes the import statements cleaner and shorter
3) You can keep the govuk-frontend package name in npm - so less breaking changes and pain moving it
4) All sass items are prefixed with govuk- so keeps it consistent?

@nickcolley There are also a performance issues when adding node_modules as an import path for SASS, going to have to use app-components and app-settings as a workaround, option 2 would probably be good for that case too?

Actually that may not be true, seems my SASS takes a second or two to register the file being changed, compilation is still pretty quick. Although the clarity would still be nice for the SASS files too.

I think these:

@import "settings/all";
@import "helpers/all";
@import "tools/all";
@import "core/typography";
@import 'core/lists';
@import "objects/width-container";
@import "objects/form-group";
@import "overrides/typography";
@import "overrides/spacing";

Would be nicer like this:

@import "govuk-settings/all";
@import "govuk-helpers/all";
@import "govuk-tools/all";
@import "govuk-core/typography";
@import 'govuk-core/lists';
@import "govuk-objects/width-container";
@import "govuk-objects/form-group";
@import "govuk-overrides/typography";
@import "govuk-overrides/spacing";

Thoughts?

Any movement on this?

Hey Graham,

Sorry for the delay, we've spoken about this as a team.

We want to make this easier so you don't have to do work around in your own code, but we think doing any of these suggestions will result in a breaking change.

So we're going to assign this to the 3.0.0 release, let us know if this is blocking you as it may be a while before we do a 3.0.0 release.

Nick

We have the same problem with HMCTS Frontend.

For example, we have a HMCTS specific Header. And Header exists inside GOV.UK Frontend.

Now it just so happens that we'd probably never want both Header's appearing in the same view, but still it illustrates our problem. We had to name our header, “global-header” which isn't ideal.

I like {% from "govuk-button/macro.njk" import govukButton %} fwiw.

Perhaps we should do this ourselves and end up with:

{% from "hmcts-button/macro.njk" import hmctsButton %}

We're looking at something related to this for HMRC and would like to follow the convention if there's one decided upon.

The conflict we have is between HMRC's header and govuk's header but it would be good to solve this problem for future conflicts too. We can follow the previous comment from @adamsilver and use

{% from "hmrc-header/macro.njk" import hmrcHeader %}

If the interface is still up for discussion I'd personally suggest a parent directory rather than each item requiring a prefix:

{% from "hmrc/header/macro.njk" import hmrcHeader %}

We've also looked at a variety of other options here https://gist.github.com/rpowis/71f3782166e7d835b12ffe7740f6b23e

Has anyone implemented this yet? We'd go for consistency over personal preference.

@matcarey As far as I can tell if you have any of those options you should be fine for the future, since the problem here is that GOV.UK Frontend and user code is both assuming no namespaces.

I'd propose in an ideal world everything would have some sort of namespace?

Shared across GOV

{% from "govuk-header/macro.njk" import govukHeader %}

Shared across service / department

{% from "hmrc-header/macro.njk" import hmrcHeader %}

In an individual application

{% from "app-header/macro.njk" import appHeader %}

This means at each layer it's clearer where you are importing from.

Note: the prefix could be one of your options you've tried...

That namespace makes sense to me. There's a level of commitment when anyone starts implementing it and more when someone releases using this interface.

I'll start working towards HMRC using the above approach (hmrc-header/macro.njk) on the basis that myself (for HMRC) and Rory (for HMRC), @adamsilver (for HMCTS), and @nickcolley (from a GDS perspective) seem comfortable with this convention.

If anyone wants to suggest a different convention now would be a great time. Alternatives include but are not limited to the ones in Rory's gist https://gist.github.com/rpowis/71f3782166e7d835b12ffe7740f6b23e

Just as an FYI, I updated HMCTS Frontend yesterday to follow the following convention as per @matcarey's message:

hmcts-header/macro.njk

https://github.com/hmcts/frontend/tree/master/src/components

Just to update, we will be doing changes to namespacing as part of 3.0.0.

We met and discussed the options proposed here and we're going to write up an architecture proposal to suggest using govuk/ namespace which would include sass and nunjucks files.

Great to hear @nickcolley and thanks for the update. Any idea on timescales for the 3.0.0 release?

@web-bert we're hoping for late June, but keep your eyes peeled.

The milestone shows the current development work we're planning to do, and we have other guidance/documentation work that's underway too...

Milestone: https://github.com/alphagov/govuk-frontend/milestone/8

Superceded by #1451. Thanks everyone for your input – it's been really helpful 👍

Was this page helpful?
0 / 5 - 0 ratings