Next.js - React SSR Cannot find module './page.scss' when rendering on the server (client side rendered works fine after saving the file)

Viewed 1872

When you're using the create-react-app package you're able to have .scss-files compiled into .css-files as you type in them. You can then do import './Header.css'; in your React component files and the styles are applied. It's easy to use your dev-tools and see where the styles are coming from.

Next.js tried to get everyone to use Styled-JSX to have your stylesheets inline inside your JSX files, similar to how web components (or Polymer) do it. I personally strongly dislike that approach.

Other problems:

  • Styled-JSX isn't supported in my IDE (Webstorm) (even the work-around looks awful);
  • Styled-JSX isn't supported in my dev-tools (Chrome) - there is no reference to what line the style is defined at;
  • It makes my source code look like a garbled mess;
  • How do I include 3rd party CSS solutions with Styled-JSX? Am I now supposed to add a <link> to my <head>? For everything external? How is that optimal usage of bandwidth? Referencing to files inside of node_modules feels awkward and bad, too.

So, just add rules to next.config.js, right?

module.exports = {
    webpack: (config, { dev }) => {
        config.module.rules.push(
            {
                test: /\.(css|scss)/,
                loader: "style-loader!css-loader"
            }
        );
        return config
    }
};

And then just import './Page.scss'; (Don't worry, it's valid CSS, not even SASS yet, I know I did not include the sass-loader here just yet. I try to keep it simple first.)

  1. Refresh the page (Server Side Rendered): does NOT work;
  2. Save the file (dynamically loaded after saving the file): it does work (until you reload the page);
  3. Keeps complaining the file can't be found, plenty of Google hits there, too. No real solutions that work today.

So, why doesn't it work with SSR?

1 Answers

Note that v5 of next.js will support CSS/Sass/Less almost out of the box:

For importing .css .scss or .less we’ve created modules which have sane defaults for server side rendering.

Until then, the following set of rules worked for me (assuming the .sass files are in /styles dir):

config.module.rules.push(
  {
    test: /\.(css|sass)/,
    loader: 'emit-file-loader',
    options: {
      // this path is relative to the .next directory
      name: 'dist/[path][name].[ext]'
    }
  },
  {
    test: /\.css$/,
    use: ['babel-loader', 'raw-loader', 'postcss-loader']
  },
  {
    test: /\.sass$/,
    use: ['babel-loader', 'raw-loader', 'postcss-loader',
      { loader: 'sass-loader',
        options: {
          includePaths: ['styles', 'node_modules']
            .map((d) => path.join(__dirname, d))
            .map((g) => glob.sync(g))
            .reduce((a, c) => a.concat(c), [])
        }
      }
    ]
  }
)
Related