Local less stylesheets for React components

- 1 answer


I started a React project using redux-easy-boilerplate (https://github.com/anorudes/redux-easy-boilerplate/tree/master/src)

I really like how each component in the boilerplate is styled with an individual local SCSS file. I'm actually porting an old app that relies on LESS, and I want to reuse the styling from that app.

I'm trying to just directly replace SCSS with LESS in this boilerplate and I'm running into an issue I can't understand. Here's a typical component in it: https://github.com/anorudes/redux-easy-boilerplate/tree/master/src/components/Footer . It has a styles directory containing two files - index.js:

import 'style!./styles.scss';
export default require('./styles.scss').locals.styles;

and styles.scss such as this:

:local(.styles) {
  text-align: center;
  padding: 70px 0 40px;

If I just rename scss file to less, I get error saying that cannot get property 'styles' of undefined (being locals), pointing to second line of index.js. I don't really know SCSS and don't understand what the first line of the scss file does and what would be the LESS equivalent for it.

BTW, I did add the LESS loader to webpack config:

  test: /\.less$/,
  loader: 'style!css!less',



I believe there's a couple things going on here.

The first thing is, you replaced the loader for the SCSS files

loader: 'css?localIdentName=[path]!postcss-loader!sass'

with this loader for Less files

loader: 'style!css!less'

but they aren't equivalent. In the former configuration, the sass loader converts the SCSS syntax to regular CSS, postcss-loader runs additional post-processing based on PostCSS, and the css?localIdentName converts this all down to plain CSS after resolving imports and URLS — but additionally creates local scopes based on the ?localIdentName=[path] query parameter. From the css-loader docs:

By default CSS exports all class names into a global selector scope. This is a feature which offer a local selector scope.

The syntax :local(.className) can be used to declare className in the local scope. The local identifiers are exported by the module.


You can configure the generated ident with the localIdentName query parameter (default [hash:base64]). Example: css-loader?localIdentName=[path][name]---[local]---[hash:base64:5] for easier debugging.

So without that query parameter, you will not get the .locals.styles property on your required CSS.

Additionally, you should not be using the style-loader as part of your loader config, because you don't want to inject the styles by default; you want to be able to require the styles (so you can get access to the locals) and additionally inject them. That's why the boilerplate has the following as part of styles/index.js for each set of styles:

import 'style!./styles.scss';
export default require('./styles.scss').locals.styles;

The first line injects the styles, and the second line exports the locals.

So, I think you simply need to change your webpack configuration to:

test: /\.less$/,
loader: 'css?localIdentName=[path]!postcss-loader!less',
source: stackoverflow.com