Replies: 2 comments 9 replies
-
@chaance from the Remix Team was prototyping CSS modules support in #2489 he probably could weigh on this esbuild approach you're proposing |
Beta Was this translation helpful? Give feedback.
-
Really solid proposal, IMO. Thanks for the explanation as well! This is actually somewhat similar to our plan for CSS Modules, with the obvious difference being the modules part. We had planned on starting with a virtual module that compiles everything into a single module that could be imported in the |
Beta Was this translation helpful? Give feedback.
-
I personally think that remix is doing a fantastic job in "not hiding how things work" and I'm a fan of that, but at the same time I think remix is making it hard / very verbose to have scoped styles. So I've been digging into some kind of automation of collecting the stylesheets which should be surfaced and I think I found a elegant solution to it. With this post I want to gather feedback from you guys and wanna know whether you think this could be a thing which is worth to have "native" support in remix:
1. Whats the problem:
In an modern web app I want to have component scoped stylesheets and I don't want to take care of re-exporting them correctly all the time.
1.1. How is it done now?
Like described here: https://remix.run/docs/en/v1/guides/styling#surfacing-styles
1.2. Why is the current solution not optimal?
Developers have to take extra care with stylesheets handling and the code ends up very verbose.
2. Proposed solution:
What I'm proposing is not to replace or get rid of any of remix concepts, I just want to have "helpers" which makes it more convenient to use remix concepts such as the links export.
So what if we could analyze each route and detect the used stylesheets automatically. This detected styles are gathered in a virtual module, which exports them as an array. This virtual module would look something like this:
Note that the array has the correct order of styles according to the import order of the styles. Now that we have this information it only needs to be exposed. This can be done however you think is best, but I'll propose it as a simple import. Something like
import styles from './index.<suffix>.js';
. This file is not there obviously, its just a virtual one which is resolved byesbuild
.Now instead of surfacing each style component by component we would end up with an correctly sorted array of stylesheet paths, which the consumer can use. Its by the way completely up to the consumer whether to use this strategy or not, this is 100% additional and is not breaking anything.
The consumption would look something like this:
Since the consumer has still full control over everything he could decide to just use a fraction of the array, or to use any
media
options etc. This is really just an helper for getting the urls, its not doing anything with them and if the helper is unused it gets treeshaken.2.1. Implementation:
The implementation is done with
esbuild
and itscss
loader. Esbuild is able to generate a css file for each entry point (https://esbuild.github.io/content-types/#css-from-js), this css file doesn't have to be written to disk (write: false
) and can be analyzed in the metafile object (https://esbuild.github.io/api/#metafile). In this metafile object you'll find all the information needed (all the used stylesheets in the correct order). After this information is gathered we just need to write the virtual-module and we are finished.2.2. Implications:
With this utilities it would be very easy to implement other stylesheet based css systems like e.g.
css-modules
because they only need to be imported in order to show up in the virtual modules array export.The resulting behavior per route would be that each route consists not of one but possibly more stylesheets depending on how long the array is. The benefit of that is that shared stylesheets can be cached and other routes with similar stylesheets doesn't have to download everything.
Other benefit are CSS Order and No unused CSS, because each route has its own array, the order is correct per route and in comparison to one big bundled css file where half of the styles could be unused we have certainty that all of the styles in the array are used in this route.
2.3. Possible Improvements:
This section only describes what could be added on top of this system. Its just me thinking about possible future features, this is not part of the proposal and only shows what could be possible:
Since the virtual module is exporting an array of stylesheet paths, it could be decided to add more information to the array if needed. There could also be a field in the remix config where someone can adjust how the array is generated and what data are in it.
3.0. Negatives
Obviously this system brings overhead, but since remix needs to process its stylesheets anyways to fix bugs (#4130) this could be implemented right into this step. Additionally the implementation logic is only "run esbuild and use its output", which is not a very complex behavior in comparison what it could be with other things.
Beta Was this translation helpful? Give feedback.
All reactions