Storybook Can't Find Components in React, Next.JS, Typescript Project

Viewed 8483

I have storybook setup with my next.js, typescript and react project. The project renders fine but storybook breaks and give me the me error: "Module not found: Error: Can't resolve 'components/atoms' in...." It seems like the path to components is causing it to break:

import { Element } from 'components/atoms';

but the following works:

import { Element } from '../../atoms

I have a tsconfig.json file with the following:

  "compilerOptions": {
    "baseUrl": "src",
    },
  "include": [
    "src/**/*.ts",
    "src/**/*.tsx"
  ],
...

I tried some of the suggestions online but none seems to resolve the path issue. I created a webpack.config.js in my .storybook folder with the following, but still get errors.

module.exports = {
 ...
  resolve: {
    modules: [path.resolve(__dirname, 'src'), 'node_modules']
  }
};

I would like to not use the ../../ when calling files and just be able to use the ./components structure.

4 Answers

Spent some time fighting with Storybook )

Here is my .storybook/main.js version, that finally worked:

const path = require("path");

module.exports = {
  webpackFinal: async (config, { configType }) => {
    config.resolve.modules.push(path.resolve(__dirname, '../src'));

    return config;
  },

  stories: [
    "../src/**/*.stories.mdx",
    "../src/**/*.stories.@(js|jsx|ts|tsx)"
  ],
  addons: [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    "@storybook/preset-create-react-app"
  ]
}

For someone who is still looking for a solution, try adding the below inside your webpackFinal before returning config. It is because storybook isn't configured to access files using absolute paths.

config.resolve.modules = [...(config.resolve.modules || []), path.resolve('./')]

I was having an issue resolving aliases

Error: Can't resolve '@foo/bar'

In root > .storybook/main.js I added the property config.resolve.alias

const path = require('path');

module.exports = {
  stories: ['../libs/feature/src/**/*.stories.@(js|jsx|ts|tsx)'],
  addons: [
    '@storybook/addon-links',
    '@storybook/addon-essentials',
    '@storybook/addon-interactions',
  ],
  framework: '@storybook/react',
  webpackFinal: async (config, { configType }) => {
    config.resolve.alias = {
      ...config.resolve.alias,
      '@foo/bar': path.resolve(__dirname, '../libs/bar/src/'),
    };

    return config;
  },
};

I think what you need is path aliases. If you're working on a typescript project, you can declare aliases that map to a certain absolute path in your application using tsconfig.json paths compiler option:

"baseUrl": "./src",
"paths": {
  "components/*": ["components/*"],
  "@/common/*": ["common/*"],
 }

Be aware that is not always that easy because in production your build toolchain will have to translate them to the correct paths as tsc doesn’t do it. Fortunately nexjts has added this feature recently => https://nextjs.org/docs/advanced-features/module-path-aliases

Related