reactjswebpackstorybook

How to resolve aliases in Storybook?


I have a React/Typescript project with Storybook. Storybook works great, but as soon as I start importing files with aliases, it crashes.

Example:

import Foo from "@components/foo" => crash
import Foo from "../../components/foo" => ok

The app works fine with the aliases. The issue is only related to Storybook.

Here is my storybook config:

module.exports = {
  stories: ["../**/stories.tsx"],
  webpackFinal: (config) => {
    return {
      ...config,
      module: {
        ...config.module,
        rules: [
          {
            test: /\.(ts|js)x?$/,
            exclude: /node_modules/,
            use: { loader: "babel-loader" },
          },
          { test: /\.css$/, use: ["style-loader", "css-loader"] },
          { test: /\.(png|jpg|gif)$/, use: ["file-loader"] },
          {
            test: /\.svg$/,
            use: [
              {
                loader: "babel-loader",
              },
              {
                loader: "react-svg-loader",
                options: {
                  jsx: true,
                },
              },
            ],
          },
        ],
      },
    };
  },
  typescript: {
    check: false,
    checkOptions: {},
    reactDocgen: "react-docgen-typescript",
    reactDocgenTypescriptOptions: {
      shouldExtractLiteralValuesFromEnum: true,
      propFilter: (prop) =>
        prop.parent ? !/node_modules/.test(prop.parent.fileName) : true,
    },
  },
};

My webpack config:

/* eslint-env node */
const path = require("path");
const TerserPlugin = require("terser-webpack-plugin");
const Dotenv = require("dotenv-webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");

const isProductionMode = (mode) => mode === "production";

module.exports = () => {
  const env = require("dotenv").config({ path: __dirname + "/.env" });
  const nodeEnv = env.parsed.NODE_ENV;
  return {
    mode: "development",
    entry: "./src/index.tsx",
    output: {
      path: path.join(__dirname, "./dist"),
      filename: "[name].[contenthash].bundle.js",
      publicPath: "/",
    },
    resolve: {
      extensions: [".ts", ".tsx", ".js", "jsx", ".json"],
      alias: {
    "@api": path.resolve(__dirname, "src/api/"),
    "@assets": path.resolve(__dirname, "src/assets/"),
    "@components": path.resolve(__dirname, "src/components/"),
    "@containers": path.resolve(__dirname, "src/containers/"),
    "@data": path.resolve(__dirname, "src/data/"),
    "@i18n": path.resolve(__dirname, "src/i18n/"),
    "@models": path.resolve(__dirname, "src/models/"),
    "@pages": path.resolve(__dirname, "src/pages/"),
    "@src": path.resolve(__dirname, "src/"),
    "@stores": path.resolve(__dirname, "src/stores/"),
    "@utils": path.resolve(__dirname, "src/utils/"),
  },
    },
    module: {
      rules: [
        {
          test: /\.(ts|js)x?$/,
          exclude: /node_modules/,
          use: { loader: "babel-loader" },
        },
        { test: /\.css$/, use: ["style-loader", "css-loader"] },
        { test: /\.(png|jpg|jpeg|gif)$/, use: ["file-loader"] },
        {
          test: /\.svg$/,
          use: [
            {
              loader: "babel-loader",
            },
            {
              loader: "react-svg-loader",
              options: {
                jsx: true,
              },
            },
          ],
        },
      ],
    },
    devServer: {
      historyApiFallback: true,
      port: 3000,
      inline: true,
      hot: true,
    },
    plugins: [
      new HtmlWebpackPlugin({
        template: "./src/index.html",
      }),
      new Dotenv(),
    ],
    optimization: {
      minimize: isProductionMode(nodeEnv),
      minimizer: isProductionMode(nodeEnv) ? [new TerserPlugin()] : [],
      splitChunks: { chunks: "all" },
    },
  };
};

How to fix this? I am on webpack 5.24.2 and storybook 6.1.20, so these are the latest versions.


Solution

  • Just add this in your .storybook/main.js

    const path = require('path');
    
    module.exports = {
      "stories": [
        "../components/**/*.stories.mdx",
        "../components/**/*.stories.@(js|jsx|ts|tsx)"
      ],
      "addons": [
        "@storybook/addon-links",
        "@storybook/addon-essentials",
        '@storybook/preset-scss',
      ],
      webpackFinal: async (config) => {
        config.resolve.alias = {
          ...config.resolve.alias,
          '@/interfaces': path.resolve(__dirname, "../interfaces"),
        };
    
        return config;
      }
    }
    

    here interface is folder at my project root

    It works For Me