typescriptnext.jswebpacksassturbopack

How to change scss classname generation pattern (output format) in Next.js with Turbopack?


I am using latest Next.js and sass (scss) in my project. Here is next.config.ts configuration:

import type { NextConfig } from 'next';
import createNextIntlPlugin from 'next-intl/plugin';

import '~/env';

const nextConfig: NextConfig = {
  webpack: config => {
    // Add svgr loader
    config.module.rules.push({
      test: /\.svg$/,
      use: ['@svgr/webpack'],
    });

    return config;
  },
  images: {
    // https://nextjs.org/docs/pages/api-reference/components/image#devicesizes
    deviceSizes: [360, 430, 576, 768, 992, 1440, 1920],
    // https://nextjs.org/docs/messages/next-image-unconfigured-host
    remotePatterns: [
      // ...
    ],
  },
  // https://sass-lang.com/d/legacy-js-api
  // https://github.com/vercel/next.js/issues/71638#issuecomment-2431137842
  sassOptions: {
    silenceDeprecations: ['legacy-js-api'],
  },
  experimental: {
    turbo: {
      rules: {
        '*.svg': {
          loaders: ['@svgr/webpack'],
          as: '*.js',
        },
      },
    },
  },
};

const withNextIntl = createNextIntlPlugin('./src/shared/config/i18n/request.ts');
export default withNextIntl(nextConfig);

Also I am using Turbopack in development mode.

I am getting this output for generated scss class names...

Container-module-scss-module__5CxIxW__root
Header-module-scss-module__4xIsZW__content

... and I want it to be somewhat like this:

Container-5CxIxW__root
Header-4xIsZW__content

Is it possible to achieve?

I've already tried multiple strategies:


Solution

  • If you disable Turbopack (by running NEXT_USE_TURBOPACK=0 next dev) and use Webpack, you can override the class name generation like this:

    webpack(config) {
      const cssRule = config.module.rules.find(
        rule =>
          typeof rule === 'object' &&
          rule !== null &&
          'oneOf' in rule
      );
    
      if (cssRule && 'oneOf' in cssRule) {
        cssRule.oneOf?.forEach(rule => {
          if (
            rule &&
            typeof rule === 'object' &&
            rule.use &&
            Array.isArray(rule.use)
          ) {
            rule.use.forEach((u: any) => {
              if (
                u.loader?.includes('css-loader') &&
                u.options?.modules
              ) {
                u.options.modules.localIdentName = '[name]-[hash:base64:6]__[local]';
              }
            });
          }
        });
      }
    
      return config;
    }
    

    This gives me class names like:

    Container-5CxIxW__root
    

    This customization doesn’t work—Turbopack seems to ignore localIdentName and uses its own internal naming scheme.