Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Image component does not work with Storybook #18393

Closed
kodai3 opened this issue Oct 28, 2020 · 46 comments
Closed

Image component does not work with Storybook #18393

kodai3 opened this issue Oct 28, 2020 · 46 comments
Assignees
Labels

Comments

@kodai3
Copy link

kodai3 commented Oct 28, 2020

Bug report

Describe the bug

using next/image component in storybook throw Error.

To Reproduce

  1. Set up with-storybook example yarn create next-app --example with-storybook with-storybook-app
  2. 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} />
)
  1. Start storybook

Expected behavior

show Image without Error as plane image tag do.

Screenshots

image

System information

  • OS: macOS
  • Browser Chrome
  • Version of Next.js: 10.0.0
  • Version of Node.js: v12.16.3
@Timer Timer added kind: bug Confirmed bug that is on the backlog type: needs investigation labels Oct 28, 2020
@Timer Timer added this to the iteration 11 milestone Oct 28, 2020
@Timer Timer added the point: 2 label Oct 30, 2020
@Timer Timer modified the milestones: iteration 11, iteration 12 Oct 30, 2020
@styfle
Copy link
Member

styfle commented Nov 4, 2020

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 like http://localhost:3000/_next/image or else the images aren't loaded by the browser when visiting http://localhost:6006.

@aippili-asp
Copy link

Is there any workaround for this?

@tiavina-mika

This comment has been minimized.

@Timer Timer removed their assignment Nov 19, 2020
@SZharkov
Copy link
Contributor

SZharkov commented Nov 24, 2020

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.
image

@steoneill
Copy link

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.

image

I have this too, I'm guessing you're trying to use slice machines too right? :)

@SZharkov
Copy link
Contributor

@steoneill I don't until it's stable. I use my own implementation of dynamic slices. I am also experiencing very low google pagespeed score, looks like because of a big amount of props (because of slices). Do you experience the same?

@steoneill
Copy link

@SZharkov yeah im seeing that too sadly.

@BramDecuypere
Copy link

BramDecuypere commented Dec 20, 2020

@aippili-asp I believe I have a workaround.

Is there any workaround for this?

What I did was the following:

  1. Add a file .storybook/middleware.js. (Mind you, they don't support a .ts version)
const { createProxyMiddleware } = require('http-proxy-middleware');

const expressMiddleWare = (router) => {
  router.use('/_next/image', createProxyMiddleware({ target: 'http://localhost:{ NEXTJS_PORT}', changeOrigin: true }));
};

module.exports = expressMiddleWare;

  1. Don't forget to update the port.
  2. I believe you could also do something for production values if needed.

@ChoSeoHwan
Copy link

I found a solution, and it works fine in my environment.

I'll share this solution.

  1. Add below option in ".storybook/main.js"
# main.js

module.exports = {
    // another options...,
    webpackFinal: async (config) => {
        // awesome code...

        config.plugins.push(new webpack.DefinePlugin({
            'process.env.__NEXT_IMAGE_OPTS': JSON.stringify({
                deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
                imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
                domains: [],
                path: '/',
                loader: 'default',
            }),
        }));
    }
} 

This option will change "_next/image" directory to "/public" directory

  1. use "next/image" component with "unoptimized" option in storybook
# Image.stories.tsx
// awesome code ...

export const Image: Story<ImageProps> = ({ src }) => 
    <Image src={src} layout="fill" objectFit="contain" unoptimized />;

I hope this solution will solve it.

@mavichow
Copy link

I found a solution, and it works fine in my environment.

I'll share this solution.

  1. Add below option in ".storybook/main.js"
# main.js

module.exports = {
    // another options...,
    webpackFinal: async (config) => {
        // awesome code...

        config.plugins.push(new webpack.DefinePlugin({
            'process.env.__NEXT_IMAGE_OPTS': JSON.stringify({
                deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
                imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
                domains: [],
                path: '/',
                loader: 'default',
            }),
        }));
    }
} 

This option will change "_next/image" directory to "/public" directory

  1. use "next/image" component with "unoptimized" option in storybook
# Image.stories.tsx
// awesome code ...

export const Image: Story<ImageProps> = ({ src }) => 
    <Image src={src} layout="fill" objectFit="contain" unoptimized />;

I hope this solution will solve it.

Thanks! This workaround works for me! and I've added babel-plugin-react-remove-properties in my project to remove unoptimized attribute when building or in production mode.

@josbroers
Copy link

josbroers commented Dec 24, 2020

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.

import * as nextImage from "next/image"

Object.defineProperty(nextImage, "default", {
  configurable: true,
  value: props => {
    const { width, height } = props
    const ratio = (height / width) * 100
    return (
      <div
        style={{
          paddingBottom: `${ratio}%`,
          position: "relative",
        }}
      >
        <img
          style={{
            objectFit: "cover",
            position: "absolute",
            minWidth: "100%",
            minHeight: "100%",
            maxWidth: "100%",
            maxHeight: "100%",
          }}
          {...props}
        />
      </div>
    )
  },
})

If you prefer to render the same output as next/image would, I've created the following code based on the Image Component:

Object.defineProperty(nextImage, "default", {
  configurable: true,
  value: props => {
    const height = props.height
    const width = props.width
    const quotient = height / width
    const paddingTop = isNaN(quotient) ? "100%" : `${quotient * 100}%`
    let wrapperStyle
    let sizerStyle
    let sizerSvg
    let toBase64
    let imgStyle = {
      position: "absolute",
      top: 0,
      left: 0,
      bottom: 0,
      right: 0,
      boxSizing: "border-box",
      padding: 0,
      border: "none",
      margin: "auto",
      display: "block",
      width: 0,
      height: 0,
      minWidth: "100%",
      maxWidth: "100%",
      minHeight: "100%",
      maxHeight: "100%",
      objectFit: props.objectFit ? props.objectFit : undefined,
      objectPosition: props.objectPosition ? props.objectPosition : undefined,
    }

    if (width !== undefined && height !== undefined && props.layout !== "fill") {
      if (props.layout === "responsive") {
        wrapperStyle = {
          display: "block",
          overflow: "hidden",
          position: "relative",
          boxSizing: "border-box",
          margin: 0,
        }
        sizerStyle = {
          display: "block",
          boxSizing: "border-box",
          paddingTop,
        }
      } else if (props.layout === "intrinsic" || props.layout === undefined) {
        wrapperStyle = {
          display: "inline-block",
          maxWidth: "100%",
          overflow: "hidden",
          position: "relative",
          boxSizing: "border-box",
          margin: 0,
        }
        sizerStyle = {
          boxSizing: "border-box",
          display: "block",
          maxWidth: "100%",
        }
        sizerSvg = `<svg width="${width}" height="${height}" xmlns="http://www.w3.org/2000/svg" version="1.1"/>`
        toBase64 = Buffer.from(sizerSvg).toString("base64")
      } else if (props.layout === "fixed") {
        wrapperStyle = {
          overflow: "hidden",
          boxSizing: "border-box",
          display: "inline-block",
          position: "relative",
          width,
          height,
        }
      }
    } else if (width === undefined && height === undefined && props.layout === "fill") {
      wrapperStyle = {
        display: "block",
        overflow: "hidden",
        position: "absolute",
        top: 0,
        left: 0,
        bottom: 0,
        right: 0,
        boxSizing: "border-box",
        margin: 0,
      }
    } else {
      throw new Error(
        `Image with src "${props.src}" must use "width" and "height" properties or "layout='fill'" property.`,
      )
    }

    return (
      <div style={wrapperStyle}>
        {sizerStyle ? (
          <div style={sizerStyle}>
            {sizerSvg ? (
              <img
                style={{ maxWidth: "100%", display: "block" }}
                alt={props.alt}
                aria-hidden={true}
                role="presentation"
                src={`data:image/svg+xml;base64,${toBase64}`}
              />
            ) : null}
          </div>
        ) : null}
        <img {...props} decoding="async" style={imgStyle} />
      </div>
    )
  },
})

@Timer Timer modified the milestones: 10.x.x, backlog Jan 6, 2021
@sklawren
Copy link

sklawren commented Jan 7, 2021

@josbroers Thank you for this it works exactly as expected.

However, you have a tiny error in your Image Component code.

throw new Error(
  `Image with src "${src}" must use "width" and "height" properties or "layout='fill'" property.`,
)

That should be ${props.src}

Cheers!

@josbroers
Copy link

However, you have a tiny error in your Image Component code.

throw new Error(
  `Image with src "${src}" must use "width" and "height" properties or "layout='fill'" property.`,
)

That should be ${props.src}

Glad it works as expected and thanks @sklawren for mentioning the error. I've implemented the change in the code above.

@sklawren
Copy link

One other issue. The imgStyle object overrides any className prop passed to the Image component. For example, if you pass a css class with margin or padding, they get overridden by the imgStyle margin and padding.

@travisbloom
Copy link

team member (@kn0ll) came up with a really elegant solution we use at our company.

import NextBaseImage, { ImageProps } from 'next/image'

const StorybookNextImage: React.FC<ImageProps> = props => (
  <NextBaseImage
    {...props}
    loader={({ src }) => {
      return src
    }}
  />
)
export const NextImage = !isStorybook ? NextBaseImage : (StorybookNextImage as typeof NextBaseImage)

@evisotskiy
Copy link

team member (@kn0ll) came up with a really elegant solution we use at our company.

import NextBaseImage, { ImageProps } from 'next/image'

const StorybookNextImage: React.FC<ImageProps> = props => (
  <NextBaseImage
    {...props}
    loader={({ src }) => {
      return src
    }}
  />
)
export const NextImage = !isStorybook ? NextBaseImage : (StorybookNextImage as typeof NextBaseImage)

And where do you get isStorybook variable ?

@kn0ll
Copy link

kn0ll commented Aug 19, 2021

we set it at runtime in the environment. something like ENV=storybook yarn storybook then const 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.

@rpedroni
Copy link

In case you have the same problem with next/link (considering you're using a. <a> inside <Link>s):

import * as nextLink from 'next/link';

Object.defineProperty(nextLink, 'default', {
  configurable: true,
  value: (props) => <>{props.children}</>,
});

@JCQuintas
Copy link

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't console.warn on the browser, but can be removed if you don't care about it or need the optimisation features somehow.

// preview.tsx
import * as NextImage from 'next/image'

const OriginalNextImage = NextImage.default

Object.defineProperty(NextImage, 'default', {
  configurable: true,
  value: (props) => (
    <OriginalNextImage {...props} unoptimized loader={({ src }) => src} />
  ),
})

@jeroenroumen
Copy link

jeroenroumen commented Oct 2, 2021

@JCQuintas This works but I'm still struggling to setup storybook with Next.js 11 and being able to use image imports like I would in Next. Next's webpack config uses next-image-loader for static image imports.

When using storybook it defaults to it's file-loader for images and even when trying to override it I can't seem to make storybook use the next file loader. Do you have any experience with this?

@JCQuintas
Copy link

@jeroenroumen Hi, I would suspect you need to change the file loaders in storybook to use next-image-loader instead of file-loader. You can probably get some info about that from this page storybook webpack config

Make sure that the next-image-loader is loaded INSTEAD of the file-loader to prevent issues

@jeroenroumen
Copy link

jeroenroumen commented Oct 3, 2021

@JCQuintas yeah that's one of the first things I tried. Sorry forgot to mention that. Basically it throws an error that webpack can't resolve the next-image-loader module. Even tried adding the npm package itself but it doesn't seem to work on it's own.

My main problem now is to make the storybook main.js aware or be able to access next-image-loader.

Did you ever run in this use case or do you always provide width,height or layout?

@ajayjaggi97
Copy link

ajayjaggi97 commented Oct 8, 2021

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't console.warn on the browser, but can be removed if you don't care about it or need the optimisation features somehow.

// preview.tsx
import * as NextImage from 'next/image'

const OriginalNextImage = NextImage.default

Object.defineProperty(NextImage, 'default', {
  configurable: true,
  value: (props) => (
    <OriginalNextImage {...props} unoptimized loader={({ src }) => src} />
  ),
})

By doing this getting the error: @JCQuintas

Objects are not valid as a React child (found: object with keys {type, props, key, ref, __k, __, __b, __e, __d, __c, __h, constructor, __v}). If you meant to render a collection of children, use an array instead.
in value (created by Avatar)
in Avatar
in Unknown (created by unboundStoryFn)
in unboundStoryFn
in ErrorBoundary

Kamigami55 added a commit to Kamigami55/oh-so-pro-blog that referenced this issue Oct 15, 2021
@RyanClementsHax
Copy link
Contributor

RyanClementsHax commented Oct 30, 2021

I am running into similar problems trying to use storybook with next/image. Not only did I run into the Failed 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 defining unoptimized on the next/image default export, but I also ran into the Image with src "static/media/public/banner..jpg" has "placeholder='blur'" property but is missing the "blurDataURL" property. when I tried to use next/image with placeholder='blur'.

For me, I was able to solve this by putting the following code in .storybook/preview.js.

// other code omitted for brevity
import * as NextImage from 'next/image'

const OriginalNextImage = NextImage.default

Object.defineProperty(NextImage, 'default', {
  configurable: true,
  value: props => (
    <OriginalNextImage {...props} unoptimized blurDataURL={props.src} />
  )
})

If you are looking for a more type safe solution (but probably not necessary):

  1. put .storybook/preview.js in your tsconfig.json's include array since glob patterns automatically ignore dotfiles files/dirs that start with a dot (.) do not get copied or transpiled by default microsoft/TypeScript#13399 (eslint ignores .storybook too btw .storybook folder is a dotfile and ignored by default by eslint storybookjs/storybook#295)
  2. handle the case that props.src is of the StaticImport type (the type that next js constructs for static imports at build time)
// other code omitted for brevity
import * as NextImage from 'next/image'

const OriginalNextImage = NextImage.default

// eslint-disable-next-line no-import-assign
Object.defineProperty(NextImage, 'default', {
  configurable: true,
  value: (/** @type {import('next/image').ImageProps} */ props) => {
    if (typeof props.src === 'string') {
      return (
        <OriginalNextImage {...props} unoptimized blurDataURL={props.src} />
      )
    } else {
      // don't need blurDataURL here since it is already defined on the StaticImport type
      return <OriginalNextImage {...props} unoptimized />
    }
  }
})

I hope this helps

@jeroenroumen
Copy link

jeroenroumen commented Oct 31, 2021

@RyanClementsHax How are you handling the image importing in the Storybook webpack configuration? In our project with Next.js 11 when you import a .png for example, it returns a StaticImageData object. This already provides src, width, height.

This is due too the next-image-loader which I can't for the life of of me work with the storybook config.

@RyanClementsHax
Copy link
Contributor

next-image-loader

when you say next-image-loader do you mean this npm package?

How are you handling the image importing in the Storybook webpack configuration?

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 file

/* eslint-disable @typescript-eslint/no-var-requires */
const path = require('path')

/**
 * @typedef {import('next').NextConfig} NextConfig
 * @typedef {import('webpack').Configuration} WebpackConfig
 */

module.exports = {
  stories: ['../**/*.stories.@(js|jsx|ts|tsx)'],
  addons: [
    '@storybook/addon-links',
    '@storybook/addon-essentials',
    'storybook-addon-next-router',
    '@storybook/addon-a11y',
    '@storybook/addon-storysource',
    'storybook-dark-mode'
  ],
  core: {
    builder: 'webpack5'
  },
  /**
   * @param {WebpackConfig} baseConfig
   * @return {Promise<WebpackConfig>}
   */
  async webpackFinal(baseConfig) {
    const nextConfig = require('../next.config.js')([], baseConfig)

    configureRootAbsoluteImport(baseConfig)
    configureCss(baseConfig, nextConfig)

    return baseConfig
  }
}

/**
 * @param {WebpackConfig} baseConfig
 * @return {void}
 */
const configureRootAbsoluteImport = baseConfig => {
  baseConfig.resolve?.modules?.push(path.resolve(__dirname, '..'))
}

/**
 * @param {WebpackConfig} baseConfig
 * @param {NextConfig} nextConfig
 * @return {void}
 */
const configureCss = (baseConfig, nextConfig) => {
  baseConfig.module?.rules?.push({
    test: /\.(s*)css$/,
    use: [
      'style-loader',
      {
        loader: 'css-loader',
        options: {
          modules: { auto: true }
        }
      },
      {
        loader: 'postcss-loader'
      },
      {
        loader: 'sass-loader',
        options: {
          additionalData: nextConfig.sassOptions?.prependData
        }
      }
    ]
  })
}

Bellow is my next.config.js file

// I'd love to convert this to .mjs but typescript doesn't suport .mjs yet https://github.com/microsoft/TypeScript/issues/15416
/* eslint-disable @typescript-eslint/no-var-requires */

// @ts-expect-error: there are no typings for this module
const withPlugins = require('next-compose-plugins')
// @ts-expect-error: there are no typings for this module
const withBundleAnalyzer = require('@next/bundle-analyzer')

/**
 * @type {import('next').NextConfig}
 **/
const config = {
  experimental: { esmExternals: true }
}

module.exports = withPlugins(
  [
    withBundleAnalyzer({
      enabled: process.env.ANALYZE === 'true'
    })
  ],
  config
)

This is the page that statically imports the image

import { Layout } from 'components/landing/Layout'
import Head from 'next/head'
import Image from 'next/image'
import banner from 'public/banner.jpg'

export const Index: React.FC = () => {
  return (
    <Layout>
      <Head>
        <title>Ryan Clements</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <section className="h-screen w-100 p-8">
        <div className="h-full grid gap-4 content-center md:container md:mx-auto md:grid-cols-2 lg:grid-cols-5">
          <div className="grid content-center lg:col-span-2">
            <h1 className="text-4xl font-bold mb-4">
              Hiya 👋
              <br />
              I’m Ryan Clements
            </h1>
            <h2 className="text-2xl text-gray-600">
              I 💖 God, my wife and daughter&nbsp;👨‍👩‍👧, and making dope
              software&nbsp;👨‍💻
            </h2>
          </div>
          <div className="relative h-[500px] hidden md:block shadow-md lg:col-span-3">
            <Image
              src={banner}
              layout="fill"
              objectFit="cover"
              objectPosition="center"
              placeholder="blur"
              priority
              alt="My wife, me, and our wedding party being silly"
            />
          </div>
        </div>
      </section>
    </Layout>
  )
}

export default Index

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 my next/image solution with storybook was also working on nextjs 11 (although I wasn't using placeholder='blur' yet when I was on 11).

All of this code is from my personal website if you want to go dig around more.

  • This commit is when I was using nextjs 11
  • This commit contains all of the upgrades I did (including upgrading to nextjs 12)
  • This a commit on the branch I'm working on that has the placeholder='blur' code

@jeroenroumen
Copy link

@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 or layout 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.

@styfle styfle modified the milestones: 11.1.x, 12.0.4 Nov 5, 2021
@timneutkens timneutkens removed this from the 12.0.5 milestone Nov 17, 2021
@kftsehk
Copy link

kftsehk commented Nov 23, 2021

Building on the previous ideas here, might be possible to hack around and get a default image W/H

.storybook/main.js

require('./main/compile-image-dimension');

.storybook/preview.js

import IMAGE_DIMENSION from './cache/image-dimension.json';

const UnoptimizedNextImage = NextImage.default;
Object.defineProperty(NextImage, 'default', {
  configurable: true,
  value: (props) => (
    <UnoptimizedNextImage
      {...IMAGE_DIMENSION[props.src]}
      {...props}
      unoptimized
      blurDataURL={props.placeholder === 'blur' ? props.src : undefined}
    />
  ),
});

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

const fs = require('fs');
const sizeOf = require('image-size');
const _ = require('lodash');
const path = require('path');

const getAllFiles = function (dirPath, arrayOfFiles) {
  files = fs.readdirSync(dirPath);

  arrayOfFiles = arrayOfFiles || [];

  files.forEach(function (file) {
    if (fs.statSync(dirPath + '/' + file).isDirectory()) {
      arrayOfFiles = getAllFiles(dirPath + '/' + file, arrayOfFiles);
    } else {
      arrayOfFiles.push(path.join(dirPath, '/', file).replace(/\\/g, '/'));
    }
  });

  return arrayOfFiles;
};

const suffixes = ['.png', '.jpg'];
const suffixFilter = function (filename) {
  return _.some(suffixes, (s) => filename.endsWith(s));
};

const compiledImageSizes = _(getAllFiles('./public'))
  .filter(suffixFilter)
  .map((url) => {
    const idx = url.lastIndexOf('.');
    // Mind the url is <path/basename>(dot)(dot)<extension>
    return {
      url: `static/media/${url.slice(0, idx)}.${url.slice(idx)}`,
      ...sizeOf(url),
    };
  })
  .keyBy('url')
  .mapValues(({ width, height }) => ({ width, height }))
  .value();

const data = JSON.stringify(compiledImageSizes);
fs.mkdirSync('.storybook/cache', { recursive: true });
fs.writeFileSync('.storybook/cache/image-dimension.json', data);

@tylernevell
Copy link

I found a solution, and it works fine in my environment.
I'll share this solution.

  1. Add below option in ".storybook/main.js"
# main.js

module.exports = {
    // another options...,
    webpackFinal: async (config) => {
        // awesome code...

        config.plugins.push(new webpack.DefinePlugin({
            'process.env.__NEXT_IMAGE_OPTS': JSON.stringify({
                deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
                imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
                domains: [],
                path: '/',
                loader: 'default',
            }),
        }));
    }
} 

This option will change "_next/image" directory to "/public" directory

  1. use "next/image" component with "unoptimized" option in storybook
# Image.stories.tsx
// awesome code ...

export const Image: Story<ImageProps> = ({ src }) => 
    <Image src={src} layout="fill" objectFit="contain" unoptimized />;

I hope this solution will solve it.

Thanks! This workaround works for me! and I've added babel-plugin-react-remove-properties in my project to remove unoptimized attribute when building or in production mode.

Is this Babel plugin even necessary when deploying in production node since this "unoptimized" attribute is only in storybook?

@balazsorban44
Copy link
Member

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?

@RyanClementsHax
Copy link
Contributor

@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 :)

@balazsorban44
Copy link
Member

Thank you for your hard work! 💚🙏 I'm going to close this issue for now.

@github-actions
Copy link
Contributor

This closed issue has been automatically locked because it had no new activity for a month. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 26, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests