Odas0R
Odas0R

Reputation: 41

How can I use static assets on scss with storybook?

I have a scss library under styles/ folder where I have code like this:

// Variables
$path-to-img: "/img" !default;
$path-to-fonts: "/fonts" !default;

// Example use case
.bg-pattern-2 {
  background-image: linear-gradient(to bottom, transparent 0%, $black 100%), url('#{$path-to-img}/patterns/pattern-2.png');
}

In Next.js, I have all the static assets under the public/ folder, so:

public/
------- img/
------- fonts/
------- ...
       

But when I try to run start-storybook -p 9000 it gives me an error:

enter image description here

It makes a lot of sense that this error is thrown, but how can I really solve this?

With webpack in specific?

Upvotes: 1

Views: 3778

Answers (1)

Odas0R
Odas0R

Reputation: 41

Well, I figured it out.

First of, you can run yarn storybook --debug-webpack to take a quick look at the structure of Webpack configuration.

After some debugging, I could see that the publicPath was "", so this means that the assets needed to be in .storybook folder under it the /img and /fonts folders

Why?

Because the html output that renders the Storybook app is on that same path with injected CSS files, and one of them is the css given by the sass-loader.

Solution:

  webpackFinal: async (config, { configType }) => {
    // Add Sass to storybook
    config.module.rules.push({
      test: /\.scss$/,
      include: path.resolve(__dirname, "../styles"),
      use: [
        {
          loader: "style-loader",
        },
        {
          loader: "css-loader",
          options: {
            url: false, // This was the important key ** see explanation
          },
        },
        {
          loader: "sass-loader",
        },
      ],
    });

    // Copy all assets to publicPath
    config.plugins.push(
      new CopyPlugin({
        patterns: [
          {
            from: path.resolve(__dirname, "../public/fonts"),
            to: "./fonts", 
          },
          {
            from: path.resolve(__dirname, "../public/img"),
            to: "./img", 
          },
        ],
      })
    );

    return config;
  },

options {url: false} This was the key to my problem. Well, basically when you have:

// Example use case
.bg-pattern-2 {
  background-image: linear-gradient(to bottom, transparent 0%, $black 100%), url('#{$path-to-img}/patterns/pattern-2.png');
}

the css-loader will create his own urls, so the injected css will have the wrong path to the images.

By disabling it, we can then copy those assets with copy-webpack-plugin to the publicPath of webpack, where will all function accordingly.

Upvotes: 2

Related Questions