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

Importing Link from gatsby breaks Storybook #10668

Closed
sidharthachatterjee opened this issue Dec 26, 2018 · 36 comments
Closed

Importing Link from gatsby breaks Storybook #10668

sidharthachatterjee opened this issue Dec 26, 2018 · 36 comments
Labels
type: bug An issue or pull request relating to a bug in Gatsby

Comments

@sidharthachatterjee
Copy link
Contributor

Storybook breaks (#10662) if a component includes import { Link } from 'gatsby'

This was working fine before #9123 because

  • main was an es6 build
  • webpack would treeshake when Link was imported

Now that main is a commonjs build and the ES6 build is at module, it breaks since

  • the commonjs entry point at gatsby-browser-entry.js requires public-page-renderer
  • which tries to require pages.json
  • which doesn't exist because since presumably a gatsby build hasn't been run yet

public-page-renderer.js looks like

if (process.env.BUILD_STAGE === `develop`) {
  module.exports = preferDefault(require(`./public-page-renderer-dev`))
} else if (process.env.BUILD_STAGE === `build-javascript`) {
  module.exports = preferDefault(require(`./public-page-renderer-prod`))
} else {
  module.exports = () => null
}

I assumed that this would work since BUILD_STAGE is not set but it seems webpack wants to resolve both calls to require

@sidharthachatterjee
Copy link
Contributor Author

sidharthachatterjee commented Dec 26, 2018

For now I've added a quick fix to the documentation in #10669

DSchau pushed a commit that referenced this issue Dec 27, 2018
…k config (#10669)

The steps in the current documentation for using Storybook with Gatsby (https://www.gatsbyjs.org/docs/visual-testing-with-storybook/) don't work because importing Link from gatsby in any component breaks. 

This is because several internals get required as a result of requiring anything from the default commonjs build (which would have been tree shaken before #9123) and eventually require a non-existent `pages.json`. 

More details are at #10668

This pull request updates the documentation with a quick fix (setting resolve.mainFields in the storybook webpack config override thereby _preferring_ es6 gatsby over commonjs) 

Fixes #10662
@stephanschubert
Copy link

I applied the fix but now I get this error:

WARNING in ./node_modules/gatsby/cache-dir/page-renderer.js 41:24-33
"export 'apiRunner' was not found in './api-runner-browser'
 @ ./node_modules/gatsby/cache-dir/public-page-renderer-prod.js
 @ ./node_modules/gatsby/cache-dir/public-page-renderer.js
 @ ./node_modules/gatsby/cache-dir/gatsby-browser-entry.js

@DSchau
Copy link
Contributor

DSchau commented Jan 2, 2019

@stephanschubert could you provide a reproduction? Sorry you're experiencing that!

@stephanschubert
Copy link

@DSchau A full reproduction is hard (custom flavored monorepo setup here) but I could narrow the issue down:

  config.module.rules[0].use[0].options.presets = [
    require.resolve("@babel/preset-react"),
    [
      require.resolve("@babel/preset-env"),
      {
        shippedProposals: true,
        useBuiltIns: "entry", // <-- was "usage"
      },
    ],
  ];

Switching from usage to entry resolves it but I don't quite understand why. Do you have more insight here?

gpetrioli pushed a commit to gpetrioli/gatsby that referenced this issue Jan 22, 2019
…k config (gatsbyjs#10669)

The steps in the current documentation for using Storybook with Gatsby (https://www.gatsbyjs.org/docs/visual-testing-with-storybook/) don't work because importing Link from gatsby in any component breaks. 

This is because several internals get required as a result of requiring anything from the default commonjs build (which would have been tree shaken before gatsbyjs#9123) and eventually require a non-existent `pages.json`. 

More details are at gatsbyjs#10668

This pull request updates the documentation with a quick fix (setting resolve.mainFields in the storybook webpack config override thereby _preferring_ es6 gatsby over commonjs) 

Fixes gatsbyjs#10662
@gatsbot gatsbot bot added the stale? Issue that may be closed soon due to the original author not responding any more. label Feb 10, 2019
@gatsbot
Copy link

gatsbot bot commented Feb 10, 2019

Hiya!

This issue has gone quiet. Spooky quiet. 👻

We get a lot of issues, so we currently close issues after 30 days of inactivity. It’s been at least 20 days since the last update here.

If we missed this issue or if you want to keep it open, please reply here. You can also add the label "not stale" to keep this issue open!

Thanks for being a part of the Gatsby community! 💪💜

@gatsbot
Copy link

gatsbot bot commented Feb 21, 2019

Hey again!

It’s been 30 days since anything happened on this issue, so our friendly neighborhood robot (that’s me!) is going to close it.

Please keep in mind that I’m only a robot, so if I’ve closed this issue in error, I’m HUMAN_EMOTION_SORRY. Please feel free to reopen this issue or create a new one if you need anything else.

Thanks again for being part of the Gatsby community!

@gatsbot gatsbot bot closed this as completed Feb 21, 2019
@sidharthachatterjee sidharthachatterjee added not stale and removed stale? Issue that may be closed soon due to the original author not responding any more. labels Feb 21, 2019
@pho3nixf1re
Copy link

pho3nixf1re commented May 25, 2019

I am seeing this issue and changing to 'entry' fixed it for me as well. This should probably be re-opened.

@Jimmydalecleveland
Copy link

Jimmydalecleveland commented Jun 9, 2019

I'm still getting an error on gatsby: 2.8.4 and @storybook/react: 5.1.1 when trying to import any component using Link:

ERROR in my-gatsby/node_modules/gatsby/cache-dir/gatsby-browser-entry.js 17:2
Module parse failed: Unexpected token (17:2)
You may need an appropriate loader to handle this file type.
| 
| const StaticQuery = props => (
>   <StaticQueryContext.Consumer>
|     {staticQueryData => {
|       if (
 @ ./src/baseComponents/Link/Link.stories.jsx 4:0-30
 @ . sync \.stories\.(js|jsx)$
 @ ./.storybook/config.js
 @ multi my-gatsby/node_modules/@storybook/core/dist/server/common/polyfills.js /my-gatsby/node_modules/@storybook/core/dist/server/preview/globals.js ./.storybook/config.js (webpack)-hot-middleware/client.js?reload=true

I've done all the steps in this tutorial: https://www.gatsbyjs.org/docs/visual-testing-with-storybook/
And changing entry as mentioned above did not do anything in my case.

Update: I spun up a gatsby starter with the same versions as my project and importing Link works fine after applying the changes from the "visual-testing-with-storybook" walkthrough.

My project that it isn't working on is a monorepo, using gatsby-themes so there may be something about its setup that is causing this issue but I still haven't located it.

@Jimmydalecleveland
Copy link

For anyone having the same issue as me, I found a solution and was given an alternate solution over in the storybook github issues here: storybookjs/storybook#5949 (comment)

@levino
Copy link

levino commented Jul 17, 2019

Reopen.

@terrierscript
Copy link

Same issue here.

In my environment, I can workaround to use gatsby-link

// import { Link } from "gatsby" // error 
import Link from "gatsby-link" // not error 

@chang-ryan
Copy link
Contributor

@terrierscript's solution works nicely. but this is still an issue

@raulfdm
Copy link

raulfdm commented Nov 10, 2019

Same issue here.

In my environment, I can workaround to use gatsby-link

// import { Link } from "gatsby" // error 
import Link from "gatsby-link" // not error 

This workaround also solves my problem.

@emileber
Copy link

emileber commented Jan 9, 2020

I'm not sure why this is closed since it is still relevant. I just started a new Gatsby projet with a storybook and I got a lot of trouble finding a solution to this issue. Which in the end is just a patch in the meantime.

The following line (source) is causing issues with core-js versions differing in Gatsby and Storybook.

// Transpile Gatsby module because Gatsby includes un-transpiled ES6 code.
config.module.rules[0].exclude = [/node_modules\/(?!(gatsby)\/)/]

Not importing gatsby is what worked for me right now.

@Abrh1m
Copy link

Abrh1m commented Jan 20, 2020

Using link from @reach/router solved my problem, like this

import { Link } from "@reach/router";

@AaronFeledy
Copy link

For me the issue was related to using Yarn Workspaces to develop my Gatsby theme and nesting it within the Gatsby package. The Webpack config runs in the root of the current package, in this case my Gatsby theme directory/ Yarn Workspace. My node_modules/gatsby files that need transpiling are actually in a parent directory. The code in the guide doesn't consider this scenario, so I needed to update the config to point to the correct directory. Adding the following to my Storybook webpack config did the trick:

// Since we're using Yarn Workspaces and nesting the packages, we need to include the parent package
config.module.rules[0].include = require('path').resolve('../..');

@turistua
Copy link

@AaronFeledy could you share your folders structure, and note where you have storybook and in which node_modules you have gatsby?

@salatielsql
Copy link

Same issue here.
In my environment, I can workaround to use gatsby-link

// import { Link } from "gatsby" // error 
import Link from "gatsby-link" // not error 

This workaround also solves my problem.

Tried this solution but got:

__PATH_PREFIX__ is not defined
ReferenceError: __PATH_PREFIX__ is not defined
    at withPrefix (http://localhost:62911/vendors~main.3925691bc29e63af178f.bundle.js:74828:80)
    at GatsbyLink.render (http://localhost:62911/vendors~main.3925691bc29e63af178f.bundle.js:74970:22)
    at finishClassComponent (http://localhost:62911/vendors~main.3925691bc29e63af178f.bundle.js:162866:31)
    at updateClassComponent (http://localhost:62911/vendors~main.3925691bc29e63af178f.bundle.js:162816:24)
    at beginWork (http://localhost:62911/vendors~main.3925691bc29e63af178f.bundle.js:164335:16)
    at HTMLUnknownElement.callCallback (http://localhost:62911/vendors~main.3925691bc29e63af178f.bundle.js:145870:14)
    at Object.invokeGuardedCallbackDev (http://localhost:62911/vendors~main.3925691bc29e63af178f.bundle.js:145919:16)
    at invokeGuardedCallback (http://localhost:62911/vendors~main.3925691bc29e63af178f.bundle.js:145974:31)
    at beginWork$1 (http://localhost:62911/vendors~main.3925691bc29e63af178f.bundle.js:168916:7)
    at performUnitOfWork (http://localhost:62911/vendors~main.3925691bc29e63af178f.bundle.js:167867:12)

@AaronFeledy
Copy link

AaronFeledy commented Mar 5, 2020

@turistua

project/
+-- gastby-theme-mytheme/
|   +-- .storybook/
|   |   +-- main.js
|   +-- gatsby-config.js
+-- node_modules/
|   +-- gatsby/

@pdeka
Copy link

pdeka commented Mar 17, 2020

Why is this issue closed? Its is an issue related to creating a common lib, adding gatsby to it and importing 'Link' (or anything else). Its quite simple to reproduce as well. Am I missing something? It is not a Story book related issue. Its for all shared libs where gatsby is used.

It effectively stops us from using gatsby in a common lib. We have 3 templates and common/shared libs across the templates. https://share.getcloudapp.com/p9uKLEkK

Importing 'gatsby-link' also does not work for the reasons mentioned above by @salatielq .

Env
Lerna: 3.20.2
gatsby-cli: 2.10.10
gatsby: 2.19.41
Node: 12.16.1 - ~/.nvm/versions/node/v12.16.1/bin/node
Yarn: 1.22.4 - ~/.yarn/bin/yarn
npm: 6.14.2 - ~/.nvm/versions/node/v12.16.1/bin/npm

Webpack:

  module: {
    rules: [
      {
        test: /\.js$/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              presets: ['@babel/preset-env', '@babel/react'],
              plugins: ["transform-class-properties"]
            }
          }
        ],
        include: [
          path.resolve(__dirname, "src")
        ],
        exclude: /node_modules/
      },
      {
        test: /\.(png|jpe?g|gif)$/i,
        use: [
          {
            loader: 'file-loader',
          },
        ],
        include: path.resolve(__dirname, "src"),
        exclude: /node_modules/
      }
    ]
  },

@turistua
Copy link

turistua commented Mar 18, 2020

As far as I understand the issue, webpack config for storybook should be aware of gatsby package.

I've fixed the issue by adding additional line of code to storybook webpack config:
config.module.rules[0].include = path.resolve(__dirname, '../../..');

which allows webpack to find gatsby package. The path can be different for your case, I have a monorepo, storybook is a part of one package and gatsby is placed in the root node-modules folder.

The reason why changing import from gatsby to gatsby-link works is proably because gatsby-link is installed in the folder which was already included in webpack config.

Hope this helps.

@levino
Copy link

levino commented Mar 18, 2020

I guess using yarn and "nohoist" for gatsby could also do the trick.

@pdeka
Copy link

pdeka commented Mar 24, 2020

@levino I tried nohoist and I have gatsby in the child's (common component's) node_modules.

stencils/common-components/kenekt-helper/node_modules/gatsby on  master [⇡!] is 📦 v2.19.49 via ⬢ v12.16.1
➜

I still get the following when I import gatsby..


kenekt-helper: ERROR in ../node_modules/gatsby/cache-dir/gatsby-browser-entry.js 25:4
kenekt-helper: Module parse failed: Unexpected token (25:4)
kenekt-helper: You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
kenekt-helper: |
kenekt-helper: |   return (
kenekt-helper: >     <React.Fragment>
kenekt-helper: |       {finalData && render(finalData)}
kenekt-helper: |       {!finalData && <div>Loading (StaticQuery)</div>}

@bostrom
Copy link

bostrom commented May 13, 2020

Gatsby has some useful information on how to tweak the Storybook config to make it work https://www.gatsbyjs.org/docs/visual-testing-with-storybook/.

However, since Storybook's config files have changed in version 5.3, and Gatsby's documentation isn't up to date yet, the stuff they say should go into ./storybook/config.js should actually go into ./storybook/preview.js. And the things they say should go into .storybook/webpack.config.js should actually go into the webpackFinal option of .storybook/main.js.

But otherwise it was mostly copy and paste.

@emileber
Copy link

@bostrom The problem exposed in this issue is not about the outdated Storybook config documentation, but about a dependency version mismatch between Storybook and Gatsby, making it impossible to import anything from the gatbsy module (e.g. import { Link } from 'gatsby';) in a component that's used in a story.

If you're not importing gatsby in a component used in a story, then it works without an itch. Or if you're using compatible older version of either or both storybook and gatsby, it might work as well.

It looks realated to #15601

@bostrom
Copy link

bostrom commented May 14, 2020

Ok, maybe I misunderstood the original issue, but I faced the same error as @pdeka when importing components from gatsby and thought I'd share a workaround provided by the Gatsby documentation, which clearly states

However, since this is for a Gatsby project, you need to update the default Storybook configuration a bit so you don’t get errors when trying to use Gatsby specific components inside of the stories.

But maybe this is about that very issue, i.e. that we have to do a workaround for it, and it doesn't work out of the box.

But nevertheless, that piece of documentation helped me get Storybook running while still being able to import { Link } from 'gatsby';.

@emileber
Copy link

@bostrom maybe it's fixed now? I didn't had the chance to try it since January.

@tevla
Copy link

tevla commented May 28, 2020

Having the exact same issue and neither solutions worked.
If I use

import navigate from "gatsby-link";

it works on Storybook but fail build on Gatsby, but if I have

import { navigate } from "gatsby";

it will work on Gatsby but not Storybook.

I ended up doing something a tad dirty

    try {
      navigate = require("gatsby").navigate;
    } catch (e) {
      navigate = require("gatsby-link").navigate;
    }

Hoping for a fix soon because I really don't like that hack

@colbyfayock
Copy link
Contributor

I was having the issue where I was receiving the __BASE_PATH__ error when using the Link component from gatsby inside another component inside that component's story

Though the docs doesn't specifically mention __BASE_PATH__, I was able to resolve this by adding:

// .storybook/preview.js
global.__BASE_PATH__ = '';

Similar to how in the docs they mention to add:

// .storybook/preview.js
global.__PATH_PREFIX__ = '';

https://www.gatsbyjs.org/docs/visual-testing-with-storybook/#storybook-version-5

Hope that helps someone else :)

lowsky added a commit to jscraftcamp/website that referenced this issue Jun 13, 2020
* move old components ini DEPRECATED_components folder

* update packages

* set storybook in production mode so the graphql queries work

* move images into assets

* change images to assets routes

* fix storybook error when using Gatsby components (e.g. Link)

gatsbyjs/gatsby#10668 (comment)

* update gatsby config

* disable including fontawesome to fix gatsby svg importer

* configure storybook

* move logo into images folder and add svg version

* adapt logo path

* storybook fails on missing folder

* temporary fix storybook: logo and footer

Co-authored-by: Michael Zoidl <github@michaelzoidl.com>
Co-authored-by: lowsky <lowsky@users.noreply.github.com>
@DanailMinchev
Copy link
Contributor

I have similar issue, because I am using Yarn Workspaces / monorepo setup.

The solution suggested by @AaronFeledy in #10668 (comment) is working for me.

I've created a small fix which checks if the Gatsby is not in your project's node_module and calculates the correct path then to be used in config.module.rules[0].include, this way it will work for standard projects and yarn workspace ones not depending on the structure.

The code you can add in main.js:

    await new Promise((resolve, reject) => {
      const gatsbyBinPath = require("path").resolve(
        "./node_modules/.bin/gatsby"
      )
      require("fs").lstat(gatsbyBinPath, (err, stats) => {
        if (stats.isSymbolicLink()) {
          if (err) {
            reject(err)
          } else {
            const gatsbyResolvedLink = require("fs").readlinkSync(gatsbyBinPath)
            if (gatsbyResolvedLink !== "../gatsby/cli.js") {
              config.module.rules[0].include = require("path").resolve(
                gatsbyResolvedLink.replace("/../node_modules/gatsby/cli.js", "")
              )
            }
          }
        }
        resolve()
      })
    })

If people think it is useful I can create a PR for it to update the docs.

Thanks

@SilencerWeb
Copy link
Contributor

It would be awesome to have a fix for __BASE_PATH__ in the documentation, would save some time for me and I'm sure it will save some time for other developers 🙂

@lucis
Copy link

lucis commented Oct 12, 2020

Having this same issue with Storybook v6 and the recommended settings from Gatsby's tutorial.

Unfortunately, I was only able to make it work switching to gatsby-link, what I find not that great :(

@tevla I think it should be import { navigate } from "gatsby-link". It works fine here both for Storybook and Gatsby.

@romellem
Copy link

romellem commented Feb 16, 2021

I think these lines in Visual Testing with Storybook - Storybook version 5 are problematic because it makes an assumption about the order of the Webpack rules.

Namely, it doesn't take into consideration if you have other add-ons that also change the rules. In my case, this is happening because I use @storybook/preset-create-react-app@2.1.2, which modifies these rules before the webpackFinal callback runs.

If I had a vanilla Storybook webpack configuration, using the latest v5 (v5.3.21), the config should output the following module.rules:

module: {
  rules: [
    {
      test: /\.(mjs|jsx?)$/,
      use: [
        {
          loader: 'babel-loader',
          options: babelOptions,
        },
      ],
      include: [path.resolve('./')],
      exclude: [path.resolve('./node_modules')],
    },
    {
      test: /\.md$/,
      use: [
        {
          loader: require.resolve('raw-loader'),
        },
      ],
    },
  ],
}

However, after @storybook/preset-create-react-app executes, my module.rules webpack config looks like this (several items below have been pruned / edited so it fits better in this comment):

module: {
  rules: [
    {
      test: /\.md$/,
      use: ['raw-loader'],
    },
    { parser: { requireEnsure: false } },
    {
      test: /\.(js|mjs|jsx|ts|tsx)$/,
      enforce: 'pre',
      use: ['eslint-loader'],
      include: ['~/src', '~/.storybook'],
    },
    {
      oneOf: [
        {
          test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
          loader: 'url-loader',
        },
        {
          test: /\.(js|mjs|jsx|ts|tsx)$/,
          include: ['~/src', '~/.storybook'],
          loader: 'babel-loader',
          options: { /* ... */ }
        },
        {
          test: /\.(js|mjs)$/,
          exclude: /@babel(?:\/|\\{1,2})runtime/,
          loader: 'babel-loader',
          options: { /* ... */ },
          include: ['~/.storybook'],
        },
        { test: /\.css$/, /* ... */ },
        { test: /\.module\.css$/, /* ... */ },
        { test: /\.(scss|sass)$/, /* ... */ },
        { test: /\.module\.(scss|sass)$/, /* ... */ },
        {
          exclude: [
            /\.(js|mjs|jsx|ts|tsx)$/,
            /\.html$/,
            /\.json$/,
            /\.(ejs|md|mdx)$/,
          ],
          loader: 'file-loader',
          options: { /* ... */ },
        },
      ],
    },
    {
      test: /\.js$/,
      include: /node_modules\/acorn-jsx/,
      use: ['babel-loader'],
    },
    { test: /\.(stories|story).mdx$/, /* ... */ },
    {
      test: /\.mdx$/,
      exclude: /\.(stories|story).mdx$/,
      // ...
    },
    {
      test: /\.(stories|story)\.[tj]sx?$/,
      loader: '@storybook/source-loader',
      // ...
    },
  ],
}

I got this configuration by running yarn storybook --debug-webpack per the docs.

Importantly, @storybook/preset-create-react-app moves all "non JS" rules to the front when it finally returns a webpack config. Since we only have two rules before (the /\.(mjs|jsx?)$/ and the /\.md$/ one), this effectively moves the /\.md$/ rule to the front of our array.

So, when making modifications to the rules first item via:

// Transpile Gatsby module because Gatsby includes un-transpiled ES6 code.
config.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)
config.module.rules[0].use[0].loader = require.resolve("babel-loader")
// use @babel/preset-react for JSX and env (instead of staged presets)
config.module.rules[0].use[0].options.presets = [
    require.resolve("@babel/preset-react"),
    require.resolve("@babel/preset-env"),
]
config.module.rules[0].use[0].options.plugins = [
    // use @babel/plugin-proposal-class-properties for class arrow functions
    require.resolve("@babel/plugin-proposal-class-properties"),
    // use babel-plugin-remove-graphql-queries to remove static queries from components when rendering in storybook
    require.resolve("babel-plugin-remove-graphql-queries"),
]

config.module.rules[0] is not the rule concerning how JS-related files are loaded, and instead we are making changes to how Markdown files are loaded!


I'm not 100% sure how to change the webpackFinal(config) callback to address this, but either way, if you use @storybook/preset-create-react-app, the instructions given will not work as they are intended!

@daviddelusenet
Copy link

I created a new issue since this is still happening in the latest versions of Gatsby/Storybook: #29702

@OmarKhattab
Copy link

Gatsby has some useful information on how to tweak the Storybook config to make it work https://www.gatsbyjs.org/docs/visual-testing-with-storybook/.

However, since Storybook's config files have changed in version 5.3, and Gatsby's documentation isn't up to date yet, the stuff they say should go into ./storybook/config.js should actually go into ./storybook/preview.js. And the things they say should go into .storybook/webpack.config.js should actually go into the webpackFinal option of .storybook/main.js.

But otherwise it was mostly copy and paste.

thanks for this

@leads
Copy link

leads commented Sep 13, 2022

Same issue and it was fixed using instructions here

However it does seem to have take my build time running build-storybook to increase by a minute. Anyone else seen an increase in build time?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug An issue or pull request relating to a bug in Gatsby
Projects
None yet
Development

No branches or pull requests