DEV Community

Molly Gingras
Molly Gingras

Posted on

1

Using custom style loaders with the Neutrino React preset

I’m trying out Neutrino to build a new React project, using its React preset.

By default, Neutrino includes everything I need except custom style loaders for tools like Sass. At first, I tried to define my custom loaders according to Neutrino’s style-loader documentation, updating my .neutrinorc.js like so:

const standard = require('@neutrinojs/standardjs');
const react = require('@neutrinojs/react');
const jest = require('@neutrinojs/jest');
const styles = require('@neutrinojs/style-loader');

module.exports = {
  options: {
    root: __dirname,
  },
  use: [
    standard(),
    react({
      html: {
        title: 'app-title'
      }
    }),
    jest(),
    styles({
      test: /\.(css|sass|scss)$/,
      modulesTest: /\.module\.(css|sass|scss)$/,
      loaders: [
        {
          loader: 'postcss-loader',
          options: {
            plugins: [require('autoprefixer')],
          },
        },
        {
          loader: 'sass-loader',
          useId: 'sass'
        },
      ],
    })
  ],
};

Unfortunately, this setup threw an error when I started my dev server:

DuplicateRuleError: @neutrinojs/style-loader has been used twice with the same ruleId of 'style', which would overwrite the existing configuration. If you are including this preset manually to customise rules configured by another preset, instead use that preset's own options to do so.

It wasn’t immediately obvious to me what was going on here, and Google led me to a couple of people with the same problem, but no solutions.

Soon enough, though, I realized that the React preset was already using style-loader under the hood. style-loader’s behavior within the React preset is configurable through a property in the preset's options object called style. I had missed that option because it's documented as part of the Web preset, and not redundantly included in the React preset's docs.

So I adjusted my module.exports accordingly:

module.exports = {
  options: {
    root: __dirname,
  },
  use: [
    standard(),
    react({
      html: {
        title: 'app-title'
      },
      style: {
        test: /\.(css|sass|scss)$/,
        loaders: [
        {
          loader: 'postcss-loader',
          options: {
            plugins: [require('autoprefixer')],
          },
        },
        {
          loader: 'sass-loader',
          useId: 'sass'
        },
      ]
      }
    }),
    jest()
  ],
};

Et voilà, it worked.

TL;DR: If you’re using Neutrino’s React preset (or presumably any of its web presets), you’ll need to configure your custom style loaders within that preset’s options object, using the style property.

I hope this helps someone who’s run into the same issue.

Heroku

Amplify your impact where it matters most — building exceptional apps.

Leave the infrastructure headaches to us, while you focus on pushing boundaries, realizing your vision, and making a lasting impression on your users.

Get Started

Top comments (0)

Image of PulumiUP 2025

Let's talk about the current state of cloud and IaC, platform engineering, and security.

Dive into the stories and experiences of innovators and experts, from Startup Founders to Industry Leaders at PulumiUP 2025.

Register Now

👋 Kindness is contagious

Engage with a wealth of insights in this thoughtful article, valued within the supportive DEV Community. Coders of every background are welcome to join in and add to our collective wisdom.

A sincere "thank you" often brightens someone’s day. Share your gratitude in the comments below!

On DEV, the act of sharing knowledge eases our journey and fortifies our community ties. Found value in this? A quick thank you to the author can make a significant impact.

Okay