Gatsby: Importing Link from gatsby breaks Storybook

Created on 26 Dec 2018  Â·  32Comments  Â·  Source: gatsbyjs/gatsby

Storybook breaks (https://github.com/gatsbyjs/gatsby/issues/10662) if a component includes import { Link } from 'gatsby'

This was working fine before https://github.com/gatsbyjs/gatsby/pull/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

bug

Most helpful comment

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 :)

All 32 comments

For now I've added a quick fix to the documentation in https://github.com/gatsbyjs/gatsby/pull/10669

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

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

@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?

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! 💪💜

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!

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

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.

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: https://github.com/storybookjs/storybook/issues/5949#issuecomment-500869039

Reopen.

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 

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

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.

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.

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

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

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('../..');

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

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)

@turistua

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

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/
      }
    ]
  },

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.

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

@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>}

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.

@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 https://github.com/gatsbyjs/gatsby/issues/15601

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';.

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

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

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 :)

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

The solution suggested by @AaronFeledy in https://github.com/gatsbyjs/gatsby/issues/10668#issuecomment-580951826 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

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 🙂

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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ghost picture ghost  Â·  3Comments

benstr picture benstr  Â·  3Comments

timbrandin picture timbrandin  Â·  3Comments

kalinchernev picture kalinchernev  Â·  3Comments

jimfilippou picture jimfilippou  Â·  3Comments