How can I configure Storybook.js Webpack to work with absolute image paths in CSS modules in a Next.js project?
Asked Answered
T

4

8

I am trying to configure Storybook to work with Next.js, Ant Design, Less, and TypeScript. In Next.js, images have to be stored in the public/ folder and referenced with absolute paths to be used throughout the project. I am having trouble configuring the Storybook.js webpack to be able to resolve these absolute image paths.

For example, in a CSS module I could have:

.testImage {
  background-image: url('/images/cucumber.png');
  background-repeat: no-repeat;
  background-size: contain;
  height: 300px;
  width: 300px;
}

But Storybook will fail when building with this error:

ERROR in ./common/layout/TestImage/TestImage.module.css (./node_modules/css-loader/dist/cjs.js??ref--15-1!./common/layout/TestImage/TestImage.module.css)
Module build failed (from ./node_modules/css-loader/dist/cjs.js):
Error: Can't resolve '/images/cucumber.png' in '/Users/gerritvanderlugt/Development/misc/storybook-issue/common/layout/TestImage'
    at /Users/gerritvanderlugt/Development/misc/storybook-issue/node_modules/enhanced-resolve/lib/Resolver.js:209:21
    at /Users/gerritvanderlugt/Development/misc/storybook-issue/node_modules/enhanced-resolve/lib/Resolver.js:285:5
    at eval (eval at create (/Users/gerritvanderlugt/Development/misc/storybook-issue/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:15:1)
    at /Users/gerritvanderlugt/Development/misc/storybook-issue/node_modules/enhanced-resolve/lib/UnsafeCachePlugin.js:44:7
    at /Users/gerritvanderlugt/Development/misc/storybook-issue/node_modules/enhanced-resolve/lib/Resolver.js:285:5
    at eval (eval at create (/Users/gerritvanderlugt/Development/misc/storybook-issue/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:15:1)
    at /Users/gerritvanderlugt/Development/misc/storybook-issue/node_modules/enhanced-resolve/lib/Resolver.js:285:5
    at eval (eval at create (/Users/gerritvanderlugt/Development/misc/storybook-issue/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:27:1)
    at /Users/gerritvanderlugt/Development/misc/storybook-issue/node_modules/enhanced-resolve/lib/DescriptionFilePlugin.js:67:43
    at /Users/gerritvanderlugt/Development/misc/storybook-issue/node_modules/enhanced-resolve/lib/Resolver.js:285:5
    at eval (eval at create (/Users/gerritvanderlugt/Development/misc/storybook-issue/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:16:1)
    at /Users/gerritvanderlugt/Development/misc/storybook-issue/node_modules/enhanced-resolve/lib/Resolver.js:285:5
    at eval (eval at create (/Users/gerritvanderlugt/Development/misc/storybook-issue/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:16:1)
    at /Users/gerritvanderlugt/Development/misc/storybook-issue/node_modules/enhanced-resolve/lib/Resolver.js:285:5
    at eval (eval at create (/Users/gerritvanderlugt/Development/misc/storybook-issue/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:16:1)
    at /Users/gerritvanderlugt/Development/misc/storybook-issue/node_modules/enhanced-resolve/lib/Resolver.js:285:5
 @ ./common/layout/TestImage/TestImage.module.css 2:12-115 9:17-24 13:7-14 45:20-27 47:4-60:5 49:6-59:7 50:38-45 56:26-33 58:21-28 68:15-22
 @ ./common/layout/TestImage/TestImage.tsx
 @ ./common/layout/TestImage/index.tsx
 @ ./common/layout/TestImage/TestImage.stories.tsx
 @ . sync ^\.(?:(?:^|\/|(?:(?:(?!(?:^|\/)\.).)*?)\/)(?!\.)(?=.)[^/]*?\.stories\.(js|jsx|ts|tsx))$
 @ ./.storybook/generated-stories-entry.js
 @ multi ./node_modules/@storybook/core/dist/server/common/polyfills.js ./node_modules/@storybook/core/dist/server/preview/globals.js ./.storybook/storybook-init-framework-entry.js ./node_modules/@storybook/addon-docs/dist/frameworks/common/config.js-generated-other-entry.js ./node_modules/@storybook/addon-docs/dist/frameworks/react/config.js-generated-other-entry.js ./node_modules/@storybook/addon-links/dist/preset/addDecorator.js-generated-other-entry.js ./node_modules/@storybook/addon-actions/dist/preset/addDecorator.js-generated-other-entry.js ./node_modules/@storybook/addon-actions/dist/preset/addArgs.js-generated-other-entry.js ./node_modules/@storybook/addon-backgrounds/dist/preset/defaultParameters.js-generated-other-entry.js ./.storybook/preview.js-generated-config-entry.js ./.storybook/generated-stories-entry.js (webpack)-hot-middleware/client.js?reload=true&quiet=false&noInfo=undefined

I tried a few different things with file-loader, url-loader and css-loader but was unable to get it working. Any help would be greatly appreciated!

Here is a GitHub repo where the issue can be reproduce by running npm install and npm run storybook.

Taima answered 10/11, 2020 at 16:14 Comment(0)
S
7

Basically you already have had an image loader configured which means you're able to load image in your app. The issue is css-loader doesn't resolve absolute path /images/cucumber.png (since it just supports relative path). In order to fix this, you can manually resolve as following:

newConfig.resolve.alias['/images/cucumber.png'] = path.resolve(__dirname, '../public/images/cucumber.png');

return newConfig;
Strafe answered 11/11, 2020 at 3:54 Comment(3)
Which file does this go into?Orb
In .storybook/main.js It's documented in more detail here: storybook.js.org/docs/react/builders/…Hullabaloo
Is there a way to do this for multiple files without having to explicitly state their path? I have a couple of urls in various files but they all start with the path assets/{folder}/{image} But i need to resolve it to ../public/assets/{folder}/{image} I've tried and it works when i explicitily state each one but i was hoping there might be a more generic assets/**/* catch all that work sort all of them out? - I appreciate this is an old question just thought i'd ask just incase @StrafeCavalryman
O
1

Building on @tmhao2005's answer, I created .storybook/webpack.config.js with this:

const path = require('path')

module.exports = ({ config }) => {
  config.resolve.alias['/images/some-image.png'] = path.resolve(
    __dirname,
    '../public/images/some-image.png',
  )

  return config
}
Orb answered 19/6, 2022 at 17:8 Comment(0)
C
0

You can define a static folder for Storybook in your run script: "start-storybook": "start-storybook -s ./public -p 9001"

Carpetbagger answered 11/11, 2020 at 3:59 Comment(2)
I am already doing this. The problem is with trying to link to files using url() in my CSS files using absolute paths.Taima
@Taima Did you ever find a solution for using the url() in your files with absolute paths? i'm having the same issue nowCavalryman
H
0

I solved the similar issue with this.

// storybook/main.js

module.exports = {
  staticDirs: ['../public']
};

Serving static files via Storybook Configuration

How answered 30/3, 2022 at 10:52 Comment(1)
This solution worked for me. Make sure to restart your "storybook" script once you make this change for the change to show up.Zillion

© 2022 - 2024 — McMap. All rights reserved.