-
Notifications
You must be signed in to change notification settings - Fork 0
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
Investigate alternative CSS bundlers #46
Comments
Tried using I imagine this is still solvable as ESBuild works the same way but is directly supported in The easier solution for now was to use The main challenge I haven't solved yes is that I had to use relative CSS imports for now for Parcel to resolve files correctly. Even that likely only works because the two files I was importing happen to both be source files. If one was generated, it would exist in a different artifact root and Parcel wouldn't know to look there. Workspace-relative imports also wouldn't work. Parcel does seem to support custom resolvers (example), so this could likely be solved. I'll have to experiment a little more. Current progress is at ref/parcel. |
I took a deeper look at a custom resolver, however it seems that |
In the Loading and calling the bundler was relatively straightforward. Unfortunately there doesn't seem to be a good way of defining an explicit output path, so I used an in-memory filesystem for Parcel and then manually forwarded the result to the real filesystem. I think it may be possible to get Parcel to do the right thing without this trick, but this should be good enough for now. The biggest challenge was loading a resolver plugin. This turned out to be quite involved as plugins are defined in the I eventually got Parcel to accept a provided One other challenge I haven't fully solved yet is how to ship this plugin approach to downstream users.
Depending on how hard getting this to work in external workspaces is, I'm starting to wonder if it would be easier to fork I'll also follow up with Parcel folks to confirm that I really do have to go through all this NPM nonsense. It's a lot of ceremony to deal with in order to import a plugin, and there should definitely be a simpler way to do this. |
Snapshot of the current state is in ref/parcel-2. |
One other note: I had to abuse a global variable in order to have the CSS import map loaded into the Parcel binary get passed through the resolver plugin. Since Parcel manages loading and creating the plugin, there is no way to pass through use case specific context, and this was the best workaround I could find. |
Latest suggestion is to implement the resolver in Rust since that API is actually supported. I hacked on it a bit and managed to get something working in ref/parcel-3, the Bazel side is infinitely simpler this way. That said I do have a few concerns:
This definitely feels better than trying to use the Parcel API, but there's a lot of new Rust-based problems I'm not familiar with which will take some solving before this becomes a viable approach. |
Since |
Refs #46. This is blocking the Node.js upgrade past v12 and the feature doesn't really work anyways as it isn't currently linked properly in the output. See: bazelbuild/rules_postcss#73. Hopefully a future migration to Parcel will put us back in a position where CSS sourcemaps can be used.
I just realized that the actual |
In #48, we've now moved to I took a pass at this today and was able to make it work relatively easily. I'm not a fan of the dependency layout. After figuring out the dependencies I was able to make it work without too much effort. I got it working in an external workspace and was even able to remove all the PostCSS stuff, though Parcel is using PostCSS under the hood. I haven't bothered with strict deps yet, and it might be out of scope for this issue, but that would definitely be good to add sooner than later. |
Refs #46. This tool calls `lightningcss` (formerly `@parcel/css`) to bundle the given entry points and output them to the specified locations. I considered using the `parcel` CLI directly, but that included a lot of other functionality around compiling JavaScript, GraphQL, YAML, etc. `lightningcss` is a more narrowly defined package with a smaller dependency graph, which makes this easier to work with. It also includes a CLI, and I considered calling `lightningcss-cli` directly, but this was a bit easier to work with when bundling multiple files at the same time.
Refs #46. This adds a new `css_bundle()` target which calls the `css_bundler` binary (using `lightningcss`) to bundle all the given CSS files. This rule is then swapped in for `postcss_multi_binary()` for use across the whole project. This necessitated updating `css_library()` to copy all its sources to the bin directory to be compatible with the `css_bundler` `js_binary()` target downstream. I would have liked to land this in a separate commit, but it actually breaks the `@bazel/postcss` pipeline since that relies on the bundled file having the same name as its entry point. Partially for this reason, I ended up changing the output file paths of the bundled CSS files. Instead of generating the bundled CSS to use the same basename, I rerooted the whole execroot under the target. So if you bundle a file at `@some_wksp//path/to:file.css` at `@some_other_wksp//path/to/pkg:bundle` it will output the bundled version at: ``` .../execroot/some_other_wksp/path/to/pkg/bundle/some_wksp/path/to/file.css ``` Including the workspacename and putting everything under the bundle target means every input file as a 1:1 correlation with its output file, and there is no potential ambiguity or conflict.
Refs #46. The import map is only ever generated as part of `css_bundle()`. It needed to be a different rule before because `postcss_multi_binary()` was a macro and needed to be called at that level. But now that `css_bundle()` is a custom rule, we can generate the import map directly, which is much more straightforward.
Refs #46. These are no longer used since the implementation has been completely swapped over to Parcel.
Before I refactor and merge the branch using the After spending some time with that, I was able to make a |
Currently we use
rules_postcss
for bundling CSS files, however it's current support level seems to be in a weird place (see bazelbuild/rules_postcss#73 and bazelbuild/rules_postcss#74).rules_prerender
doesn't really have strict requirements here beyond resolving@import
and the wayrules_postcss
does this is unnecessarily complicated IMHO. It would be worth investigating Parcel or ESBuild as an alternative CSS bundler which might be simpler, more modern, and more maintainable.rules_nodejs
has a Parcel example, though this seems intended for bundling JavaScript, not CSS.Also see #34 for a separate investigation into ESBuild for bundling JS. Using the same tool for both pieces of the build could have other maintainability advantages.
The text was updated successfully, but these errors were encountered: