next.js: Image component does not work with Storybook
Bug report
Describe the bug
using next/image
component in storybook throw Error.
To Reproduce
- Set up with-storybook example
yarn create next-app --example with-storybook with-storybook-app
- Create new story using
next/image
import Image from 'next/image'
import React from 'react'
export default { title: 'Image' }
// image url
const url = 'https://......'
export const withNextImage = () => (
<Image src={url} width={100} height={100} />
)
- Start storybook
Expected behavior
show Image without Error as plane image tag do.
Screenshots
System information
- OS: macOS
- Browser Chrome
- Version of Next.js: 10.0.0
- Version of Node.js: v12.16.3
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 52
- Comments: 46 (10 by maintainers)
Commits related to this issue
- Mock Next.js <Image/> in storybook https://github.com/vercel/next.js/issues/18393#issuecomment-783269086 — committed to Kamigami55/oh-so-pro-blog by Kamigami55 3 years ago
By using both @ChoSeoHwan and @Erazihel’s answers, you can render the html from the real
next/image
by addingunoptimized
.storybook/preview.js
The images still have to be served by storybook:
Using @JosBroers answer and link, I struggled a bit to make it work.
I finally succeeded with the help of the Storybook’s documentation by modifying my
start-storybook
script:I’ve also simplified the modification of the
.storybook/preview.js
file:There’s a simpler workaround which is to override
next/image
. It replaces this component with a responsive image in all stories. Found this solution here.Add following code in
.storybook/preview
to make it work.If you prefer to render the same output as
next/image
would, I’ve created the following code based on the Image Component:Is there any workaround for this?
The import is fixed when adding
@next/plugin-storybook
like in PR #18367.However, this only solves the problem for 3rd party loaders like imgix, cloudinary, etc.
For the default loader, we still need a way to expose the API at
/_next/image
such that it can be used from a different port.For example, storybook is running on 6006 and next dev is running on 3000, so we need to change the
src
to something likehttp://localhost:3000/_next/image
or else the images aren’t loaded by the browser when visitinghttp://localhost:6006
.I got an error in Storybook when trying to use next.js Image with src using another host. I have
domains
set properly in my next.js config and dev servers works without errors.I have resolved this problem by add this code to .storybook/preview.js:
I found a solution, and it works fine in my environment.
I’ll share this solution.
This option will change “_next/image” directory to “/public” directory
I hope this solution will solve it.
@balazsorban44 Thanks for the shoutout!
I’m the creator and maintainer of that addon. The addon mentioned attempts to create a “zero config” experience to get nextjs to “just work” with storybook,
next/image
being one of the features that works out of the box. It actually draws inspiration from a solution proposed here to get that working! So, thanks to everyone in this thread that helped move this forward, especially @JCQuintas who proposed the aforementioned solution.Side note: To avoid any confusion, this is a personal project of mine and it isn’t an official addon of storybook. I’m also not affiliated with Storybook, just someone who really likes the tools and wants to make other peoples’ lives better 😃
The following will keep the default behaviour of
NextImage
while allowing external urls or anything in the public folder to be statically loaded.unoptimized
is optional and is used so it doesn’tconsole.warn
on the browser, but can be removed if you don’t care about it or need the optimisation features somehow.I was seeing a similar error to this so I used a combination of the webpack and mocked module implementations above to achieve compatibility in both storybook & jest.
First, create a
next/image
mock component in your root__mocks__
folder ->__mocks__/next/image.js
. Props to @JosBroers as I simply took his code and moved it into a mock file.Then in
.storybook/main.js
, usewebpackFinal
to push an instance of NormalModuleReplacementPlugin to the plugins array that replacesnext/image
with this mockBecause the mock path matches the import path of
next/image
, jest will automatically use the mock inside of unit tests.Hope this helps!
It would be great if the current official NextJS example would be extended with the use of
next/image
(https://github.com/vercel/next.js/tree/canary/examples/with-storybook) I stumbled across this issue as well and looking for a solution after migration tonext/image
Hi everyone, Storybook just released a no config addon that amongst other things make
next/imge
work!Check it out here https://storybook.js.org/addons/storybook-addon-next#supported-features
so I believe this can be closed for now?
team member (@kn0ll) came up with a really elegant solution we use at our company.
Not sure why but it led to infinite loading for me…
@JosBroers Thank you for this it works exactly as expected.
However, you have a tiny error in your Image Component code.
That should be
${props.src}
Cheers!
Building on the previous ideas here, might be possible to hack around and get a default image W/H
.storybook/main.js
.storybook/preview.js
The hackery: statically output size for every image of /public into a json, have it imported in preview.js to provide a default W/H
.storybook/main/compile-image-dimension.js
@RyanClementsHax Thank you for the great summary of what you’re using!
Yes, I meant that npm package. It’s published there but it’s actually the default image loader since Next.js 11. The problem with Storybook is if you’re using Next Image without any
width
,height
orlayout
property. I guess it could be fine if we just included either layout or width/height in our project. I think the layout prop is being passed in usually anyway.when you say
next-image-loader
do you mean this npm package?I actually don’t touch any webpack configuration regarding static imports of images. I only configure webpack to handle css/scss/css module/postcss configuration. It seems that Storybook’s default webpack config already handles statically importing images as static paths rather than static objects, even though the later is what nextjs does.
Below is my
.storybook/main.js
fileBellow is my
next.config.js
fileThis is the page that statically imports the image
It should be noted that I’m using Storybook at version
6.x.x
and webpack 5 for the manger/builder. I’m also on nextjs 12, but mynext/image
solution with storybook was also working on nextjs 11 (although I wasn’t usingplaceholder='blur'
yet when I was on 11).All of this code is from my personal website if you want to go dig around more.
placeholder='blur'
codeI am running into similar problems trying to use storybook with
next/image
. Not only did I run into theFailed to parse src "static/media/public/banner..jpg" on 'next/image', if using relative image it must start with a leading slash "/" or be an absolute URL (http:// or https://)
which was fixed for me by definingunoptimized
on thenext/image
default export, but I also ran into theImage with src "static/media/public/banner..jpg" has "placeholder='blur'" property but is missing the "blurDataURL" property.
when I tried to usenext/image
withplaceholder='blur'
.For me, I was able to solve this by putting the following code in
.storybook/preview.js
.If you are looking for a more type safe solution (but probably not necessary):
.storybook/preview.js
in yourtsconfig.json
’sinclude
array since glob patterns automatically ignore dotfiles https://github.com/microsoft/TypeScript/issues/13399 (eslint ignores.storybook
too btw https://github.com/storybookjs/storybook/issues/295)props.src
is of theStaticImport
type (the type that next js constructs for static imports at build time)I hope this helps
we set it at runtime in the environment. something like
ENV=storybook yarn storybook
thenconst isStorybook = process.env.ENV === 'storybook'
. the idea here is basically just “if you are in storybook, use a loader that does not transform the original URL”. it could be useful outside of storybook though, for something like a static build where you’re not running the Next image proxy.Also seeing this same issue despite trying all of the workarounds here.
@JosBroers Worked for me! Thanks so much. I just had to change
props.layout === "intrinsic"
toprops.layout === "intrinsic" || props.layout === undefined
since layout is not required and defaults to “intrinsic”.@aippili-asp I believe I have a workaround.
What I did was the following:
.ts
version)@SZharkov yeah im seeing that too sadly.