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 4 + create-react-app 2 + Typescript: loader issue #4739

Closed
ibrambe opened this issue Nov 6, 2018 · 18 comments

Comments

@ibrambe
Copy link

commented Nov 6, 2018

Describe the bug
I'm trying to setup a storybook using the guidelines here: https://storybook.js.org/configurations/typescript-config, but this doesn't seem to be accurate (anymore).

To Reproduce

npx create-react-app my-app
yarn add -D typescript @types/node @types/react @types/react-dom @types/jest

Rename react files from .js to .ts/.tsx

npx -p @storybook/cli sb init
yarn add -D awesome-typescript-loader
yarn add -D @types/storybook__react
yarn add -D @storybook/addon-info react-docgen-typescript-webpack-plugin

Results in following depedencies:

{
  "dependencies": {
    "react": "^16.6.0",
    "react-dom": "^16.6.0",
    "react-scripts": "2.1.1"
  },
  "devDependencies": {
    "@babel/core": "^7.1.2",
    "@storybook/addon-actions": "^4.0.4",
    "@storybook/addon-info": "^4.0.4",
    "@storybook/addon-links": "^4.0.4",
    "@storybook/addons": "^4.0.4",
    "@storybook/react": "^4.0.4",
    "@types/jest": "^23.3.9",
    "@types/node": "^10.12.2",
    "@types/react": "^16.4.18",
    "@types/react-dom": "^16.0.9",
    "@types/storybook__react": "^3.0.9",
    "awesome-typescript-loader": "^5.2.1",
    "babel-loader": "^8.0.4",
    "react-docgen-typescript-webpack-plugin": "^1.1.0",
    "typescript": "^3.1.6"
  }
}

Copy tsconfig.json + .storybook/webpack.config.js from https://storybook.js.org/configurations/typescript-config/

Add simple button component:

// src/components/button/Button.tsx

import * as React from "react";

interface ButtonProps {
    label: string
}
export const Button: React.SFC<ButtonProps> = (props) => {
    return <button>{props.label}</button>;
}

Add Storybook config

// .storybook/config.ts

import { configure } from '@storybook/react';

const req = require.context('../src/stories', true, /\.tsx$/);

configure(() => {
  req.keys().forEach(filename => req(filename));
}, module);

Add story

// src/stories/index.tsx

import React from 'react';

import { storiesOf } from '@storybook/react';
import { Button } from '../components/button/Button';

const stories = storiesOf('Button', module);

stories.add(
    'test', 
    () => <Button>Test</Button>,
);

Expected behavior
yarn storybook should mount a storybook with one story.

Screenshots
schermafbeelding 2018-11-06 om 16 53 32

Code snippets
I also had to remove "isolatedModules": true from tsconfig.json before I could get the storybook running.

System:

  • OS: MacOS
  • Browser: Chrome
  • Framework: react
  • Version: 4.0.4

Additional context
Storybook 4 + create-react-app 2.1 without typescript enabled works like a charm :)

@ashutoshrishi

This comment has been minimized.

Copy link

commented Nov 8, 2018

CRA 2.0 typescript config wants "jsx": "preserve" so that it can use babel to transform the JSX. But storybook wants "jsx": "react".

@ibrambe

This comment has been minimized.

Copy link
Author

commented Nov 8, 2018

Okay @ashutoshrishi , thanks for clearing that out.

It seems like yarn start in a CRA 2 app alters tsconfig.json and thus overwrites the suggested Storybook tsconfig:

cra

Is there a way to use the same config for Storybook as CRA 2?

@ibrambe

This comment has been minimized.

Copy link
Author

commented Nov 8, 2018

Found the solution here: https://vincenttunru.com/migrate-create-react-app-typescript-to-create-react-app: a custom tsconfig.json for Storybook.

// .storybook/tsconfig.json

{
    "extends": "../tsconfig",
    "compilerOptions": {
      "jsx": "react",
      "isolatedModules": false,
      "noEmit": false
  }
}
// .storybook/webpack.config.js

const path = require('path');
const TSDocgenPlugin = require('react-docgen-typescript-webpack-plugin');
module.exports = (baseConfig, env, config) => {
  config.module.rules.push({
    test: /\.(ts|tsx)$/,
    loader: require.resolve('awesome-typescript-loader'),
    options: { configFileName: path.resolve(__dirname, './tsconfig.json') } // << added 
  });
  config.plugins.push(new TSDocgenPlugin()); // optional
  config.resolve.extensions.push('.ts', '.tsx');
  return config;
};
@mohamedmansour

This comment has been minimized.

Copy link
Contributor

commented Nov 10, 2018

This is incorrect, please follow my guide #4763 you shouldn't use awesome-typescript-loader you should use babel-loader which is inside cra2

@ibrambe

This comment has been minimized.

Copy link
Author

commented Nov 10, 2018

@mohamedmansour this works like a charm indeed:

  config.module.rules.push({
    test: /\.(ts|tsx)$/,
    loader: require.resolve('babel-loader'),
    options: {
        presets: [['react-app', { flow: false, typescript: true }]]
      }
  });

no need for awesome-typescript-loader anymore.

@fayway

This comment has been minimized.

Copy link

commented Nov 10, 2018

For CRA using react-scripts-ts(Microsoft/TypeScript-React-Starter), I had to install:
yarn add -D @babel/preset-typescript

And use the following .storybook/webpack.config.js

module.exports = (baseConfig, env, config) => {
    config.module.rules.push({
        test: /\.(ts|tsx)$/,
        loader: require.resolve('babel-loader'),
        options: {
            presets: ['@babel/preset-react', '@babel/preset-typescript']
        }
    });
    config.resolve.extensions.push('.ts', '.tsx');
    return config;
};
@vitalybe

This comment has been minimized.

Copy link

commented Nov 13, 2018

@ibrambe

@mohamedmansour this works like a charm indeed:

  config.module.rules.push({
    test: /\.(ts|tsx)$/,
    loader: require.resolve('babel-loader'),
    options: {
        presets: [['react-app', { flow: false, typescript: true }]]
      }
  });

no need for awesome-typescript-loader anymore.

It semi-works - It indeed compiles TypeScript but it also doesn't do any type validation, e.g:

const a: number = "d";

In a story works without any error.

@igor-dv

This comment has been minimized.

Copy link
Member

commented Nov 14, 2018

you can use fork-ts-checker-webpack-plugin for this.

@ibrambe

This comment has been minimized.

Copy link
Author

commented Nov 14, 2018

@vitalybe @igor-dv

Upgraded to storybook 4.0.6 and using this as webpack.config.js:

// .storybook/webpack.config.js

const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin-alt');

module.exports = (baseConfig, env, config) => {
  config.module.rules.push({
    test: /\.(ts|tsx)$/,
    loader: require.resolve('babel-loader'),
    options: {
        presets: [require.resolve('babel-preset-react-app')]
      }
  });

  config.resolve.extensions.push('.ts', '.tsx');

  config.plugins.push(
    new ForkTsCheckerWebpackPlugin({
        async: false,
        checkSyntacticErrors: true,
        formatter: require('react-dev-utils/typescriptFormatter'),
      }),
  );

  return config;
};

This works and has live type validation, it's based on the config in react-scripts, so all dependencies are already loaded if you use CRA 2.

@dfee

This comment has been minimized.

Copy link

commented Nov 17, 2018

@ibrambe: why are you using fork-ts-checker-webpack-plugin-alt instead of fork-ts-checker-webpack-plugin?

@ibrambe

This comment has been minimized.

Copy link
Author

commented Nov 18, 2018

@ibrambe: why are you using fork-ts-checker-webpack-plugin-alt instead of fork-ts-checker-webpack-plugin?

I have no clue, wasn't on purpose :)

@shilman shilman added the cra label Nov 22, 2018

@falkolab

This comment has been minimized.

Copy link

commented Dec 19, 2018

@ibrambe how to configure babel-loader with custom tsconfig.json path? I can't find it.

@harry-sm

This comment has been minimized.

Copy link

commented Dec 26, 2018

After following the example here

Cannot find module 'react-scripts\config\webpack.config.dev'

using packages

{
...,
"@storybook/react": "^4.1.3",
"@storybook/addon-actions": "^4.1.3",
"react-docgen-typescript-webpack-plugin": "^1.1.0",
"react-scripts": "2.1.2",
...
}

Has anyone encountered this issue also?

@osi-oswald

This comment has been minimized.

Copy link

commented Dec 27, 2018

Has anyone encountered this issue also?

@harry-sm Same here, using 4.0.x instead of 4.1.x worked

@harry-sm

This comment has been minimized.

Copy link

commented Dec 27, 2018

@osi-oswald
4.0.x works thanks.

@hatton

This comment has been minimized.

Copy link

commented Apr 13, 2019

In webpack.config.js, I was getting

TypeScript error: Cannot compile namespaces when the '--isolatedModules' flag is provided. TS1208

Worked around this by adding
export function dummy() {}

to the top of that file. It would make more sense to tell CRA to ignore .stories/, but I don't know how.

@bhargavshah

This comment has been minimized.

Copy link

commented Aug 6, 2019

@mohamedmansour this works like a charm indeed:

  config.module.rules.push({
    test: /\.(ts|tsx)$/,
    loader: require.resolve('babel-loader'),
    options: {
        presets: [['react-app', { flow: false, typescript: true }]]
      }
  });

no need for awesome-typescript-loader anymore.

Hi, @mohamedmansour @ibrambe. This worked for me! Can you please explain this? Didn't quite get my head around this :/

@reggi

This comment has been minimized.

Copy link

commented Aug 6, 2019

This works:

module.exports = ({config}) => {
  config.module.rules.push({
    test: /\.(ts|tsx)$/,
    loader: require.resolve('react-scripts/node_modules/babel-loader'),
    options: {
        presets: [require.resolve('babel-preset-react-app')]
      }
  });

  config.resolve.extensions.push('.ts', '.tsx');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
You can’t perform that action at this time.