Martin van Houte
Martin van Houte

Reputation: 577

Compiling SCSS in Storybook with Gatsby

I have an existing GatsbyJS project and I want to add Storybook to this project to showcase each separate component. I'm using SCSS in my project, which are being compiled with gatsby-plugin-sass, which works great. However, I can't use my components in Storybook since it cannot compile the SCSS files.

I followed the instructions from both Storybook and GatsbyJS. This is how my storybook/webpack.config.js looks like:

module.exports = ({ config }) => {

  // Transpile Gatsby module because Gatsby includes un-transpiled ES6 code.
  config.module.rules[0].exclude =
    [
      /node_modules\/(?!(gatsby)\/)/,
    ];

  // use installed babel-loader which is v8.0-beta (which is meant to work with @babel/core@7)
  config.module.rules[0].use[0].loader = require.resolve('babel-loader');

  // use @babel/preset-react for JSX and env (instead of staged presets)
  config.module.rules[0].use[0].options.presets = [
    require.resolve('@babel/preset-react'),
    require.resolve('@babel/preset-env'),
  ];

  config.module.rules[0].use[0].options.plugins = [
    // use @babel/plugin-proposal-class-properties for class arrow functions
    require.resolve('@babel/plugin-proposal-class-properties'),

    // use babel-plugin-remove-graphql-queries to remove static queries from components when rendering in storybook
    require.resolve('babel-plugin-remove-graphql-queries'),
  ];

  // Prefer Gatsby ES6 entrypoint (module) over commonjs (main) entrypoint
  config.resolve.mainFields = ['browser', 'module', 'main'];
  return config;
};

and my storybook/config.js file looks like this:

import { configure } from '@storybook/react';
import { action } from '@storybook/addon-actions';

// automatically import all files ending in *.stories.js
configure(require.context('../src', true, /\.stories\.js$/), module);

// Gatsby's Link overrides:
// Gatsby defines a global called ___loader to prevent its method calls from creating console errors you override it here
global.___loader = {
  enqueue: () => {
  },
  hovering: () => {
  },
};

// Gatsby internal mocking to prevent unnecessary errors in storybook testing environment
global.__PATH_PREFIX__ = '';

// This is to utilized to override the window.___navigate method Gatsby defines and uses to report what path a Link would be taking us to if it wasn't inside a storybook
window.___navigate = pathname => {
  action('NavigateTo:')(pathname);
};

I assume I need to add a sass-loader to the webpack config, however it does feel a bit unnatural to add another custom loader since GatsbyJS already handles my SCSS files.

I've been fiddling with adding sass-loader, css-loader and style-loader to my webpack.config.js, but I couldn't get it to work.

Also Googling this specific situation doesn't give me a lot of hits. I assume I'm not the first person who tries to do this.

Upvotes: 8

Views: 2263

Answers (3)

Mosesoak
Mosesoak

Reputation: 251

I was able to get it to work by installing @storybook/preset-scss and adding that to the storybook "addons" list (I did not install the additional sass or loader dependencies), and also by modifying storybook's main.js file to import my global styles.

Upvotes: 0

Nikki Pantony
Nikki Pantony

Reputation: 173

I had this same problem.

I solved it by removing my styles.scss from my layout.js as this was causing errors due to not having loaders in Storybook. I then instead included styling in 2 separate locations, one for Gatsby and the other for Storybook which is now working well.


For Gatsby I have included styling in gatsby-browser.js as below:

import "./src/styles/styles.scss"

And for Storybook in .storybook/preview.js as:

import "!style-loader!css-loader!sass-loader!../src/styles.scss"

Adding loader support.


I think Amir Jafari's answer above should also work well.

I have used this method as I also use it to add support for the :focus-visible polyfill for visually testing components in Storybook so I feel this method can be useful for including other packages as well if a suitable Gatsby plugin is not (yet) available.

Upvotes: 1

Amir Jafari
Amir Jafari

Reputation: 19

install this npm package:

npm install sass-loader node-sass webpack --save-dev

and then in the .storybook folder create a file with webpack.config.js name and paste these configs on this file:

module.exports = {
  module: {
    rules: [
      {
        test: /\.s[ac]ss$/i,
        use: [
          // Creates `style` nodes from JS strings
          'style-loader',
          // Translates CSS into CommonJS
          'css-loader',
          // Compiles Sass to CSS
          'sass-loader',
        ],
      },
    ],
  },
};

Upvotes: 2

Related Questions