storybook: Can't resolve assets file path in SCSS file

Describe the bug When importing a file using @import, it seems that there is a problem with the image path of the imported file. The relative path of the file in SCSS should be based on the imported target file, but it doesn’t seems to be. (Please see code snippet)

Expected behavior

  • Must search the file path based on the mixins folder path

Code snippets

.storybook/main.js

const path = require('path');
module.exports = {
  stories: ['../src/**/*.stories.tsx'],
  addons: ['@storybook/addon-actions', '@storybook/addon-links'],
  webpack: async config => {
 ...
    config.module.rules.push(
      {
        test: /\.scss$/,
        use: ['style-loader', 'css-loader', 'sass-loader'],
        include: path.resolve(__dirname, '../'),
      },
    );
...
    return config;
  },
};

src/index.scss

@import "~src/shared/_mixins";
@include test;

src/shared/_mixin.scss

@mixin test {
  background: url("./images/img.svg"); // << not works, but moving image directory to 'src' work fine.
}

directory

.storybook/
src/
 - index.tsx
 - index.scss
 - shared/
    -_mixin.scss
    - images/
      - img.svg

Output: ERROR in ./src/index.scss (./node_modules/css-loader/dist/cjs.js!./node_modules/sass-loader/dist/cjs.js!./src/index.scss) Module not found: Error: Can’t resolve ‘./images/test.svg’ in ‘/Users/test/src/index’

System:

  System:
    OS: macOS High Sierra 10.13.6
    CPU: (4) x64 Intel(R) Core(TM) i5-2500S CPU @ 2.70GHz
  Binaries:
    Node: 10.15.3 - ~/.nvm/versions/node/v10.15.3/bin/node
    npm: 6.12.0 - ~/.nvm/versions/node/v10.15.3/bin/npm
  Browsers:
    Chrome: 83.0.4103.61
    Firefox: 72.0.2
    Safari: 13.1.1
  npmPackages:
    @storybook/addon-actions: ^5.3.19 => 5.3.19 
    @storybook/addon-links: ^5.3.19 => 5.3.19 
    @storybook/addons: ^5.3.19 => 5.3.19 
    @storybook/preset-scss: ^1.0.2 => 1.0.2 
    @storybook/react: ^5.3.19 => 5.3.19 
  npmGlobalPackages:
    @storybook/cli: 5.0.11
    @storybook/react: 5.0.11

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 26 (10 by maintainers)

Most upvoted comments

@Bruno-Daldegan

I had solved this (assets file path) issue by using method-1 i.e. import '!style-loader!css-loader!resolve-url-loader!sass-loader!../src/styles/my-global-file.scss' in version 5 of storybook.

After a few months, I upgraded storybook to V6 and found that I no longer needed to use method-1 and I could just write import '../src/styles/my-global-file.scss' in preview.js file (and it would let me resolve assets file paths).

To answer your question, I had style-loader "^1.0.0", css-loader "^3.0.0", resolve-url-loader "^3.1.2" and sass-loader "^10.0.5", in my yarn.lock file, when I was using V5 of storybook. Now, I would simply recommend you to try the latest V6 of Storybook.

PS: I used storybook in a React project built with CRA.

I’ve resolved this issue by referring to the content below.

// next.config.js const path = require(“path”);

module.exports = { webpack(config, options) { config.resolve.alias[“images”] = path.join(__dirname, “./src/assets”); return config; }, };

Hey, finally figured it out, wouldn’t have been possible without your help, thanks man

Thanks @PFight , your suggestion helped resolve my path issue (solution below).

I’m using NextJS + SCSS + NextJS public folder for font files + Storybook.

The issue was css-loader was trying to resolve the URL when I needed it left as is.

// .storybook/main.js
module.exports = {
  addons: [
    "@storybook/preset-scss",
  ],
  staticDirs: ["../public"],
  webpackFinal: async (config) => {
    for (let rule of config.module.rules) {
      if (rule.use && rule.use.length > 0) {
        for (let use of rule.use) {
          if (use.loader && use.loader.includes("/css-loader/")) {
            use.options = {
              ...use.options,
              url: (url, resourcePath) => !url.startsWith("/"),
            };
          }
        }
      }
    }
    return config;
  },
};

My erroring SCSS file:

@font-face {
  font-display: optional;
  font-family: "Arial Narrow";
  font-style: normal;
  font-weight: 400;
  src: url("/ArialNarrow.woff2") format("woff2"); // font file is in /public/
}

Error:

ModuleBuildError: Module build failed (from ./node_modules/css-loader/dist/cjs.js):
Error: Can't resolve '/ArialNarrow.woff2' in '/Users/jack.matthews/Development/github/doyoutrackid/next-frontend/styles'

You can use resolve-url-loader to fix the problem-with-url in one of the following ways:

  1. If you are using inline loaders (e.g. in .storybook/preview.js file):
import '!style-loader!css-loader!resolve-url-loader!sass-loader!../src/styles/my-global-file.scss'

or

  1. If you want to specify the loaders by extending the storybook’s webpack config (in .storybook/main.js):
const path = require('path');
module.exports = {
  webpackFinal: async (config, { configType }) => {
    config.module.rules.push({
      test: /\.scss$/,
      use: ['style-loader', 'css-loader', 'resolve-url-loader', 'sass-loader'],
      include: path.resolve(__dirname, '../'),
    });
    return config;
  },
};

Found next solution (for css, not scss):

   for (let rule of config.module.rules) {
	if (rule.use && rule.use.length > 0) {
		for (let use of rule.use) {
		  if (use.loader && use.loader.includes("css-loader")) {
			use.options.url = false;
		  }
		}
	}
   }

@lethanhtupk If you want to use absolute path, try using alias feature in webpack. but, this setting must be applied to both the storybook and the project webpack.

@phong10119 @stegano thanks for the response I’ve tried to put sourceMap option but got the same result On my scss file. I use background-image with url('/images/icons/triangle-right.svg')

directory

public/ 
  - images/  
      - icons
          .svg files in here
styles/
  - components/ 
      - elements/ 
         - scss files in here

I found that if I changed the path in scss file into ../../../public/images/icon/triangle-right.svg, then bookstory work fine. So I think I need to use resolve-url-loader to change the url into relative path as above but don’t know how to do that yet

Hi, @stegano I’m facing the error exactly the same as you. My config in main.js as below

...
config.module.rules.push({
      test: /\.s[ac]ss$/i,
      use: ['style-loader', 'css-loader', 'resolve-url-loader', 'sass-loader'],
      include: path.resolve(__dirname, '../'),
})

The error output is

Error: Can’t resolve ‘/images/icons/triangle-right.svg’ in ‘/home/tult/RikkeiSoft/pms-frontend/styles/components/elements’

Seems like you missing this? It’s in resolve-url-loader doc

Screen Shot 2021-01-05 at 10 30 01

Thank you @stegano, I had to make the import in global.module.scss relative. It works now!