storybookjs / storybook

Storybook is the industry standard workshop for building, documenting, and testing UI components in isolation
https://storybook.js.org
MIT License
84.66k stars 9.32k forks source link

Next.js + TypeScript + Storybook compatibility issues #9610

Closed stephenkoo closed 1 year ago

stephenkoo commented 4 years ago

Describe the bug Following the TypeScript instructions & recommended config in the Storybook docs results in TS2769: No overload matches this call errors when running build storybook with Next.js.

Specifically in my Next.js setup:

  1. /src/stories/0-Welcome.stories.tsx(8,54) 2./src/stories/1-Button.stories.tsx(8,48)

To Reproduce Steps to reproduce the behavior:

  1. Clone to https://github.com/stephenkoo/aesther/compare/sk/feat-add-storybook
  2. Run yarn storybook

Expected behavior Storybook to run with no errors.

Screenshots

image

Code snippets

The following are changes & additions made to out-of-the-box Next.js & TS setup based on Storybook TS Config documentation + some Storybook addons

.storybook/main.ts:

const path = require('path')

module.exports = {
  stories: ['../src/**/*.stories.(tsx|mdx)'],
  addons: [
    // Addons
    '@storybook/addon-a11y/register',
    '@storybook/addon-actions/register',
    '@storybook/addon-knobs/register',
    '@storybook/addon-links/register',
    '@storybook/addon-storysource/register',
    // Presets
    {
      name: '@storybook/preset-typescript',
      options: {
        tsLoaderOptions: {
          configFile: path.resolve(__dirname, '../tsconfig.json'),
        },
        tsDocgenLoaderOptions: {
          tsconfigPath: path.resolve(__dirname, '../tsconfig.json'),
        },
        forkTsCheckerWebpackPluginOptions: {
          colors: false, // disables built-in colors in logger messages
        },
        include: [path.resolve(__dirname, '../src')],
      },
    },
  ],
  webpackFinal: async config => {
    config.module.rules.push({
      test: /\.(ts|tsx)$/,
      use: [
        {
          loader: require.resolve('awesome-typescript-loader'),
        },
        {
          loader: require.resolve('react-docgen-typescript-loader'),
        },
      ],
    })
    config.resolve.extensions.push('.ts', '.tsx')
    return config
  },
}

.storybook/preview.ts:

import { addDecorator } from '@storybook/react'
import { withA11y } from '@storybook/addon-a11y'
import { withInfo } from '@storybook/addon-info'

addDecorator(withInfo)
addDecorator(withA11y)

jest.config.js

const { pathsToModuleNameMapper } = require('ts-jest/utils')
const { compilerOptions } = require('./tsconfig')

module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  /**
   * Make tsconfig paths work in Jest
   * https://kulshekhar.github.io/ts-jest/user/config/#jest-config-with-helper
   */
  moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths),
  // New stuff (not sure if needed)
  transform: {
    '.(ts|tsx)': 'ts-jest',
  },
  testPathIgnorePatterns: ['/node_modules/', '/lib/'],
  testRegex: '(/test/.*|\\.(test|spec))\\.(ts|tsx)$',
  moduleFileExtensions: ['ts', 'tsx', 'js', 'json'],
  // End new stuff
}

tsconfig.json (some are Next.js defaults, some are Storybook recommended tsconfig.js settings)

{
  "compilerOptions": {
    "target": "es6",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": false,
    "skipLibCheck": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "react",
    "noUnusedLocals": true,
    "sourceMap": true,
    "baseUrl": ".",
    "declaration": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "outDir": "build/lib",
    "paths": {
      "@App/*": ["src/*"]
    },
    "rootDirs": ["src"]
  },
  "exclude": ["node_modules", "build", "scripts"],
  "include": ["next-env.d.ts", "src/**/*"]
}

package.json scripts

  "scripts": {
    "dev": "next",
    "start": "next start",
    "storybook": "start-storybook -p 6006",
    "build": "yarn run lint && yarn run build-lib && build-storybook && next build",
    "build-lib": "tsc && yarn run copy-svg-to-lib && yarn run copy-png-to-lib",
    "build-lib-watch": "tsc -w",
    "build-storybook": "build-storybook",
    "copy-svg-to-lib": "cpx \"./src/**/*.svg\" ./build/lib",
    "copy-png-to-lib": "cpx \"./src/**/*.png\" ./build/lib",
    "lint": "tslint -c tslint.json './src/**/*.{ts,tsx}'",
    "test": "jest",
    "test:watch": "jest --watch",
    "test:coverage": "jest -- --coverage"
  },

System:

Environment Info:

  System:
    OS: macOS 10.15.2
    CPU: (4) x64 Intel(R) Core(TM) i7-5557U CPU @ 3.10GHz
  Binaries:
    Node: 13.6.0 - ~/.nvm/versions/node/v13.6.0/bin/node
    Yarn: 1.21.1 - ~/.yarn/bin/yarn
    npm: 6.13.6 - ~/.nvm/versions/node/v13.6.0/bin/npm
  Browsers:
    Chrome: 79.0.3945.130
    Safari: 13.0.4
  npmPackages:
    @storybook/addon-a11y: ^5.3.8 => 5.3.8 
    @storybook/addon-actions: ^5.3.8 => 5.3.8 
    @storybook/addon-docs: ^5.3.8 => 5.3.8 
    @storybook/addon-info: ^5.3.8 => 5.3.8 
    @storybook/addon-knobs: ^5.3.8 => 5.3.8 
    @storybook/addon-links: ^5.3.8 => 5.3.8 
    @storybook/addon-storysource: ^5.3.8 => 5.3.8 
    @storybook/addons: ^5.3.8 => 5.3.8 
    @storybook/preset-typescript: ^1.2.0 => 1.2.0 
    @storybook/react: ^5.3.8 => 5.3.8 

Additional context I'm just trying to set up the simplest Next.js, TS, Storybook (& Jest, Styled Components) setup with reasonable presets.

eric-burel commented 3 years ago

For anyone interested with Storybook with Next.js 10 + TS 4.1 + jest + cypress 6 + Emotion 11 + tons of other stuff, check out UnlyEd/next-right-now#251 (PR)

It's still a WIP, but I've fixed the most complicated issues I was meant to encounter (babel/webpack, react providers, mocks).

Static version auto-hosted on vercel, deployed by github actions automatically. Heavily documented, for my own sake.

Awesome news that you plugged Storybook in! Did you manage to make CSS modules work out of the box? To me it's the main blocker to be able to close this specific issue. There might be other problems, unsupported features etc. that we may solve step by step, but CSS modules out of the box is really expected because that's the kind of stuff beginners want to use asap.

For the record, we've been working on https://github.com/vercel/next.js/issues/19345 (@next/plugin-storybook) lately. We've come to the conclusion that Next webpack-config.ts need a cleanup before we can make a more robust Storybook plugin. I intend to dedicate some times to those issues in the first half of this year, feel free to reach out.

Vadorequest commented 3 years ago

If your question is "can you load .css files directly from Storybook" the answer is yes.

I didn't try it out with CSS modules specifically, as I don't use them. I'll give it a try.

Vadorequest commented 3 years ago

@eric-burel I successfully added support for CSS modules. It wasn't working by default, as you pointed out. But using https://www.npmjs.com/package/storybook-css-modules-preset basically fixed it for me.

See commit https://github.com/UnlyEd/next-right-now/commit/777c3ce32ba13415b2ebd044b7e7b8ef1fe935a5

Storybook demo at https://nrn-v2-mst-aptd-at-lcz-sty-storybook.vercel.app/?path=/story/utilities-i18nlink--link-with-css-module

upeguiborja commented 3 years ago

I am also getting an error related to this setup but I don't know if it is related to NextJS, we have a monorepo setup with two NextJS projects and a shared component library. The error appears when I use main.ts instead of main.js in my .storybook folder, it seems to be that ts-node is trying to parse the typescript file as common js even though it is set to esnext in the compilerOptions.

My tsconfig.json (top level)

{
    "compilerOptions": {
        "target": "ES2020",
        "lib": ["dom", "dom.iterable", "esnext"],
        "allowJs": true,
        "skipLibCheck": true,
        "strict": false,
        "forceConsistentCasingInFileNames": true,
        "noEmit": true,
        "esModuleInterop": true,
        "module": "esnext",
        "moduleResolution": "node",
        "resolveJsonModule": true,
        "isolatedModules": true,
        "jsx": "preserve",
        "baseUrl": "."
    },
    "include": [
        "app/**/*",
        "marketing/**/*",
        "shared/**/*",
        "stories/**/*",
        ".storybook/**/*"
    ],
    "exclude": ["node_modules"]
}

My main.ts file

import type { StorybookConfig } from "@storybook/react/types";

const config: StorybookConfig = {
    stories: [
        "../stories/**/*.stories.mdx",
        "../stories/**/*.stories.@(js|jsx|ts|tsx)",
    ],
    addons: [
        "@storybook/react",
        "@storybook/addon-essentials",
        "@storybook/addon-links",
        { name: "@storybook/preset-typescript" },
    ],
};

module.exports = config;

And the error I get

yarn run v1.22.11
$ start-storybook -p 6006
info @storybook/react v6.3.10
info 
ERR! /Users/xxxxxx/Projects/xxxxxx/xxxxxx/.storybook/main.ts:14
ERR! export {};
ERR! ^^^^^^
ERR! 
ERR! SyntaxError: Unexpected token 'export'
ERR!     at Object.compileFunction (node:vm:352:18)
ERR!     at wrapSafe (node:internal/modules/cjs/loader:1031:15)
ERR!     at Module._compile (node:internal/modules/cjs/loader:1065:27)
ERR!     at Module.m._compile (/Users/xxxxxx/Projects/xxxxxx/xxxxxx/node_modules/ts-node/src/index.ts:1310:23)
ERR!     at Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
ERR!     at Object.require.extensions.<computed> [as .ts] (/Users/xxxxxx/Projects/xxxxxx/xxxxxx/node_modules/ts-node/src/index.ts:1313:12)
ERR!     at Module.load (node:internal/modules/cjs/loader:981:32)
ERR!     at Function.Module._load (node:internal/modules/cjs/loader:822:12)
ERR!     at Module.require (node:internal/modules/cjs/loader:1005:19)
ERR!     at require (node:internal/modules/cjs/helpers:102:18)
ERR!     at interopRequireDefault (/Users/xxxxxx/Projects/xxxxxx/xxxxxx/node_modules/@storybook/core-common/dist/cjs/utils/interpret-require.js:64:16)
ERR!     at serverRequire (/Users/xxxxxx/Projects/xxxxxx/xxxxxx/node_modules/@storybook/core-common/dist/cjs/utils/interpret-require.js:101:10)
ERR!     at getPreviewBuilder (/Users/xxxxxx/Projects/xxxxxx/xxxxxx/node_modules/@storybook/core-server/dist/cjs/utils/get-preview-builder.js:25:55)
ERR!     at buildDevStandalone (/Users/xxxxxx/Projects/xxxxxx/xxxxxx/node_modules/@storybook/core-server/dist/cjs/build-dev.js:99:71)
ERR!     at processTicksAndRejections (node:internal/process/task_queues:96:5)
ERR!     at async buildDev (/Users/xxxxxx/Projects/xxxxxx/xxxxxx/node_modules/@storybook/core-server/dist/cjs/build-dev.js:154:5)
ERR!  /Users/xxxxxx/Projects/xxxxxx/xxxxxx/.storybook/main.ts:14
ERR! export {};
ERR! ^^^^^^
ERR! 
ERR! SyntaxError: Unexpected token 'export'
ERR!     at Object.compileFunction (node:vm:352:18)
ERR!     at wrapSafe (node:internal/modules/cjs/loader:1031:15)
ERR!     at Module._compile (node:internal/modules/cjs/loader:1065:27)
ERR!     at Module.m._compile (/Users/xxxxxx/Projects/xxxxxx/xxxxxx/node_modules/ts-node/src/index.ts:1310:23)
ERR!     at Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
ERR!     at Object.require.extensions.<computed> [as .ts] (/Users/xxxxxx/Projects/xxxxxx/xxxxxx/node_modules/ts-node/src/index.ts:1313:12)
ERR!     at Module.load (node:internal/modules/cjs/loader:981:32)
ERR!     at Function.Module._load (node:internal/modules/cjs/loader:822:12)
ERR!     at Module.require (node:internal/modules/cjs/loader:1005:19)
ERR!     at require (node:internal/modules/cjs/helpers:102:18)
ERR!     at interopRequireDefault (/Users/xxxxxx/Projects/xxxxxx/xxxxxx/node_modules/@storybook/core-common/dist/cjs/utils/interpret-require.js:64:16)
ERR!     at serverRequire (/Users/xxxxxx/Projects/xxxxxx/xxxxxx/node_modules/@storybook/core-common/dist/cjs/utils/interpret-require.js:101:10)
ERR!     at getPreviewBuilder (/Users/xxxxxx/Projects/xxxxxx/xxxxxx/node_modules/@storybook/core-server/dist/cjs/utils/get-preview-builder.js:25:55)
ERR!     at buildDevStandalone (/Users/xxxxxx/Projects/xxxxxx/xxxxxx/node_modules/@storybook/core-server/dist/cjs/build-dev.js:99:71)
ERR!     at processTicksAndRejections (node:internal/process/task_queues:96:5)
ERR!     at async buildDev (/Users/xxxxxx/Projects/xxxxxx/xxxxxx/node_modules/@storybook/core-server/dist/cjs/build-dev.js:154:5)

WARN Broken build, fix the error above.
WARN You may need to refresh the browser.

error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

And when I change the module option to commonjs under tsconfig.json everything works fine.

valentinpalkovic commented 1 year ago

In Storybook 7.x (currently in alpha), we have improved the Next.js > v12 support. We are delivering a zero-config experience now. Try now to upgrade to the latest prerelease!

npx sb@next upgrade --prerelease

Closing this for now. Please reopen if the issue is still relevant.

mateuspiresl commented 1 year ago

I have upgraded Storybook, as @valentinpalkovic advised (thanks), and the problem was gone, but another one related to SASS showed up because I had the @storybook/preset-scss addon in my main.js. Removing that addon fixed the new issue.