Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] feat: add rollup-plugin-include-css #4609

Closed
wants to merge 3 commits into from

Conversation

joshblack
Copy link
Member

@joshblack joshblack commented May 20, 2024

Summary

This Pull Request is an experiment which adds a custom Rollup plugin, rollup-plugin-include-css, into Primer React so that we can ship generated CSS files alongside components so that consumers only include the CSS they use.

Motivation

As we move towards CSS Modules, it's important that we prioritize the overall size of a component and its styles. The current behavior when using CSS Modules along with Rollup is that there will be a single CSS file emitted. This would create a tension where someone using @primer/react would get all the styles for every component instead of only the styles for components they use. Over time, the size of this CSS bundle will grow even if the styles for specific components does not.

This approach looks to make it so that a consumer of @primer/react only uses the styles they need for the components they import.

Detailed design

The main addition here is through a custom rollup plugin, rollup-plugin-include-css, which will go through the following steps:

  • If the plugin encounters a CSS module file, it will:
    • Process the file with postcss
    • Get the generated classes and emit a JS module that a component will use to refer to classes
    • Emit a CSS file that contains the generated CSS with the mapped classes
    • Import the CSS file inside the generated CSS module classes file

With this approach, we know that if the classes for a CSS Module file are imported then the associated styles for that file are also imported.

On the library side, the package only needs to import and use this plugin in their rollup config. It includes support for custom ostcss and postcss-modules options and will emit the CSS files relative to their position in the source directory. For example:

dist/Blankslate
├── Blankslate-c90a59c9.css
├── Blankslate.d.ts
├── Blankslate.js
├── Blankslate.module.css.js
└── index.d.ts

Here, Blankslate.module.css.js will include the CSS Modules classes and will also import Blankslate-c90a59c9.css which contains the CSS that corresponds to those classes.

In addition, the library should specify that these files contain side-effects.

Drawbacks

The main drawback is that this is a custom rollup plugin that our team will need to maintain. Since we aren't familiar with writing rollup plugins, there could be potential issues down the road with maintaining it.

It also isn't immediately clear how to address things like imports between CSS files, or if we will run into ordering problems if component CSS is imported in different orders.

Alternatives

Alternatives to this approach include:

  • Generating a single CSS file for the bundle for folks downstream to consume
  • Emit CSS files and require downstream teams to include them along with the JS import for a component

Unresolved questions

Questions

What's the impact downstream for consumers with this RFC?

Hopefully nothing! 🤞 Folks should be able to import components and use them the way they normally do. The only caveat to this is that they should make sure that their bundler (whether that's webpack, vite, parcel, next, etc) can in interpret CSS imports from JavaScript files.

What does the generated CSS look like?

This is something that is configurable through CSS Modules and can be changed over time. Details for the parts we can use are available here. One option could be to do something like:

prc_[name]_[local]

Which would give you something like:

prc_Blankslate_heading

This would indicate that the styles for this are in the Blankslate file under the heading class.

Copy link

changeset-bot bot commented May 20, 2024

⚠️ No Changeset found

Latest commit: 18b3492

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@github-actions github-actions bot temporarily deployed to storybook-preview-4609 May 20, 2024 16:13 Inactive
Copy link
Contributor

size-limit report 📦

Path Size
packages/react/dist/browser.esm.js 88.49 KB (0%)
packages/react/dist/browser.umd.js 88.84 KB (0%)

@joshblack
Copy link
Member Author

cc @primer/engineer-reviewers would love your feedback if you have a sec this week! Will also bring this up in our working session 👀

Copy link
Member

@broccolinisoup broccolinisoup left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really like the idea, especially when we compare it with the alternatives, I think this is a good way to go and thanks for writing a roll up plugin from scratch, this is so cool 🔥

  1. Do you think adding some tests in the plugin and adding it to the CI help with the maintenance? I feel it might be less cryptic if the plugin tests fail when there is an issue rather than primer/react build step fails - curious to hear your thoughts 🙌🏻
  2. I assume adding this plugin wouldn't impact the component that don't have the css modules yet?
  3. Do you think we should open source it under Primer in a separate repo or would it make more sense to keep it in the monorepo here?

@@ -0,0 +1,45 @@
# rollup-plugin-include-css
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohh, you wrote this plugin!! I totally missed that point 😄 This is so cool!! 🔥

@joshblack
Copy link
Member Author

@broccolinisoup

  1. Do you think adding some tests in the plugin and adding it to the CI help with the maintenance? I feel it might be less cryptic if the plugin tests fail when there is an issue rather than primer/react build step fails - curious to hear your thoughts 🙌🏻

Happy to take a look and see how hard this would be 👀 Always down for adding testing 👍

  1. I assume adding this plugin wouldn't impact the component that don't have the css modules yet?

The components that don't import css will not be effected but if the components are in the same entrypoint then it might impact them 😞 This would be because when trying to resolve the component that does not use CSS modules it would find a file that does in the same entrypoint and could potentially error out if what they are using does not understand importing CSS files

  1. Do you think we should open source it under Primer in a separate repo or would it make more sense to keep it in the monorepo here?

I think it would make sense to keep it in the monorepo so that we don't have to worry about publishing the package. It'd be great if we could keep it private for now and if we need to publish it we could either do so from here or move it to a separate project if that makes sense.

@joshblack
Copy link
Member Author

Opened up: #4650 to add the rollup plugin to the project 👀 Going to close out this RFC!

@joshblack joshblack closed this Jun 7, 2024
@joshblack joshblack deleted the feat/add-rollup-plugin-include-css branch June 7, 2024 16:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants