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

Storybook is not able to resolve path with Next js absolute import #11639

Closed
rahul3103 opened this issue Jul 22, 2020 · 41 comments · Fixed by #26651
Closed

Storybook is not able to resolve path with Next js absolute import #11639

rahul3103 opened this issue Jul 22, 2020 · 41 comments · Fixed by #26651

Comments

@rahul3103
Copy link

rahul3103 commented Jul 22, 2020

Describe the bug
Storybook is not able to resolve path with Next js absolute import

To Reproduce
Steps to reproduce the behavior:
yarn add storybook
Added .storybook folder
Add jsconfig for absolute import

Expected behavior
It should build correctly.

const path = require('path');
const resolve = (dir) => path.resolve(__dirname, dir);

module.exports = ({ config }) => {
  config.resolve.alias = {
    '@utils/*': resolve('../src/utils/*'),
   ....
  };

  return config;
};

Error


ERROR in ./src/components/Base/Button/Button.jsx
Module not found: Error: Can't resolve '@utils/boxShadowGenerator' in '/Users/rahulshrivastava/projects/unacademy-web-learning/src/components/Base/Button'
 @ ./src/components/Base/Button/Button.jsx 9:0-59 107:35-53 122:9-27
 @ ./src/stories/button.stories.js
 @ ./src/stories sync \.stories\.js$
 @ ./.storybook/config.js
 @ multi ./node_modules/@storybook/core/dist/server/common/polyfills.js ./node_modules/@storybook/core/dist/server/preview/globals.js ./.storybook/config.js (webpack)-hot-middleware/client.js?reload=true&quiet=true

Code snippets
I am using jsconfig.json

{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es2016",
    "jsx": "react",
    "baseUrl": "./src/",
    "paths": {
      "@utils/*": ["utils/*"],
    ....
    }
  },
  "exclude": ["node_modules", "dist"]
}

System:

 npx -p @storybook/cli@next sb info

Environment Info:
(node:1828) UnhandledPromiseRejectionWarning: TypeError: e.filter is not a function
    at /Users/rahulshrivastava/.npm/_npx/1031/lib/node_modules/@storybook/cli/node_modules/envinfo/dist/envinfo.js:1:73205
    at processTicksAndRejections (internal/process/task_queues.js:93:5)
    at async Promise.all (index 6)
(node:1828) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:1828) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
@stale
Copy link

stale bot commented Aug 24, 2020

Hi everyone! Seems like there hasn't been much going on in this issue lately. If there are still questions, comments, or bugs, please feel free to continue the discussion. Unfortunately, we don't have time to get to every issue. We are always open to contributions so please send us a pull request if you would like to help. Inactive issues will be closed after 30 days. Thanks!

@stale stale bot added the inactive label Aug 24, 2020
@EduardoHidalgo
Copy link

I have exactly the same problem! I tried adding a tsconfig.json and with a custom webpack but didn't work.

@stale stale bot removed the inactive label Aug 25, 2020
@oalexdoda
Copy link

+1 - Same issue here. Any idea on how to process Next.js paths in jsconfig.json? I found this on TypeScript (haven't tested it) but need one on Javascript instead: #9610

@kalanda
Copy link

kalanda commented Sep 9, 2020

+1 Same problem here. NextJS resolves but SB don't.

jsconfig.json

{
  "compilerOptions": {
    "baseUrl": "./src"
  }
}

@EduardoHidalgo
Copy link

@kalanda That's correct, Next.js resolve but SB don't. I tried a lot of webpack solutions and multiple tsconfig.json options but anyone was successful. I decided to remove SB for my project for now. Sad.

@GxDesign
Copy link

GxDesign commented Sep 9, 2020

I havent gotten everything working with Next yet but this resolved the absolute import issues (in .storybook/webpack.config.js):

const path = require('path');

module.exports = ({config}) => {
  config.resolve.modules = [
    path.resolve(__dirname, ".."),
    "node_modules",
  ]

  return config
}

For using ./src, you can use path.resolve(__dirname, "..", "src"),

@EduardoHidalgo
Copy link

With SB 6.x you don't have a webpack configuration, instead you use a main.js file with specific import structure (see Storybook React Configure Preview). Please, could you provide the same code in this format?

I havent gotten everything working with Next yet but this resolved the absolute import issues (in .storybook/webpack.config.js):

const path = require('path');

module.exports = ({config}) => {
  config.resolve.modules = [
    path.resolve(__dirname, ".."),
    "node_modules",
  ]

  return config
}

For using ./src, you can use path.resolve(__dirname, "..", "src"),

@GxDesign
Copy link

GxDesign commented Sep 10, 2020

You can still add a webpack.config.js to your .storybook directory. But with main.js, you define it as webpackFinal:

const path = require('path');

module.exports = {
  stories: ["../stories/*.stories.@(js|jsx)"],
  addons: [
    "@storybook/addon-actions",
    "@storybook/addon-knobs",
    "@storybook/addon-links",
  ],
  presets: ["@storybook/preset-scss"],
  webpackFinal: async (config, { configType }) => {
    config.resolve.modules = [
      path.resolve(__dirname, ".."),
      "node_modules",
    ]

    return config;
  }
};

@Fernando-FloresP
Copy link

Hello! I've just tried this fix in a project with Nextjs v9.5.3 and Storybook v6.0.21 but its not working.

On the path /sb-test/stories/Button.stories.js on the the 2nd and 3rd lines you can switch between absolute and relative paths.
The absolute path works but if i use the relative path it doesn't work.

//import { ButtonComponent } from "../src/components/button/Button";
import { ButtonComponent } from "@/Components/button/Button";

This is the error:
image

ERROR in ./stories/Button.stories.js
Module not found: Error: Can't resolve '@/Components/button/Button' in '/mnt/c/Users/reape/sb-test/stories'
@ ./stories/Button.stories.js 85:0-61 88:13-28 97:42-57
@ ./stories sync ^.(?:(?:^|/|(?:(?:(?!(?:^|/).).)?)/)(?!.)(?=.)[^/]?.stories.(js|jsx|ts|tsx))$
@ ./.storybook/generated-stories-entry.js
@ multi ./node_modules/@storybook/core/dist/server/common/polyfills.js ./node_modules/@storybook/core/dist/server/preview/globals.js ./.storybook/storybook-init-framework-entry.js ./node_modules/@storybook/addon-docs/dist/frameworks/common/config.js-generated-other-entry.js ./node_modules/@storybook/addon-docs/dist/frameworks/react/config.js-generated-other-entry.js ./node_modules/@storybook/addon-links/dist/preset/addDecorator.js-generated-other-entry.js ./node_modules/@storybook/addon-actions/dist/preset/addDecorator.js-generated-other-entry.js ./node_modules/@storybook/addon-actions/dist/preset/addArgs.js-generated-other-entry.js ./node_modules/@storybook/addon-backgrounds/dist/preset/defaultParameters.js-generated-other-entry.js ./.storybook/preview.js-generated-config-entry.js ./.storybook/generated-stories-entry.js (webpack)-hot-middleware/client.js?reload=true&quiet=false&noInfo=undefined

@GxDesign
Copy link

Its because thats not an absolute import from root, your path is using an alias. The following code allows you to import from src using "src/components/button/Button":

config.resolve.modules = [
      path.resolve(__dirname, ".."),
      "node_modules",
    ]

But it does not tell webpack anything about the "@/Components" syntax. You would need to pass an alias configuration like this:

config.resolve.alias = {
      ...config.resolve.alias,
      "@/Components": path.resolve(__dirname, "../src/components")
    };

@Fernando-FloresP
Copy link

Great! It worked perfectly, thanks a lot man. I wrote a commit implementing your fix: Absolute path with Storybook problem solved

@EduardoHidalgo
Copy link

I love you man, I spent like about 40 hours trying to solve but I never could. Thanks <3

Its because thats not an absolute import from root, your path is using an alias. The following code allows you to import from src using "src/components/button/Button":

config.resolve.modules = [
      path.resolve(__dirname, ".."),
      "node_modules",
    ]

But it does not tell webpack anything about the "@/Components" syntax. You would need to pass an alias configuration like this:

config.resolve.alias = {
      ...config.resolve.alias,
      "@/Components": path.resolve(__dirname, "../src/components")
    };

@GxDesign
Copy link

GxDesign commented Sep 11, 2020

haha no problem, glad I could help 🍻

@stale
Copy link

stale bot commented Oct 4, 2020

Hi everyone! Seems like there hasn't been much going on in this issue lately. If there are still questions, comments, or bugs, please feel free to continue the discussion. Unfortunately, we don't have time to get to every issue. We are always open to contributions so please send us a pull request if you would like to help. Inactive issues will be closed after 30 days. Thanks!

@stale stale bot added the inactive label Oct 4, 2020
@shilman shilman added the PN label Oct 5, 2020
@stale stale bot removed the inactive label Oct 5, 2020
@shilman shilman added nextjs P1 and removed PN labels Oct 7, 2020
@shilman shilman self-assigned this Oct 8, 2020
@EduardoHidalgo
Copy link

Current direction would be at Next.js level, splitting Next webpack logic feature by feature. It is currently quite monolithic and does a lot of things, which in turns makes it quite difficult to stabilize the Storybook plugin. I am personnaly ok to invest time in this but I might be busy for a while :/ so contributions are welcome.

Taking a look at https://github.com/vercel/next.js/pull/18367/files could help.

Also you may want to check UnlyEd/next-right-now#251, Storybook has been integrated in Next Right Now with good support. I think solving the issue more elegantly at Next level could help simplifiying the code but it seems to do the job.

I don't think NRN should be one the first option. Personally I always prefer an unopininated option. Some SB plugin or an internal Next.js solution will be better.

If you are nice in guide me through the process, I can make a PR (:

@eric-burel
Copy link
Contributor

eric-burel commented Feb 15, 2021

As a starting point you can take a look at this issue, on Next side: vercel/next.js#19345
Relevant logic lives here: https://github.com/vercel/next.js/blob/canary/packages/next/build/webpack-config.ts. You can see that Next has some logic to alter the Webpack config, adding aliases, based on the content of tsconfig or jsconfig files.

You'd want to extract this logic to make it more reusable, that could be the starting point for a simpler Next/storybook plugin. Then you can do this process again and again for each part of the config: going step by step would allow to detect and correct the hard part of each feature (loading CSS, using path aliases, etc. etc.).

What I meant for NRN is that you can take inspiration from their Storybook config without actually using it if you don't feel like it.

Also this PR provides a test example in with-storybook folder: https://github.com/vercel/next.js/pull/18367/files

@Ahmed-osama
Copy link

Its because thats not an absolute import from root, your path is using an alias. The following code allows you to import from src using "src/components/button/Button":

config.resolve.modules = [
      path.resolve(__dirname, ".."),
      "node_modules",
    ]

But it does not tell webpack anything about the "@/Components" syntax. You would need to pass an alias configuration like this:

config.resolve.alias = {
      ...config.resolve.alias,
      "@/Components": path.resolve(__dirname, "../src/components")
    };

thank you man you saved my day

that's how it worked for next.js

const path = require('path');
module.exports = {
  stories: [
    '../desktop/**/*.stories.@(ts|tsx)',
    '../mobile/**/*.stories.@(ts|tsx)',
  ],
  addons: ['@storybook/addon-links', '@storybook/addon-essentials'],
  webpackFinal: async (config, { configType }) => {
    config.resolve.modules = [path.resolve(__dirname, '..'), 'node_modules'];
    config.resolve.alias = {
      ...config.resolve.alias,
      '@': path.resolve(__dirname, '../'),
    };
    return config;
  },
};

@shilman shilman removed this from the 6.2 core milestone Apr 1, 2021
@eric-burel
Copy link
Contributor

Hi, I am going to close this for now, as there are 2 main alternatives:

  • just set Storybook up to reproduce Next.js magic, there are multiple comments demoing how to do so. This is of course not very satisfactory, but it works for the moment.

  • in the meantime we will keep working on @next/plugin-storybook to make this a one-liner, but this takes time as it is not so easy to export Next.js buildtime magic to 3rd parties at the moment. It technically works, but it's not very stable. I'll demo this package usage here: https://github.com/lbke/next-plugin-storybook-demo. It may be included in Next.js as an official example but only when @next/plugin-storybook reach stability. Anyway, this question is on Next.js side at the moment more than SB.

@Matheus8174
Copy link

now just install the next addon in your project.

https://storybook.js.org/addons/storybook-addon-next

@nabu1615
Copy link

nabu1615 commented Jan 11, 2023

After some errors and look a way to work with NEXT components, this config works. ./storybooks/main.js

  const path = require('path');
  
  webpackFinal: async (config, { configType }) => {
    config.resolve.modules = [
        path.resolve(__dirname, '..'),
        'node_modules',
    ];

    config.resolve.alias = {
        ...config.resolve.alias,
        components: path.resolve(__dirname, '../components'),
    };

    return config;
 }

@sendy34
Copy link

sendy34 commented Mar 20, 2023

Anyone still having issues, I had two typescript configurations.
One was on global ts-config but there was another configuration on main.ts for Storybook.
If you have a custom configuration on main.ts, then alias also needs to be defined on that configuration under paths.

Once you define the alias, and resolve the alias using webpackFinal, it should start working fine!

@Sutil
Copy link

Sutil commented Jan 10, 2024

Here is how I solved.

I got the problem because I installed storybook in a Nextjs project that was using Shad cn ui.

On the component.json I replaced the @/ with src/

"aliases": {
-   "components": "@/components",
-   "utils": "@/lib/utils"
+   "components": "src/components",
+   "utils": "src/lib/utils"
  }

On the tsconfig.json I removed the paths and added baseUrl.

-"paths": {
-    "@/*": ["./src/*"]
-  }
+ "baseUrl": "."

After that, I went to the vscode search and replace tool (Ctrl + Shift + F);

And I replaced all @/components with src/components and all @/lib with src/lib.

@shilman
Copy link
Member

shilman commented Mar 15, 2024

@valentinpalkovic @vanessayuenn This was raised on Twitter I've reproduced by editing the Storybook CLI template files:

// stories/Header.tsx
import React from 'react';
import { Button } from '@/stories/Button';

@/* is installed in the Next.js boilerplate by default, so I think we should prioritize fixing this in @storybook/nextjs. WDYT?

@valentinpalkovic
Copy link
Contributor

I would love to work on it!

@gabitoesmiapodo
Copy link

gabitoesmiapodo commented Mar 15, 2024

@shilman @valentinpalkovic I don't know if it helps you or not, but I got it working by doing this: https://stackoverflow.com/a/68288720/7949258

In any case it might help someone having this problem (like me!) until you can fix it.

@weyert
Copy link
Contributor

weyert commented Mar 16, 2024

I thought Storybook already used tsconfig-paths-webpack-plugin?

@valentinpalkovic
Copy link
Contributor

valentinpalkovic commented Mar 26, 2024

Actually, tsconfig-paths-webpack-plugin is configured for Next.js. However, to activate the plugin, you have to define the baseUrl in your tsconfig.json. If baseUrl isn't defined, the plugin doesn't get initialized.

@thewanionly
Copy link

For my case, adding "baseUrl": "." in my tsconfig.json fixes the issue:

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

@valentinpalkovic
Copy link
Contributor

This was fixed by #26651. The fix will be part of the 8.0.6 release!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment