babel-plugin-react-css-modules icon indicating copy to clipboard operation
babel-plugin-react-css-modules copied to clipboard

SASS @at-root generated class names do not work with plugin

Open ncrum opened this issue 7 years ago • 8 comments

When using SASS @at-root directive and referencing the parent class name with #{&}, the babel plugin is unable to find a class, but the class exists at runtime. Below is the error I'm getting, here is the basic setup:

.ResultWrapperHeader {
  ...
  @at-root #{&}__title {
    ...
  }
}

Which outputs to:

.ResultWrapperHeader {...}
.ResultWrapperHeader__title {...}

The plugin gives me this error message: Could not resolve the styleName 'ResultWrapperHeader__title'.

This may just be something that is not supported with the babel plugin version, since the plugin would have to process the sass to css in order to know what the class name is. Is there a way around this issue and still use this nested pattern (other than not using nesting)?

ncrum avatar May 03 '17 02:05 ncrum

@ncrum Does it work when you remove @at-root? If so, can you share your config? I'm struggling to get the plugin working with any nested SASS rules, not only those with @at-root.

marcin-mazurek avatar May 12 '17 08:05 marcin-mazurek

I'm not certain the #{&} variable is supposed to work without @at-root, but it doesn't work for me. I did however try:

.ResultWrapperHeader {
  ...
  .ResultWrapperHeader__title {
    ...
  }
}

This kind of nesting works fine, so I'm just going to use this pattern for my scss files, even though it is a little more verbose, which is fine.

Also, if it helps you, this is how I configured my css/scss loaders using webpack 2:

{
    test : /\.(css|scss)$/,
    use : [
        'style-loader',
        'css-loader?importLoader=1&modules&localIdentName=[local]___[hash:base64:5]',
        'resolve-url-loader',
        {
            loader : 'sass-loader?sourceMap',
            options : {
                includePaths : [path.resolve(__dirname, 'app')],
            }
        }
    ],
    include : path.resolve(__dirname, 'app'),
}

ncrum avatar May 12 '17 14:05 ncrum

@ncrum Can you also share your babel-plugin-react-css-modules plugin config?

marcin-mazurek avatar May 15 '17 07:05 marcin-mazurek

I had an issue with nested rules. Created a pull request to support extra postcss plugins, like postcss-nested PR #100

mvsmal avatar Jun 14 '17 08:06 mvsmal

I was having the same issue with standard sass syntax of nesting rules using &. Correct me if I'm wrong, but shouldn't this support sass out of the box without having to use a PostCSS plugin like postcss-nested?

I searched all over the web so far and this was the only solution that actually worked... but somehow I guess I'm still not satisfied that I'm using a PostCSS plugin to to do the work that Sass should be doing...

drewdecarme avatar Sep 01 '17 20:09 drewdecarme

@drewdecarme I did some research a few months ago, it turned out that the plugin does not compile SASS (which is even described in the docs: https://github.com/postcss/postcss#syntaxes). The fact that the postcss-nested works is just an accident, because this plugin has nothing to do with SASS. If you have any other non-standard CSS syntax this will fail again. The proper and safe solution is to pass SASS compiled to CSS to the plugin.

marcin-mazurek avatar Sep 02 '17 07:09 marcin-mazurek

I have a similar issue with the following Less syntax:

.btn {
  // ...
  &--additional-info {
    // ...
  }
}

The plugin prints:

Error: Could not resolve the styleName 'btn--additional-info'.
      
      at node_modules/babel-plugin-react-css-modules/dist/browser/getClassName.js:83:15
          at Array.map (<anonymous>)
      at Object.<anonymous>.exports.default (node_modules/babel-plugin-react-css-modules/dist/browser/getClassName.js:66:6)

My webpack config:

  {
    rules: [
      {
        test: /\.less$/i,
        include: path.resolve(__dirname, 'src'),
        use: ExtractTextPlugin.extract({
          use: [
            {
              loader: 'css-loader',
              options: {
                importLoader: 1,
                modules: true,
                localIdentName: '[local]___[hash:base64:5]',
              },
            },
            'less-loader',
          ],
          fallback: 'style-loader',
        }),
      },
      {
        test: /\.(jsx|js)$/,
        include: path.resolve(__dirname, 'src'),
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: require('./.babelrc.json'),
        },
      },
    ],
  }

My Babel config (.babelrc.json):

    {
      "presets": [
        "es2015",
        "react"
      ],
      "plugins": [
        [
          "babel-plugin-react-css-modules",
          {
            "filetypes": {
              ".less": {
                "syntax": "postcss-less"
              }
            },
            "generateScopedName": "[local]___[hash:base64:5]"
          }
        ]
      ]
    }

michalstocki avatar Oct 24 '17 12:10 michalstocki

Finally I got it to work by adding postcss-nested plugin to a .babelrc.json configuration:

@@ -10,7 +13,10 @@
           {
             "filetypes": {
               ".less": {
-                "syntax": "postcss-less"
+                "syntax": "postcss-less",
+                "plugins": [
+                  "postcss-nested"
+                ]
               }
             },
             "generateScopedName": "[local]___[hash:base64:5]"

michalstocki avatar Oct 25 '17 08:10 michalstocki