uswds / web-components

Work on the next version of USWDS will happen here
https://federalist-c7964e49-2db7-4585-85f1-49d23b9329cb.sites.pages.cloud.gov/site/uswds/uswds-next/
28 stars 5 forks source link

Configure monorepo to build component packages #5

Open heymatthenry opened 5 months ago

heymatthenry commented 5 months ago

Users should be able to add component packages to their projects a la carte without having to have the entire design system installed. This becomes especially important if/when components are distributed via CDN for buildless installation. In order to support these use cases, each component needs to be able to be built with just the bare minimum dependencies required for that specific component. On our end, that means setting this project up as a monorepo with separate package configurations for each component.

The issues referenced here all have a subtask for configuring them to build as independent packages. There's some basic configuration in #1 for using an npm monorepo, but nothing (yet) in the actual package directory to build that package separately from building at the level of the project root. In addition to configuring component package builds, it may be worth investigating whether an alternative package manager (like pnpm or yarn) or a package manager coupled with additional monorepo tooling (Nx or something like that) could make this process easier.

anselmbradford commented 4 months ago

At the CFPB we're publishing several npm packages out of a single monorepo and I'm actually looking into moving away from that setup. It would arguably be a better dev experience to be able to install the whole design system package (within reason, assuming it's not ginormous) and then pick out the individual components as needed.

For example, we currently have code like:

import { Expandable } from '@cfpb/cfpb-expandables';
import { Multiselect } from '@cfpb/cfpb-forms';

A nicer setup might be to have

import { Expandable, Multiselect } from '@cfpb/cfpb-design-system';

…which simplifies the publishing (we currently use lerna to manage the monorepo and could remove that), and simplifies the interdependence between the different packages within the design system.

If all the scripts within the design system package are ES6 modules, picking them out from a single package should be straightforward.

A more complicated part is how to handle the CSS. In your code, everything is in the JS, so it looks like you could still pick individual components out via a JS pathway. Alternatively, some build systems (i.e. esbuild) can take source files that reference CSS in the JS and spit out a CSS file.

This doesn't help your buildless CDN scenario. To address that, what may work is to have your build spit out an individual dist file for each component. It doesn't seem like these would need to be in a different npm package—they'd just need to be built at different dist URIs that are available via a CDN. In fact, couldn't you already build the index.js files from each package (e.g. https://github.com/uswds/uswds-next/blob/develop/src/components/usa-banner/index.js) and point a CDN to the built file for each?

Anyway, I'm sure I'm missing something here, but food for thought. A bunch of interconnected npm modules can be a pain that may not be worth it!