gajus / babel-plugin-react-css-modules

Transforms styleName to className using compile time CSS module resolution.
Other
2.05k stars 162 forks source link

Trying to use with `postcss-easy-import` - Async error #158

Open Nantris opened 6 years ago

Nantris commented 6 years ago

I'm trying to run this using the postcss-easy-import plugin. I've got everything configured "properly" but I get the following error regarding async plugin execution. Is there any way to work around this? Everything runs fine with other (presumably synchronous) plugins.

Thanks very much.

Error:

Use process(css).then(cb) to work with async plugins
    at LazyResult.sync (C:\projects\myapp\node_modules\postcss\lib\lazy-result.es6:310:23)

.babelrc plugin config:

"plugins": [
    "add-module-exports",
    "dynamic-import-webpack",
    "transform-remove-console",
    "transform-remove-debugger",
    "minify-mangle-names",
    "transform-react-jsx",
    [
        "react-css-modules",
        {
          "generateScopedName": "[local]___[hash:base64:5]",
          "filetypes": {
            ".scss": {
              "syntax": "postcss-scss",
              "plugins": ["postcss-easy-import"]
            }
          }
        }
    ]
gajus commented 6 years ago

Currently, there is no way to use async plugins.

igorsvee commented 6 years ago

Currently, there is no way to use async plugins.

Can we have this implemented please? Because it's written in the guidelines for new plugins to make them async and most of them are - import, precss etc.

gajus commented 6 years ago

Can we have this implemented please? Because it's written in the guidelines for new plugins to make them async and most of them are - import, precss etc.

Give it a go. Contributions are welcome.

bpatram commented 5 years ago

I've spent sometime digging into this today and I'm at a loss. I'm not an expert with writing Babel plugins. I've hit a bit of a brick wall and I'm hoping someone can point me in the right direction...

To add support for async postcss plugins we really just need to modify the getTokens function (which is where postcss is run). These lines in particular:

https://github.com/gajus/babel-plugin-react-css-modules/blob/f11d423ae43f2eb57f603bd13cef7f58f0216a07/src/requireCssModule.js#L84-L85

With something like (while making this entire function async -- returning a Promise):

  const lazyResult = await runner
    .process(readFileSync(cssSourceFilePath, 'utf-8'), options);

This actually works just fine, however, obviously now the tokens are not returned synchronously within the babel traversals and this function now returns a Promise.

We can see the getTokens method get called here, when traversing the AST in babel: https://github.com/gajus/babel-plugin-react-css-modules/blob/f11d423ae43f2eb57f603bd13cef7f58f0216a07/src/index.js#L176-L180

At first I tried to just make the entire function be async and calling requireCssModule with an await, but Babel does not support async traversal visitors. You'll get an error like:

You appear to be using a plugin with an async traversal visitor, which your current version of Babel does not support. If you're using a published plugin, you may need to upgrade your @babel/core version.

This is the case in the latest version of Babel, I tried upgrading it in hopes it was supported by now

At this point, I'm not sure what to do... I think to add support for async postcss plugins would require a bit more reworking to this plugin's logic than I was hoping for. Or maybe there is a better way of doing these code manipulations or calling postcss asynchronously than I am aware of.

Thoughts anyone more familiar with Babel plugins than I am?