Closed1

Next.js 14とStorybook 8でSVGをインラインコードで扱う

3w36zj63w36zj6

https://github.com/storybookjs/storybook/issues/18557

SVGRのWebpack loaderを依存関係に追加する。

https://www.npmjs.com/package/@svgr/webpack

Next.js

next.config.mjs
/** @type {import('next').NextConfig} */
const nextConfig = {
  output: "standalone",
  webpack: (config) => {
    config.module.rules.push({
      test: /\.svg$/,
      use: [
        {
          loader: "@svgr/webpack",
        },
      ],
    });
    return config;
  },
};

TypeScript

Next.jsの内部で意図的にanyが指定されているので、型を用意する。

https://github.com/vercel/next.js/blob/v14.2.11/packages/next/image-types/global.d.ts#L10-L19

src/app/globals.d.ts
declare module "*.svg" {
  const ReactComponent: React.FC<React.SVGProps<SVGSVGElement>>;
  export default ReactComponent;
}

tsconfig.jsonincludenext-env.d.tsの前に型ファイルを追加する。

tsconfig.json
{
  "include": [
    "src/app/globals.d.ts",
    "next-env.d.ts",
    "**/*.ts",
    "**/*.tsx",
    ".next/types/**/*.ts"
  ],
}

Storybook

.storybook/main.ts
const config: StorybookConfig = {
  stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
  addons: [
    "@storybook/addon-onboarding",
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    "@chromatic-com/storybook",
    "@storybook/addon-interactions",
  ],
  framework: {
    name: "@storybook/nextjs",
    options: {},
  },
  staticDirs: ["../public"],
  webpackFinal: async (config) => {
    // NOTE: https://github.com/storybookjs/storybook/issues/18557
    config.module = config.module || {};
    config.module.rules = config.module.rules || [];

    // This modifies the existing image rule to exclude .svg files
    // since you want to handle those files with @svgr/webpack
    const imageRule = config.module.rules.find((rule) =>
      rule?.["test"]?.test(".svg"),
    );
    if (imageRule) {
      imageRule["exclude"] = /\.svg$/;
    }

    // Configure .svg files to be loaded with @svgr/webpack
    config.module.rules.push({
      test: /\.svg$/,
      use: ["@svgr/webpack"],
    });

    return config;
  },
};
このスクラップは2ヶ月前にクローズされました