-
-
Notifications
You must be signed in to change notification settings - Fork 6.2k
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
fix: handle CSS Modules as modules #16018
base: main
Are you sure you want to change the base?
Conversation
Run & review this pull request in StackBlitz Codeflow. |
}, | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These tests are removed because this plugin no longer handles CSS Modules.
) | ||
|
||
expect(await imported.getAttribute('class')).toMatch( | ||
/.composes-path-resolving-module__path-resolving-less___[\w-]{5}/, | ||
/composes-path-resolving-module__path-resolving-less___[\w-]{5}/, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed the .
from these because they match wild-cards in Regex which are unnecessary here.
Nice! Thanks for working on this @privatenumber. I'd like to see what other maintainers think about the separate package. My first impression is that CSS Modules are important enough for this plugin to live directly in Vite core. It will be good to avoid sync issues, for example with internals of Vite you are duplicating. |
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
Currently not sure why nx, rakkas, and unocss are failing—it doesn't seem related to CSS Modules but I'll dig deeper later. |
Gotcha, thanks! Hope it passes now 🙏 Astro is failing because it basically hard-coded the expected hash.
But I thought it was needlessly complex and simplified it to: |
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
Awesome! I prefer having it directly in Vite core for the same reason with @patak-dev.
You can use
getJSON and globalModulePaths are rarely used, but localsConvention is used a lot. |
This comment was marked as outdated.
This comment was marked as outdated.
I updated the hash template to be closer to I agree both As for the plugin, I do agree it would be nice to have CSS Modules in core, and I'm happy to pull it in this PR when ready. I think moving the plugin in will be straightforward, but I think adding the tests will take time for me. Could this be done in a follow-up PR? I do want to point out that Vite previously relied on an external package for CSS Modules ( Would you mind running ecosystem-ci? Will implement getJSON & globalModulePaths soon. |
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
Late to the party. If the Astro fail is only because of hash mismatch, I think we can fix that on the Astro side. About the PR, this is an interesting approach. I don't think we necessarily have to move the entire plugin to core, as I don't think we want to maintain a duplicate CSS modules handling similar to However, If we keep it that way, maybe it makes more sense to upstream this feature directly to |
I think we shouldn't do that. Enabling it will cause browsers that does not support arbitrary module namespace names but specified in By bumping the lowest modern chunk supported version / default
I wonder if that is a bit too magical. But I'm still fine with it. I guess we can check it by whether esbuild throws an error. |
Moving this to the 5.3 milestone. We'd like to keep 5.2 as a small release for now, and keep the larger changes to 5.3. We also need to discuss this approach in the next team meeting before going forward. Personally for me, I'd like to see some of my concerns here addressed. |
@bluwy Thanks for reminding me. Here are my responses inline:
Would like to move away from using
Yeah, the core packages released by the CSS Modules team are PostCSS plugins so it's necessary. But in Lightning mode, it doesn't use PostCSS.
Ah yeah, if Essentially, compiling CSS Modules in the pre-processing step was probably not the best decision.
I think it's better to abstract CSS Module compilation into its own plugin. It processes CSS, but it's quite different from other CSS processors in that it outputs JS. Kind of like with SVGs... there are SVG optimization plugins and there are SVG-to-JS plugins, but you wouldn't want to couple them together as converting the SVG to JS (SVG string or an asset URL) is really an interfacing concern rather than a processing one. It also has quite a bit of complexity, and it even returns a source map. Separating the concerns will improve maintainability & testability (avoiding shoe-horning tests like this). |
Thanks for taking the time to respond! Your explanation about Re I think making CSS modules its own plugin and as a post plugin makes sense. My remaining concern is that I'm not sure if this PR's implementation ( I'd prefer if the CSS modules plugin is written in Vite instead, like mentioned by patak and sapphi. But not entirely inlining // rough idea (not exactly proposing this API)
function compileCSSModule(css: string, options: PostcssModulesConfig | LightningcssModulesConfig):
Promise<{ code: string, css: string, exports: Record<string, any>, map: SourceMap }> That way we can own the CSS modules plugin, and the heavy-lifting/tests are done third-party. I'd hold off implementing this first though to hear what @patak-dev and @sapphi-red think about this. If they prefer to inline everything into Vite, then I can't argue with that too 😅 |
Assuming you're referring to Reason # 6, it's in response to your suggestion to contribute upstream. Reasons for complexity aside, I'm pointing out that adopting their approach comes with a high maintenance cost & engineering complexity that isn't necessary when using with Rollup. I didn't speak to their contribution to Vite + the ecosystem, but I edited the comment for clarity.
I had this idea originally as well, and it's kind of how I implemented it in The plugin calls As I said earlier, I'm OK pulling in (I'm happy to collaborate long-term on this, but just to share my perspective: I've been working on this PR a lot longer than I hoped, and with the workaround, it's hard to keep this priority longer. Giving back to Vite is my primary motivation but the ongoing requests without a clear end-goal can feel unrewarding. If possible, I would love to collaborate incrementally.) |
@privatenumber, we really appreciate you looking into this problem and all the work you already have done here. It will be a big improvement for everyone. This is a big change though. I understand that you feel this was going to be easier to get merged but the discussion so far has been conducted well for the way Vite works and IMO is required to land this correctly with no disruption to the ecosystem and with our eyes on the long term maintainability of the project. I hope you don't get too frustrated by what is the regular flow when adding a new dependency, and we can keep working together. We already decided that this is too big of a change for Vite 5.2, as we want to release the next minor quickly and then focus bigger changes in 5.3 (that currently only have two PRs, this one and the Environment API). Vite 5.3 will be released in around 2 months so there is no rush at this point. Given the discussion above, I'm leaning to pulling in |
Thanks for letting me know the target release is 2 months away—I will plan to follow up with the refactor in a few weeks. To clarify, I'm not asking for it to be released (I'm unblocked via my plugin). Just want to ask for the work to be divided into incremental PRs. Specifically, it would be helpful if there could be a feature branch within Vite, allowing me to merge this PR and open follow-up PRs to it. I can open follow-up PRs now but it would be within my fork. Also, I think we've reached a consensus on pulling |
We have the same issue with the Environment API. What we are doing with it is have an umbrella PR (see #16129), where we are pushing changes from other PRs (see #16137). We also commit directly to it when we don't need a separate space to discuss or trigger ecosystem-ci. You could send a new PR, point this one to it and merge it. And then start sending new PRs against it until it is ready. |
@privatenumber I figured to draft my idea in a local branch to showcase the abstraction I was thinking of. I have a modified version of I thought it was a quick 30min sketch, but I've spent several hours now polishing it up 😅 It kinda works but tests are failing, but I'm not pushing for the branch over-the-line, only mainly to get the idea of the state of this PR so far. The bright side is that I understand some aspects of Happy to collaborate on it though if you'd like, or help take over if the PR is taking a while. Like patak mentioned, we'd like a get it right when making a big change to Vite as we're depended by many frameworks. Note: In the branch, I didn't make CSS modules its own plugin. I discovered that that causes lightningcss to run twice, which I'm not sure is a good default for perf. So I moved the CSS modules handling to |
Wow thank you so much 🙌 Happy to collaborate! Do you have a preferred way for us to chat? I'm determined to get this right as well. And I'm not pressed to get this released because of my plugin. Sorry I'm not sure if I follow. Which branch do you want me to change this PR against? |
@bluwy maybe you could create a new |
Happy to chat about it at the Vite Discord server I think personally I'd hold off having a feature branch to merge in first. I think there's some topics to talk about from this current implementation, like "post-load fallback", "css modules as post-plugin", "different abstraction api", etc. That will be hard to change from a feature branch if we merge it in. The code may look very different after subsequent PRs, but a feature branch is still definitely on-the-table once we have a good direction of the implementation later. |
I only went through the surface, but the idea makes sense to me. Awesome work! Just in case, let me mention Remix's use case of css module since it might not be covered by ecosystem ci. collect css module's css by intercepting `transform` hookhttps://github.com/remix-run/remix/blob/6ad886145bd35298accf04d43bd6ef69833567e2/packages/remix-dev/vite/plugin.ts#L1269-L1272 async transform(code, id) {
if (isCssModulesFile(id)) {
cssModulesManifest[id] = code;
} include css module's css code in SSR style head to avoid FOUChttps://github.com/remix-run/remix/blob/6ad886145bd35298accf04d43bd6ef69833567e2/packages/remix-dev/vite/styles.ts#L77-L79 let css = isCssModulesFile(dep.file)
? cssModulesManifest[dep.file]
: (await viteDevServer.ssrLoadModule(dep.url)).default; Does this idea still work with new js module centric approach or does it need to be written differently? Hopefully I'm not missing what Remix actually does. Maybe it's better to confirm with Remix and Vinxi side. EDIT: I knew about |
Thanks for sharing @hi-ogawa. Yeah since this PR moves the CSS modules handling as a post-plugin, I think that usecase might cause Your edit seems like a good way around it, I would agree that retrieving the CSS for SSR currently is quite clunky, because Vite's API is made around the assumption that files are lazily processed. For reference, here's how Astro (uses links) and SvelteKit (uses Since there's an implementation today that relies on how CSS modules are processed, I wouldn't mind moving the CSS modules handling back as a normal plugin to not break this for now, and in the next major, we could move it as a post plugin. Also, I've talked with privatenumber recently about where to go from here. I've created a new feat/revamped-css-modules feature branch that's squash-merged from this PR and we'll continue iterating from there. I'll be helping around to get this feature finished by Vite 4.3. |
Hey just comming around this issue, will this PR also solve the issue that you get a full page reload on an update of a module.css file? I first thought that this is a vike issue, but it seems to be a vite server render issue? |
I'm not sure what problem you're describing, but this fix is abstracted in the https://github.com/privatenumber/vite-css-modules plugin so you can confirm yourself. The work in this PR has paused. These days, my opinion is that CSS Modules should be a 2nd party plugin. |
An update on my end: I really wanted to pick this back up one day but there's a lot still to get done and verifying that it's compatible to as before (as close as possible). Among the few things I want to check:
Sorry for causing the PR to be stale. The chores laying in front here has caused me to not prioritize this in a while 😅 |
Description
This PR changes how CSS Modules are handled in Vite.
Previously, CSS Modules were bundled at every entry-point via
postcss-modules
. This caused issues, duplicating CSS Module dependencies, and preventing Vite plugins from accessing dependencies.With this PR, CSS Modules are now resolved & bundled by Vite/Rollup by compiling them into individual JS modules.
fixes #15683
fixes #7504
fixes #10079
fixes #10340
fixes #14050 (this one is because I don't use Rollups
dataToEsm
)fixes #16074
fixes #16075
To achieve this, I created a plugin that handles CSS Modules here: https://github.com/privatenumber/vite-css-modules
I realize this approach is somewhat unconventional, but I wanted a way to offer this change both as a patch for users unable to upgrade Vite, and as an integration into Vite core.
It was also easier to scope this logic in a separate repo with tests. And since the previous CSS Modules implementation was an external package, I figured this isn't too far fetched.
Additional context
LightningCSS is ready to go, but I haven't implemented full parity with
postcss-modules
yet:TBH I think these options should be removed in the future, but I can implement them for parity if this is something we want.
What is the purpose of this pull request?
Before submitting the PR, please make sure you do the following
Read the Contributing Guidelines, especially the Pull Request Guidelines.
Check that there isn't already a PR that solves the problem the same way to avoid creating a duplicate.
Provide a description in this PR that addresses what the PR is solving, or reference the issue that it solves (e.g.
fixes #123
).Update the corresponding documentation if needed.
I have not updated documentation yet. Hoping to receive feedback first.
Ideally, include relevant tests that fail without this PR but pass with it.