johanholmerin / style9

CSS-in-JS compiler inspired by Meta's stylex
MIT License
570 stars 27 forks source link

Breaks with latest version of Next #55

Closed TxHawks closed 2 years ago

TxHawks commented 2 years ago

After upgrading next from v12.0.2 to v12.0.10, I am getting the following error when building:

TypeError: rawOptions.postcss is not a function

I did not have time to investigate, but my guess is that this is the same issue as https://github.com/seek-oss/vanilla-extract/issues/522, which they seem to have been fixed in https://github.com/seek-oss/vanilla-extract/pull/537

TxHawks commented 2 years ago

And here's a basic reproduction repo: https://github.com/txhawks/style9-next-repro

Just yarn && yarn build to see the error

johanholmerin commented 2 years ago

Thank you for the detailed report & reproduction. Unfortunately fixing this(without breaking support for earlier versions of Next.js) is non-trivial, since the plugin currently passes options to css-loader inline as a string, meaning it's not possible to supply a Promise without rewriting the plugin. Next.js & Webpack have already caused a lot of trouble, and they are not projects I use or ever intend to use, so I'm not going to spend any more time on them. If anyone wants to create a PR that fixes this without breaking support for older versions I would of course be happy to accept it. In the meantime I'm adding a note to the documentation.

TxHawks commented 2 years ago

Thanks for the prompt reply, and fair enough.

I'll try and see if there is a way to fix the issue without breaking compatibility with older versions, but if impossible, I'd point out that next@12.0.5, where the breakage occurs, also includes an important security patch, so it might be a good idea to transition the plugin's compatibility to be next>=12.0.5 rather than the other way around.

In the event that keeping backwards compatibility proves impossible, would providing two plugins be acceptable to you? maybe next-legacy and next?

johanholmerin commented 2 years ago

Having a legacy plugin for older versions seems like a reasonable compromise to me.

TxHawks commented 2 years ago

Okay, I'll try and give it a go. Hopefully can find some time for it next week or the one after.

Any pointers as to where to start would be appreciated

SukkaW commented 2 years ago

A temporary solution will be to use css-loader directly for style9's virtual css. Next.js's built-in pre-compiled css-loader really does nothing special.

Next.js's webpack workflow is designed in a way that everything is cachable. The css can be cached, and no longer needs to be compiled/emit again, thus no need for PostCSS to be loaded eagerly.

But it is not the same case for Style9. Style9's css is virtual and is dependent on the jsx/tsx, thus can't be cached or persistent.

since the plugin currently passes options to css-loader inline as a string, meaning it's not possible to supply a Promise without rewriting the plugin.

So here is my idea:

Style9's webpack plugin uses [path][name].[hash:base64:7].css as the name of virtual css. We can make this name configurable for Style9's loader (E.g. we can specify [path][name].[hash:base64:7].style9.css. The name really doesn't matter, as it is virtual. The real, emitted css file's name is created by MiniCssExtractPlugin). With the configured name, we can add a new rule along with loader's option fir the virtual css (E.g. rule: /\.style9\.css$/i).