wmonk/create-react-app-typescript

Using Storybook without ejecting

colinramsay opened this issue ยท 10 comments

I don't believe this is a bug, just an oversight. While the README says that Storybook (https://storybook.js.org/) will work, I think that's just copied over from CRA.

The Storybook docs (https://storybook.js.org/configurations/typescript-config/) seem to indicate that you'd need to eject to get it working.

Has anyone successful used Storybook + create-react-app-typescript without ejecting?

r3nya commented

Hey @colinramsay!

Yeah, you can use it w/o ejecting.
Please create .storybook directory and insert webpack.config.js

const path = require("path");
const TSDocgenPlugin = require("react-docgen-typescript-webpack-plugin"); // Optional
module.exports = (baseConfig, env, config) => {
  config.module.rules.push({
    test: /\.(ts|tsx)$/,
    loader: require.resolve("ts-loader")
  });
  config.plugins.push(new TSDocgenPlugin()); // optional
  config.resolve.extensions.push(".ts", ".tsx");
  return config;
};

.storybook/config.js

import { configure } from '@storybook/react';
// automatically import all files ending in *.stories.js
const req = require.context('../', true, /.stories.tsx$/);
function loadStories() {
  req.keys().forEach(filename => req(filename));
}
configure(loadStories, module);

And in your tsconfig.json update rootDirs field to:

"rootDirs": ["src", "stories"],
r3nya commented

Hey @colinramsay! Any news? ๐Ÿ˜‰

I've tried it, and it works, though I have to use NODE_PATH=src npm run storybook to successfully load my project's components. It's possible that the baseUrl is considered relative to .storybook/webpack.config.js, and an additional tsconfig.storybook.json extending the base tsconfig with baseUrl: "../src" could fix that problem, if that is the problem. However using the command above it works perfectly.

@r3nya for some reason the notification went to spam, I'll check this out and come back to you!

r3nya commented

@colinramsay oh, got it.

Let me know if you will have any problems. ;)

This is working perfectly now, thank you both!

I take that back ๐Ÿ˜„

I have the following in tsconfig.json in the root of my project:

   "paths": {
      "app/*": ["src/*"]
    }

This allows me to import files using app/somefile.ts rather than ../../somefile.ts.

I tried changing the webpack.config.js to account for this:

const path = require('path')

module.exports = (baseConfig, env, config) => {
  config.resolve.alias = {
    app: path.resolve('../src/'),
  }
  config.module.rules.push({
    test: /\.(ts|tsx)$/,
    loader: require.resolve('ts-loader'),
    options: {
      configFile: '../tsconfig.json',
    },
  })
  config.resolve.extensions.push('.ts', '.tsx')
  return config
}

No joy. Any ideas?

I am not a webpack/tsconfig expert, but I know that it works out of the box sans app/ for me. I also use absolute paths from the src directory, so I would include your file above with import "somefile.ts". (to clarify, I'd also import a file from /src/containers/header from src/components/header by using import "containers/header/headerContainer.tsx";)

I believe this is accomplished via either the "baseUrl" or "rootDir" compiler option, and is probably the reason I have to run the storybook command with NODE_PATH=src

@colinramsay The main thing that we have that is different from yours is that where you have app: path.resolve('../src/'), we have it anchored from the directory where the config file sits: src: path.resolve(__dirname, '..', 'src') (we use 'src' instead of 'app' for the alias, but otherwise doing the same thing). Likewise for the path to the tsconfig.json file in the ts-loader configuration block.

I wonder if when running storybook from the top level directory your '..' paths are trying to apply from that level?

Otherwise it should be pretty much standard - in tsconfig.json,

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "src/*": ["src/*"]    // you'd have "app/*": ["src/*"]
    }
  }
}

and NODE_PATH='.' in the top level scripts.

Changing to use path.resolve(__dirname, '..', 'src') made it work as expected. Thank you all!