DEV Community

Cover image for Storybook Addon for Next.js Image src
SeongKuk Han
SeongKuk Han

Posted on

Storybook Addon for Next.js Image src

Recently, I was confronted with the problem that an image doesn't appear in the image component in storybook.

I searched for a solution and I found the issue.
Even though there is already such a solution, it was a little hard to find it. This is why I am writing this post. Actually, there are other ways to solve the problem with some code but I didn't want to write more code in my project.

First, let me show you the problem. I set up a project with a command npx create-next-app and made a component.



import Image from "next/image";
import styled from "@emotion/styled";

export const IconButton = ({
  src,
  children,
  width = 120,
  onClick,
  iconSize = 24,
}) => {
  return (
    <Button onClick={onClick} width={width}>
      <Image
        src={src}
        width={iconSize}
        height={iconSize}
        alt="icon of the button"
      />
      <Text>{children}</Text>
    </Button>
  );
};

const Button = styled.div`
  box-sizing: border-box;
  width: ${({ width }) => width}px;
  border-radius: 8px;
  height: 40px;
  padding: 8px;
  display: flex;
  alignitems: center;
  column-gap: 6px;
  background-color: #3498db;
  color: white;
  position: relative;

  &:hover {
    cursor: pointer;
    opacity: 0.7;
  }

  -webkit-user-select: none;
  -khtml-user-select: none;
  -moz-user-select: none;
  -o-user-select: none;
  user-select: none;
`;

const Text = styled.div`
  position: absolute;
  top: 0;
  bottom: 10%;
  left: 8px;
  right: 0;
  display: flex;
  align-items: center;
  justify-content: center;
`;


Enter fullscreen mode Exit fullscreen mode

folder browser

I downloaded an image(from here) and put it to public directory.

Here is a code of the index page and the result.

Please, ignore the design



import { IconButton } from "../components/IconButton";

export default function Home() {
  return (
    <div>
      <h3>Example</h3>
      <IconButton src="/icons/home.png">Button</IconButton>
    </div>
  );
}


Enter fullscreen mode Exit fullscreen mode

Website Page

The image appears well.

Let's look at this in storybook. I added a line in main.js for serving static files.

.storybook/main.js



module.exports = {
  stories: ["../components/**/*.stories.(js|jsx|ts|tsx)"],
  addons: ["@storybook/addon-links", "@storybook/addon-essentials"],
  framework: "@storybook/react",
  staticDirs: ["../public"], // Here
};


Enter fullscreen mode Exit fullscreen mode

IconButton.stories.js



import { IconButton } from ".";

// eslint-disable-next-line import/no-anonymous-default-export
export default {
  title: "components/IconButton",
  component: IconButton,
  args: {
    width: 120,
    iconSize: 24,
    children: "Button",
  },
};

const Template = (args) => <IconButton {...args} />;

export const Home = Template.bind({});

Home.args = {
  src: "/icons/home.png",
};


Enter fullscreen mode Exit fullscreen mode

Image description

Image Component src Attribute

The image doesn't appear, right?

The src of the image points /_next/image.

Now, install the package storybook-addon-next.



npm install -D storybook-addon-next


Enter fullscreen mode Exit fullscreen mode

Then, add the addon to main.js.



module.exports = {
  stories: ["../components/**/*.stories.(js|jsx|ts|tsx)"],
  addons: [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    "storybook-addon-next", // Here
  ],
  framework: "@storybook/react",
  staticDirs: ["../public"],
};


Enter fullscreen mode Exit fullscreen mode

Restart the storybook.

.....?!

An error occurs. I've encountered it while writing this post, meanwhile I haven't seen any errors in my project.

Log



info @storybook/react v6.4.18
info
info => Loading presets
info => Serving static files from ./.\public at /
(node:14304) DeprecationWarning: You have specified an invalid glob, we've attempted to fix it, please ensure that the glob you specify is valid. See: https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#correct-globs-in-mainjs
(Use `node --trace-deprecation ...` to show where the warning was created)
info => Using implicit CSS loaders
info => Using default Webpack4 setup
ERR! WebpackOptionsValidationError: Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
ERR!  - configuration.module.rules[12].type should be one of these:
ERR!    "javascript/auto" | "javascript/dynamic" | "javascript/esm" | "json" | "webassembly/experimental"
ERR!    -> Module type to use for the module
ERR!     at webpack (C:\Users\hskco\OneDrive\바탕 화면\dev\next-storybook-image-test\node_modules\webpack\lib\webpack.js:31:9)
ERR!     at Object.start (C:\Users\hskco\OneDrive\바탕 화면\dev\next-storybook-image-test\node_modules\@storybook\builder-webpack4\dist\cjs\index.js:92:18)
ERR!     at async Promise.all (index 0)
ERR!     at async storybookDevServer (C:\Users\hskco\OneDrive\바탕 화면\dev\next-storybook-image-test\node_modules\@storybook\core-server\dist\cjs\dev-server.js:126:28)
ERR!     at async buildDevStandalone (C:\Users\hskco\OneDrive\바탕 화면\dev\next-storybook-image-test\node_modules\@storybook\core-server\dist\cjs\build-dev.js:115:31)
ERR!     at async buildDev (C:\Users\hskco\OneDrive\바탕 화면\dev\next-storybook-image-test\node_modules\@storybook\core-server\dist\cjs\build-dev.js:161:5)
ERR!  WebpackOptionsValidationError: Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
ERR!  - configuration.module.rules[12].type should be one of these:
ERR!    "javascript/auto" | "javascript/dynamic" | "javascript/esm" | "json" | "webassembly/experimental"
ERR!    -> Module type to use for the module
ERR!     at webpack (C:\Users\hskco\OneDrive\바탕 화면\dev\next-storybook-image-test\node_modules\webpack\lib\webpack.js:31:9)
ERR!     at Object.start (C:\Users\hskco\OneDrive\바탕 화면\dev\next-storybook-image-test\node_modules\@storybook\builder-webpack4\dist\cjs\index.js:92:18)
ERR!     at async Promise.all (index 0)
ERR!     at async storybookDevServer (C:\Users\hskco\OneDrive\바탕 화면\dev\next-storybook-image-test\node_modules\@storybook\core-server\dist\cjs\dev-server.js:126:28)
ERR!     at async buildDevStandalone (C:\Users\hskco\OneDrive\바탕 화면\dev\next-storybook-image-test\node_modules\@storybook\core-server\dist\cjs\build-dev.js:115:31)
ERR!     at async buildDev (C:\Users\hskco\OneDrive\바탕 화면\dev\next-storybook-image-test\node_modules\@storybook\core-server\dist\cjs\build-dev.js:161:5)

WARN Broken build, fix the error above.
WARN You may need to refresh the browser.

npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! next-storybook-image-test@ storybook: `start-storybook -p 6006`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the next-storybook-image-test@ storybook script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.    

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\hskco\AppData\Roaming\npm-cache\_logs\2022-02-06T07_30_05_523Z-debug.log        
PS C:\Users\hskco\OneDrive\바탕 화면\dev\next-storybook-image-test> 


Enter fullscreen mode Exit fullscreen mode

The installed package is storybook-addon-next^1.4.1. I used v1.4.0 in my project. So, I'll reinstall the package with npm install storybook-addon-next@1.4.0.

A result that the addon works

Finally it works! I think there was something wrong with the version v1.4.1.

I hope this post will be helpful. Good coding!


+Plus

I've reported the storybook-addon-next issue in github and I got the answer from the author.
It was the problem of the webpack version.
There is the guide for upgrading the builder from webpack4 to webpack5.
After upgrading it, storybook-addon-next@1.4.1 works.

If you haven't started your project yet, I'd recommend you to initialize the storybook with npx sb init --builder webpack5.

Top comments (2)

Collapse
 
franciscojs profile image
Francisco

Thanks for sharing this. I was missing the storybook nextjs addon.

Collapse
 
lico profile image
SeongKuk Han

Good to hear it helped :)