Gatsby: Using React Storybook with Gatsby

Created on 10 Jan 2017  Β·  37Comments  Β·  Source: gatsbyjs/gatsby

I tried setting up https://github.com/storybooks/react-storybook in my gatsby project, but i quickly felt blocked because i needed a webpack config that gatsby is using to resolve my components/imports that would work for react storybook.

Do you have any recommendations on how to use react storybook with gatsby?

question or discussion

Most helpful comment

I've invested some time into getting React Storybook working with Gatsby -- i'll paste the gist of it in here, but keen to understand if there's a desire to merge something in to this repo as an example or readme update?

For anyone else that attempts this, the crux of it is to create a custom react storybook webpack config that uses all of gatsby's config, except the entry and output, which it uses from the react storybook config. The tricky part was the way you were creating the webpack config and the resolve() function. Anyways, refer to the below file (you'll need to install the storybook packages, etc):

.storybook/wepack.config.js

const path = require('path');
const gatsbyWebpack = require('gatsby/dist/utils/webpack.config');

const directory = path.resolve(__dirname, '../');
const suppliedStage = 'develop';
const program = {
  directory,
};

const config = gatsbyWebpack(program, directory, suppliedStage).resolve();

module.exports = function customiseStorybookConfig(storybookBaseConfig) {
  // Replace parts of react storybook webpack config with gatsby webpack config.
  config.entry = storybookBaseConfig.entry;
  config.output = storybookBaseConfig.output;

  return config;
};

You'll also need stories and a react storybook config file, our stories live inside the component directories, and are named to match the [component].stories.jsx, e.g:

.storybook/config.js

import _ from 'lodash';
import { configure } from '@kadira/storybook';

const req = require.context('../components', true, /.stories.jsx$/);

function loadStories() {
  _.forEach(req.keys(), req);
}

configure(loadStories, module);

All 37 comments

I haven't used React Storybook much but love the idea. Would love it if there was an easy way to get it working with Gatsby components. React Storybook would be just as useful with Gatsby sites as any other React app.

Gatsby's webpack config is at https://github.com/gatsbyjs/gatsby/blob/master/lib/utils/webpack.config.js β€” it's pretty vanilla Webpack config for the most part β€” have you had a chance to look through the config file? If it's hard to trace what's going on, you can console.log at the end the final config.

I've invested some time into getting React Storybook working with Gatsby -- i'll paste the gist of it in here, but keen to understand if there's a desire to merge something in to this repo as an example or readme update?

For anyone else that attempts this, the crux of it is to create a custom react storybook webpack config that uses all of gatsby's config, except the entry and output, which it uses from the react storybook config. The tricky part was the way you were creating the webpack config and the resolve() function. Anyways, refer to the below file (you'll need to install the storybook packages, etc):

.storybook/wepack.config.js

const path = require('path');
const gatsbyWebpack = require('gatsby/dist/utils/webpack.config');

const directory = path.resolve(__dirname, '../');
const suppliedStage = 'develop';
const program = {
  directory,
};

const config = gatsbyWebpack(program, directory, suppliedStage).resolve();

module.exports = function customiseStorybookConfig(storybookBaseConfig) {
  // Replace parts of react storybook webpack config with gatsby webpack config.
  config.entry = storybookBaseConfig.entry;
  config.output = storybookBaseConfig.output;

  return config;
};

You'll also need stories and a react storybook config file, our stories live inside the component directories, and are named to match the [component].stories.jsx, e.g:

.storybook/config.js

import _ from 'lodash';
import { configure } from '@kadira/storybook';

const req = require.context('../components', true, /.stories.jsx$/);

function loadStories() {
  _.forEach(req.keys(), req);
}

configure(loadStories, module);

@tonymilne, I'm also interested in an idea of Gatsby and Storybook integration!
And I'd like to try the configs given by you.
But maybe you could share the whole repo with this solution? It could speed up my progress :bowtie:

@tonymilne this looks fantastic! This could be a really good fit for some upcoming client work of mine. Agree with @UsulPro β€” this would be a good fit to put in a separate repo (and publish to NPM). Then you could just run npm install --save gatsby-plugin-react-storybook and get to work.

Using the provided config it works great in develop. But after adding some components with css modules, when I run gatsby build, I get a postcss error:

Generating CSS
Generating Static HTML
Failed at generating HTML

Users/User/Sites/My-Project/node_modules/gatsby/dist/bin/cli.js:42
      throw err;
      ^
Error: ./~/css-loader?modules&minimize&importLoaders=1!./~/postcss-loader!./components/responsive-video/index.module.css
Module build failed: Error: No PostCSS Config found in: /Users/User/Sites/My-Project/components/responsive-video
    at /Users/User/Sites/My-Project/node_modules/postcss-load-config/index.js:51:26

 @ ./components/responsive-video/index.module.css 4:14-164,./~/css-loader?modules&minimize&importLoaders=1!./~/postcss-loader!./components/feature-video/index.module.css
Module build failed: Error: No PostCSS Config found in: /Users/User/Sites/My-Project/components/feature-video
    at /Users/User/Sites/My-Project/node_modules/postcss-load-config/index.js:51:26

 @ ./components/feature-video/index.module.css 4:14-164,./components/feature-video/index.module.css
Module build failed: Error
    at NormalModule.onModuleBuildFailed (/Users/User/Sites/My-Project/node_modules/webpack-core/lib/NormalModuleMixin.js:315:19)
    at nextLoader (/Users/User/Sites/My-Project/node_modules/webpack-core/lib/NormalModuleMixin.js:270:31)
    at /Users/User/Sites/My-Project/node_modules/webpack-core/lib/NormalModuleMixin.js:292:15
    at context.callback (/Users/User/Sites/My-Project/node_modules/webpack-core/lib/NormalModuleMixin.js:148:14)
    at /Users/User/Sites/My-Project/node_modules/postcss-loader/index.js:126:13
,./components/responsive-video/index.module.css
Module build failed: Error
    at NormalModule.onModuleBuildFailed (/Users/User/Sites/My-Project/node_modules/webpack-core/lib/NormalModuleMixin.js:315:19)
    at nextLoader (/Users/User/Sites/My-Project/node_modules/webpack-core/lib/NormalModuleMixin.js:270:31)
    at /Users/User/Sites/My-Project/node_modules/webpack-core/lib/NormalModuleMixin.js:292:15
    at context.callback (/Users/User/Sites/My-Project/node_modules/webpack-core/lib/NormalModuleMixin.js:148:14)
    at /Users/User/Sites/My-Project/node_modules/postcss-loader/index.js:126:13
,Error: Cannot find module "!!./../../node_modules/css-loader/index.js?modules&minimize&importLoaders=1!./../../node_modules/postcss-loader/index.js!./index.module.css"
    at webpackMissingModule (render-page.js:54791:80)
    at Object.defineProperty.value (render-page.js:54791:296)
    at __webpack_require__ (render-page.js:30:30)
    at Object.<anonymous> (render-page.js:54750:21)
    at __webpack_require__ (render-page.js:30:30)
    at Object.module.exports.id (render-page.js:52121:22)
    at __webpack_require__ (render-page.js:30:30)
    at webpackContext (render-page.js:51937:10)
    at render-page.js:25152:18
    at Array.forEach (native)
.
.

If I remove storybook from node_modules, this error goes away. I'm not sure if I need to make changes to the storybook webpack config or if this error is caused from something else.

After trying a bunch of things the following worked for me.

Add postcss.config.js to root containing: module.exports = {};

https://github.com/akveo/ng2-admin/issues/604#issuecomment-271974780

Wish I understood why this is.

FYI I've just updated the Storybooks docs site to use Gatsby. So it's both an example site for gatsby and also an example of using Storybook within a Gatsby site. cc @KyleAMathews

https://storybooks.js.org
https://github.com/storybooks/storybooks.github.io

It's kind of a weird setup because it used to be a CRA app and I wanted to preserve as much of the original structure as I could, but it seems to be working well. Here's the PR for anybody who is interested in the changes:

https://github.com/storybooks/storybooks.github.io/pull/14

@shilman it's strange, but the docs reload the whole page on every path change

@shilman yeah perhaps you're not using the react-router <Link> component? You should use that with Gatsby vs. normal <a> elements.

Thanks @g8tguy @KyleAMathews just saw this and have fixed it now https://github.com/storybooks/storybooks.github.io/issues/41.

Thanks for your help! πŸ™

@UsulPro do you think we could add @tonymilne 's solution to getstorybook to autodetect gastby projects and set this up automagically? That would be really cool.

@shilman that would be cool!

@shilman It's a great idea! The more project we can support the better!

just tried @tonymilne's solution however with no luck, receiving this following error in console:

TypeError: gatsbyWebpack(...).resolve is not a function

seeing that it might have something to do with the function being async, I attempted:

const config = gatsbyWebpack(program, directory, suppliedStage).then(config => {
  return config.resolve();
}).catch(e => {
  console.log(e);
});

this subsequently spat out another error:

TypeError: Cannot convert undefined or null to object
    at from (native)
    at exports.default (/.../node_modules/babel-runtime/helpers/toConsumableArray.js:19:31)
    at resolve (/.../node_modules/gatsby/dist/utils/webpack.config.js:261:73)
    at _callee$ (/.../node_modules/gatsby/dist/utils/webpack.config.js:513:24)
    at tryCatch (/.../node_modules/regenerator-runtime/runtime.js:65:40)
    at Generator.invoke [as _invoke] (/.../node_modules/regenerator-runtime/runtime.js:303:22)
    at Generator.prototype.(anonymous function) [as next] (/.../node_modules/regenerator-runtime/runtime.js:117:21)
    at step (/.../node_modules/babel-runtime/helpers/asyncToGenerator.js:17:30)
    at /.../node_modules/babel-runtime/helpers/asyncToGenerator.js:28:13
    at <anonymous>

does anyone know what I might be doing wrong/have encountered a similar problem? could this have something to do with program.extensions now being managed by Redux in the 1.0 release?

Hello here,
I have the same issue as @jurvis, followed the instructions by @tonymilne and receive:

TypeError: gatsbyWebpack(...).resolve is not a function

Did somebody achieve it to work? Any repo that can be used as an example?
Thanks :)

Hello, if you want an example of working configuration with storybook, you can have a look on my starter (it’s in typescript but it must be quite same with pure javascript)

https://github.com/fabien0102/gatsby-starter

I have just stub all gatsby link ;)

Thanks @fabien0102, got it working πŸ™‚

In case somebody is interested in the code/steps, I added them below:

  1. Install storybook and pertinent addons
npm i @storybook/react @storybook/addon-options @storybook/addon-notes @storybook/addon-knobs @storybook/addon-actions storybook-readme -D
  1. Create npm or yarn tasks for executing and building storybook `package.json
"storybook": "start-storybook -p 9001 -c .storybook",
"storybook:build": "build-storybook -c .storybook -o public/docs"
  1. Add all addons to storybook .storybook/addons.js
import '@storybook/addon-options/register';
import '@storybook/addon-knobs/register';
import '@storybook/addon-actions/register';
import 'storybook-readme/register';
  1. Configure storybook .storybook/config.js
import { configure } from "@storybook/react";
import { setOptions } from "@storybook/addon-options";

setOptions({
    name: 'My website',
    downPanelInRight: true
});

// Stories loader
const req = require.context("../src", true, /.stories.[jt]sx?$/);
function loadStories() {
    req.keys().forEach(req);
}

// Initialize react-storybook
configure(loadStories, module);
  1. Configure Webpack on Storybook .storybook/webpack.config.js
const path = require("path");
const genDefaultConfig = require("@storybook/react/dist/server/config/defaults/webpack.config.js");

module.exports = (baseConfig, env) => {
    return genDefaultConfig(baseConfig, env);
};

6 .Code away πŸ’―

Here's an example configuration using Gatsby with Storybook and CSS Modules:

https://github.com/m-allanson/gatsby-storybook-css-modules

Storybook is configured to match Gatsby's default setup where filenames ending with .module.css will be processed as CSS Modules, but all other CSS files will be processed as plain CSS.

Given @m-allanson's starter β€” closing this out. Please open more issues if there's something we can do to improve how Gatsby works with Storybook!

Hi guys, I got storybook to work, when I run yarn run storybook, I get storybook on port 9001, however, whenever I create a file MyModule.stories.js, I get this error:

WARNING in ./src/components/Header/Menu/Menu.stories.jsx
Module build failed: SyntaxError: Unexpected token (8:4)

   6 | storiesOf('Button', module)
   7 |   .add('with text', () => (
>  8 |     <Menu />
     |     ^
   9 |   ));
  10 | 

 @ ./src .stories.[jt]sx?$
 @ ./.storybook/config.js

Here's the content of my config.js file in .storybook

import { configure } from "@storybook/react";
import { setOptions } from "@storybook/addon-options";

setOptions({
  name: 'My website',
  downPanelInRight: true
});

// Stories loader
const req = require.context("../src", true, /.stories.[jt]sx?$/);
function loadStories() {
  req.keys().forEach(req);
}

// Initialize react-storybook
configure(loadStories, module);

and the content of my file webpack.config.js

const path = require("path");
const genDefaultConfig = require("@storybook/react/dist/server/config/defaults/webpack.config.js");

module.exports = (baseConfig, env) => {
  const config = genDefaultConfig(baseConfig, env);


  // Add markdown loader
  config.module.rules.push({
    test: /\.md$/,
    include: path.resolve(__dirname, "../src"),
    loader: require.resolve("raw-loader")
  });
  config.resolve.extensions.push(".md");

  return config;
};

Do you have any idea why I'm getting this error?

Thank you

@alveshelio Do you have @storybook/react installed? It's look like that react syntax is not recognize

Note: I reformat your message with ```js :wink:

When I attempt to run @aperkaz 's steps, and I run npm run storybook I get the following output error: ERROR in TypeError: Cannot read property 'request' of undefined

> [email protected] storybook /Users/ericmasiello/Sites/priorityconstruction
> start-storybook -p 9001 -c .storybook

info @storybook/react v3.4.8
info
info => Loading custom addons config.
info => Loading custom webpack config (full-control mode).
 10% building modules 2/2 modules 0 active(node:47372) DeprecationWarning: importing default webpack config generator from '@storybook/react/dist/server/config/defaults/webpack.config.js' is deprecated. Use third argument of your exported function instead. See https://storybook.js.org/configurations/custom-webpack-config/#full-control-mode--default
webpack built 8559cdd1efbe3e50f59f in 4189ms
Hash: 8559cdd1efbe3e50f59f
Version: webpack 3.12.0
Time: 4189ms
                       Asset     Size  Chunks                    Chunk Names
    static/manager.bundle.js  3.84 MB       0  [emitted]  [big]  manager
    static/preview.bundle.js   1.6 MB       1  [emitted]  [big]  preview
static/manager.bundle.js.map   4.7 MB       0  [emitted]         manager
static/preview.bundle.js.map   1.9 MB       1  [emitted]         preview
                  index.html  2.18 kB          [emitted]
                 iframe.html  2.18 kB          [emitted]
 [225] ./node_modules/@storybook/react/dist/server/config/polyfills.js 113 bytes {0} {1} [built]
 [701] multi ./node_modules/@storybook/react/dist/server/config/polyfills.js ./.storybook/addons.js ./node_modules/@storybook/core/dist/client/manager/index.js 52 bytes {0} [built]
 [702] ./.storybook/addons.js 165 bytes {0} [built]
 [896] ./node_modules/@storybook/addon-actions/register.js 38 bytes {0} [built]
 [920] ./node_modules/storybook-readme/register.js 819 bytes {0} [built]
 [929] ./node_modules/@storybook/core/dist/client/manager/index.js 423 bytes {0} [built]
[1100] ./node_modules/@storybook/core/dist/client/manager/provider.js 3.35 kB {0} [built]
[1102] multi ./node_modules/@storybook/react/dist/server/config/polyfills.js ./node_modules/@storybook/react/dist/server/config/globals.js ./node_modules/webpack-hot-middleware/client.js?reload=true ./.storybook/config.js 64 bytes {1} [built]
[1103] ./node_modules/@storybook/react/dist/server/config/globals.js 105 bytes {1} [built]
[1104] ./node_modules/webpack-hot-middleware/client.js?reload=true 7.77 kB {1} [built]
[1110] ./node_modules/webpack-hot-middleware/client-overlay.js 2.21 kB {1} [built]
[1115] ./node_modules/webpack-hot-middleware/process-update.js 4.33 kB {1} [built]
[1116] ./.storybook/config.js 371 bytes {1} [built]
[1193] ./node_modules/@storybook/addon-options/preview.js 101 bytes {1} [built]
[1195] ./src .stories.[jt]sx?$ 160 bytes {1} [built]
    + 1181 hidden modules

ERROR in   TypeError: Cannot read property 'request' of undefined

  - ExternalModuleFactoryPlugin.js:37 handleExternals
    [priorityconstruction]/[webpack]/lib/ExternalModuleFactoryPlugin.js:37:34

  - ExternalModuleFactoryPlugin.js:46 next
    [priorityconstruction]/[webpack]/lib/ExternalModuleFactoryPlugin.js:46:8

  - ExternalModuleFactoryPlugin.js:59 handleExternals
    [priorityconstruction]/[webpack]/lib/ExternalModuleFactoryPlugin.js:59:7

  - ExternalModuleFactoryPlugin.js:79 ExternalModuleFactoryPlugin.<anonymous>
    [priorityconstruction]/[webpack]/lib/ExternalModuleFactoryPlugin.js:79:5

  - NormalModuleFactory.js:236 applyPluginsAsyncWaterfall
    [priorityconstruction]/[core]/[webpack]/lib/NormalModuleFactory.js:236:4

  - Tapable.js:260 NormalModuleFactory.applyPluginsAsyncWaterfall
    [priorityconstruction]/[core]/[tapable]/lib/Tapable.js:260:70

  - NormalModuleFactory.js:220 NormalModuleFactory.create
    [priorityconstruction]/[core]/[webpack]/lib/NormalModuleFactory.js:220:8

  - Compilation.js:407 semaphore.acquire
    [priorityconstruction]/[core]/[webpack]/lib/Compilation.js:407:18

  - Semaphore.js:16 Semaphore.acquire
    [priorityconstruction]/[core]/[webpack]/lib/util/Semaphore.js:16:4

  - Compilation.js:406 Compilation._addModuleChain
    [priorityconstruction]/[core]/[webpack]/lib/Compilation.js:406:18

  - Compilation.js:494 Compilation.addEntry
    [priorityconstruction]/[core]/[webpack]/lib/Compilation.js:494:8

  - SingleEntryPlugin.js:22 SingleEntryPlugin.<anonymous>
    [priorityconstruction]/[webpack]/lib/SingleEntryPlugin.js:22:15

  - Tapable.js:293 Compiler.applyPluginsParallel
    [priorityconstruction]/[core]/[tapable]/lib/Tapable.js:293:14

  - Compiler.js:499 applyPluginsAsync.err
    [priorityconstruction]/[core]/[webpack]/lib/Compiler.js:499:9

  - Tapable.js:195 Compiler.applyPluginsAsyncSeries
    [priorityconstruction]/[core]/[tapable]/lib/Tapable.js:195:46

  - Compiler.js:492 Compiler.compile
    [priorityconstruction]/[core]/[webpack]/lib/Compiler.js:492:8



ERROR in   TypeError: Cannot read property 'request' of undefined

  - ExternalModuleFactoryPlugin.js:37 handleExternals
    [priorityconstruction]/[webpack]/lib/ExternalModuleFactoryPlugin.js:37:34

  - ExternalModuleFactoryPlugin.js:46 next
    [priorityconstruction]/[webpack]/lib/ExternalModuleFactoryPlugin.js:46:8

  - ExternalModuleFactoryPlugin.js:59 handleExternals
    [priorityconstruction]/[webpack]/lib/ExternalModuleFactoryPlugin.js:59:7

  - ExternalModuleFactoryPlugin.js:79 ExternalModuleFactoryPlugin.<anonymous>
    [priorityconstruction]/[webpack]/lib/ExternalModuleFactoryPlugin.js:79:5

  - NormalModuleFactory.js:236 applyPluginsAsyncWaterfall
    [priorityconstruction]/[core]/[webpack]/lib/NormalModuleFactory.js:236:4

  - Tapable.js:260 NormalModuleFactory.applyPluginsAsyncWaterfall
    [priorityconstruction]/[core]/[tapable]/lib/Tapable.js:260:70

  - NormalModuleFactory.js:220 NormalModuleFactory.create
    [priorityconstruction]/[core]/[webpack]/lib/NormalModuleFactory.js:220:8

  - Compilation.js:407 semaphore.acquire
    [priorityconstruction]/[core]/[webpack]/lib/Compilation.js:407:18

  - Semaphore.js:16 Semaphore.acquire
    [priorityconstruction]/[core]/[webpack]/lib/util/Semaphore.js:16:4

  - Compilation.js:406 Compilation._addModuleChain
    [priorityconstruction]/[core]/[webpack]/lib/Compilation.js:406:18

  - Compilation.js:494 Compilation.addEntry
    [priorityconstruction]/[core]/[webpack]/lib/Compilation.js:494:8

  - SingleEntryPlugin.js:22 SingleEntryPlugin.<anonymous>
    [priorityconstruction]/[webpack]/lib/SingleEntryPlugin.js:22:15

  - Tapable.js:293 Compiler.applyPluginsParallel
    [priorityconstruction]/[core]/[tapable]/lib/Tapable.js:293:14

  - Compiler.js:499 applyPluginsAsync.err
    [priorityconstruction]/[core]/[webpack]/lib/Compiler.js:499:9

  - Tapable.js:195 Compiler.applyPluginsAsyncSeries
    [priorityconstruction]/[core]/[tapable]/lib/Tapable.js:195:46

  - Compiler.js:492 Compiler.compile
    [priorityconstruction]/[core]/[webpack]/lib/Compiler.js:492:8

Any ideas what I'm missing?

While I haven't nailed down exactly what was going wrong, the above error seemed to be related to the versino of either @storybook/addon-options or @storybook/react (or both). If you use these specific versions, the above config should work fine.

"@storybook/addon-options": "^3.2.12",
"@storybook/react": "^3.2.12",

I was also experiencing the ERROR in TypeError: Cannot read property 'request' of undefined issue.

Attempted using [email protected]; no luck

Attempted updating webpack.config.js as per https://github.com/craigcoles/gatsby-storybook/blob/master/.storybook/webpack.config.js; no luck

Decided to move my Storybook into a subfolder with its own package.json; if clashes in dep versions are an issue now, they'll likely be an issue later, so better to avoid them entirely.

"@storybook/addon-info": "3.4.8",
"@storybook/react": "3.4.8",

@larrybotha I have the same error, I think we need to wait until v2 is released to works with storybook properly 😒

@kikobeats has anyone from gatsby said this issue will be resolved in v2?

I'm running into a slightly different error with Gatsby v2 and a config based on the one aperkaz & m-allanson shared above. So far I've been able to limit it to components that import Gatsby.

It looks like it's not compling the jsx and I'm hopeful I can get something working with babel-loader. TBD

ERROR in ./node_modules/gatsby/cache-dir/gatsby-browser-entry.js
Module parse failed: Unexpected token (9:2)
You may need an appropriate loader to handle this file type.
|
| const StaticQuery = props => (
|   <StaticQueryContext.Consumer>
|     {staticQueryData => {
|       if (
 @ ./src/components/CTA/index.js 11:14-31
 @ ./stories/index.stories.js
 @ ./.storybook/config.js
 @ multi ./node_modules/@storybook/react/dist/server/config/polyfills.js ./node_modules/@storybook/react/dist/server/config/globals.js (webpack)-hot-middleware/client.js?reload=true ./.storybook/config.js
Child html-webpack-plugin for "index.html":
         Asset    Size  Chunks  Chunk Names
    index.html  569 kB       0
       [0] ./node_modules/html-webpack-plugin/lib/loader.js!./node_modules/@storybook/react/dist/server/index.html.ejs 1.7 kB {0} [built]
       [1] ./node_modules/lodash/lodash.js 540 kB {0} [built]
       [2] (webpack)/buildin/global.js 509 bytes {0} [built]
       [3] (webpack)/buildin/module.js 517 bytes {0} [built]
Child html-webpack-plugin for "iframe.html":
          Asset    Size  Chunks  Chunk Names
    iframe.html  569 kB       0
       [0] ./node_modules/html-webpack-plugin/lib/loader.js!./node_modules/@storybook/react/dist/server/iframe.html.ejs 1.16 kB {0} [built]
       [1] ./node_modules/lodash/lodash.js 540 kB {0} [built]
       [2] (webpack)/buildin/global.js 509 bytes {0} [built]
       [3] (webpack)/buildin/module.js 517 bytes {0} [built]

I'm also happy to make a new issue to track storybook with v2 if that's more appropriate

I got it working by adding babel-loader to custom webpack.config

```
config.module.rules.push(
{
test: /gatsby\/cache-dir.*.js$/,
loader: require.resolve('babel-loader'),
}
);

I followed @aperkaz instructions, but as soon as I installed @storybook/react the Gatsby app wouldn't build any more (got a generic Webpack error).

Installing [email protected] fixed the error and then could build both the app and storybook fine.
yarn add [email protected] --dev

The only other issue I had was with Gatsby's Link component, but this can be fixed by wrapping the story in a Router (see https://github.com/gatsbyjs/gatsby/issues/2932#issuecomment-377009281).

I also received the StaticQuery error which stemmed from using push imported from gatsby. Updating to import from gatsby-link corrected the error.

For anyone else using @tonymilne 's fantastic code above, and encountering the following error message:

TypeError: gatsbyWebpack(...).resolve is not a function

I fixed the issue by noticing that Tony had used the name wepack.config.js - not webpack.config.js

In case anyone is still struggling with this problem, folks at Gatsby seem to have provided a solid solution in their documentation here: https://www.gatsbyjs.org/docs/visual-testing-with-storybook/

I just used the solution presented above, and it worked perfectly. πŸ’―

Sorry if this is the wrong spot.

I'm still getting an error when using import { Link } from 'gatsby' and Storybook, I'm using [email protected] with [email protected] and Typescript.

ERROR in ./node_modules/gatsby/cache-dir/gatsby-browser-entry.js 16:2
Module parse failed: Unexpected token (16:2)
You may need an appropriate loader to handle this file type.
| 
| const StaticQuery = props => (
>   <StaticQueryContext.Consumer>
|     {staticQueryData => {
|       if (

.stroybook/webpack.config.js

module.exports = (baseConfig, env, defaultConfig) => {
  // Transpile Gatsby module because Gatsby includes un-transpiled ES6 code.
  defaultConfig.module.rules[0].exclude = [/node_modules\/(?!(gatsby)\/)/];

  // use installed babel-loader which is v8.0-beta (which is meant to work with @babel/core@7)
  defaultConfig.module.rules[0].use[0].loader = require.resolve('babel-loader');

  // use @babel/preset-react for JSX and env (instead of staged presets)
  defaultConfig.module.rules[0].use[0].options.presets = [require.resolve('@babel/preset-react'), require.resolve('@babel/preset-env')];

  // use @babel/plugin-proposal-class-properties for class arrow functions
  defaultConfig.module.rules[0].use[0].options.plugins = [require.resolve('@babel/plugin-proposal-class-properties')];

  // Prefer Gatsby ES6 entrypoint (module) over commonjs (main) entrypoint
  defaultConfig.resolve.mainFields = ['browser', 'module', 'main'];

  defaultConfig.module.rules.push({
    test: /gatsby\/cache-dir.*\.js$/,
    loader: require.resolve('babel-loader'),
  });

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

  defaultConfig.module.rules.push({
    test: /\.(ts|tsx)$/,
    loader: require.resolve('awesome-typescript-loader'),
    exclude: [/node_modules\/(?!(gatsby)\/)/],
  });

  return defaultConfig;
};

I get a transpiling error when I downgrade to babel@7 (as above)

ERROR in ./node_modules/gatsby/cache-dir/gatsby-browser-entry.js
Module build failed (from ./node_modules/babel-loader/lib/index.js):
TypeError: Cannot read property 'code' of null
    at transpile

Is anyone else experiencing this issue?

@zacharymctague I got around that by using a conditional that requires (or not) Gatsby's Link depending on whether you're in the storybook environment.

Something like:

const Link = process.env.STORYBOOK_ENV
  ? ({ children }) => children
  : require('gatsby').Link

You can set the environment in your package.json script, e.g.
"storybook": "STORYBOOK_ENV=true start-storybook -p 9001 -c .storybook -s ./public"

@zacharymctague I don't remember where I got it from but that's how I did it:

// Gatsby's Link overrides: Gatsby defines a global called ___loader to prevent
// its method calls from creating console errors you override it here
global.___loader = {
  enqueue: () => {},
  hovering: () => {},
};

// Gatsby internal mocking to prevent unnecessary errors in storybook testing
// environment
global.__PATH_PREFIX__ = "";

// This is to utilized to override the window.___navigate method Gatsby defines
// and uses to report what path a Link would be taking us to if it wasn't inside
// a storybook
window.___navigate = pathname => {
  action("NavigateTo:")(pathname);
};

@msachi's approach looks nice though.

I followed the configuration advice in the documentation but am still seeing the issue that @zacharymctague reported; even with telling babel-loader that it needs to transpile things within the Gatsby package, it doesn't actually seem to work and the JSX in there is choked on.

@alexlafroscia
This workaround worked for me:

  config.module.rules.unshift({
    test: /\.js$/,
    use: [{
      loader: require.resolve('babel-loader'),
      options: {
        presets: ["react-app"],
      }
    }],
    include: [
      path.join(path.dirname(__dirname), 'node_modules/gatsby/cache-dir')
    ]
  });
Was this page helpful?
0 / 5 - 0 ratings

Related issues

hobochild picture hobochild  Β·  3Comments

totsteps picture totsteps  Β·  3Comments

KyleAMathews picture KyleAMathews  Β·  3Comments

rossPatton picture rossPatton  Β·  3Comments

timbrandin picture timbrandin  Β·  3Comments