gatsbyjs / gatsby

The best React-based framework with performance, scalability and security built in.
https://www.gatsbyjs.com
MIT License
55.24k stars 10.32k forks source link

Cannot read property 'Provider' of undefined. BaseContext from `@reach/router` is undefined. #26785

Closed shrirambalaji closed 3 years ago

shrirambalaji commented 4 years ago

Description

image

BaseContext is undefined here.

Also, it looks like @reach/router doesn't export BaseContext 🤔. Ideally gatsby shouldnt' be relying on this import, if its not actually exported from @reach/router.

NOTE: This issue goes away, if I fix the BaseContext by copying over the snippet to re-create it from here and then patching the production-app.js file inside cache-dir.

  const RouteHandler = props => (
    <BaseContext.Provider
      value={{
        baseuri: `/`,
        basepath: `/`,
      }}
    >
      <PageRenderer {...props} />
    </BaseContext.Provider>
  )

Steps to reproduce

Issue arises especially when I use docker to create a docker image of the source code, and then build the gatsby image, copying the public directory and then use tools like serve to host the static files. This is NOT reproducible on gatsby build or gatsby develop, which makes it even more difficult to debug, on why this issue is happening. I'm unfortunately not able to provide more information due to lack thereof.

Expected Behaviour

Gatsby should handle the BaseContext being undefined error, more gracefully.

Environment

System: OS: macOS 10.15.5 CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz Shell: 5.7.1 - /bin/zsh Binaries: Node: 12.18.3 - ~/n/bin/node Yarn: 1.22.4 - ~/.yarn/bin/yarn npm: 6.14.7 - /usr/local/bin/npm Languages: Python: 2.7.16 - /usr/bin/python Browsers: Edge: 85.0.564.44 Safari: 13.1.1 npmPackages: gatsby: ^2.24.53 => 2.24.54 gatsby-link: ^2.4.13 => 2.4.13 gatsby-plugin-catch-links: ^2.3.5 => 2.3.11 gatsby-plugin-emotion: ^4.3.2 => 4.3.10 gatsby-plugin-gtag: ^1.0.12 => 1.0.13 gatsby-plugin-layout: ^1.3.10 => 1.3.10 gatsby-plugin-manifest: ^2.2.33 => 2.4.28 gatsby-plugin-mdx: ^1.0.61 => 1.2.38 gatsby-plugin-nprogress: ^2.3.2 => 2.3.10 gatsby-plugin-offline: ^3.2.11 => 3.2.27 gatsby-plugin-react-helmet: ^3.1.18 => 3.3.10 gatsby-plugin-remove-serviceworker: ^1.0.0 => 1.0.0 gatsby-plugin-remove-trailing-slashes: ^2.3.5 => 2.3.11 gatsby-plugin-sitemap: ^2.2.24 => 2.4.12 gatsby-remark-autolink-headers: ^2.3.5 => 2.3.12 gatsby-remark-copy-linked-files: ^2.1.33 => 2.3.14 gatsby-source-filesystem: ^2.3.27 => 2.3.28 gatsby-transformer-remark: ^2.8.32 => 2.8.33

pieh commented 4 years ago

Hi @Shriram-Balaji

The non-existing export/import is due to this hack - https://github.com/gatsbyjs/gatsby/pull/15457 . It was needed to preserve behaviour that we had before some accessibility fixes (tbh behaviour is weird and we should change it in next major version, but we didn't release new major since that so it stays as-is for now).

It looks like something weird is happening in docker if only happens there, but not outside of it. Do you use any webpack config modifications?

shrirambalaji commented 4 years ago

Hey @pieh

Yeah, I'm having a couple of modifications, most of them targeted at libraries that don't play well with SSR, and supporting path aliases in typescript. Now that I know the hack fix was on webpack.config.js kinda makes me think if any of these config modifications are the cause of the issue 🤔.

exports.onCreateWebpackConfig = ({ actions, loaders, stage }) => {
  if (stage === 'build-html') {
    actions.setWebpackConfig({
      module: {
        rules: [
          {
            test: /swagger-ui/,
            use: loaders.null(),
          },
        ],
      },
    });
  }

  if (stage === 'develop-html') {
    actions.setWebpackConfig({
      module: {
        rules: [
          {
            test: /formdata-node/,
            use: loaders.null(),
          },
        ],
      },
    });
  }

  if (stage === `build-javascript`) {
    actions.setWebpackConfig({
      optimization: {
        runtimeChunk: {
          name: `webpack-runtime`,
        },
        splitChunks: {
          name: false,
          cacheGroups: {
            styles: {
              name: `styles`,
              test: /\.(css|scss)$/,
              chunks: `initial`,
              enforce: true,
            },
          },
        },
      },
    });
  }

  actions.setWebpackConfig({
    resolve: {
      plugins: [new TSConfigPathPlugin()],
    },
  });

  actions.setWebpackConfig({
    resolve: {
      modules: [path.resolve(__dirname, 'src'), 'node_modules'],
      alias: {
        $components: path.resolve(__dirname, 'src/components'),
        buble: '@philpl/buble', // to reduce bundle size
      },
    },
  });
};
pieh commented 4 years ago

First step I would do is to build with gatsby build --no-uglify and inspect produced bundles (minification makes it unreadable, so flag just disables it). Then try to find what gets bundled for @reach/router and see if that transform that supposed to add BaseContext export actually work or not.

One thing that I would also love to see results is using something vanilla like gatsby-starter-default built in your docker setup to see if that would have similar problem - this starter doesn't make any webpack modifications, so if it happens in that we could eliminate some variables

vladar commented 3 years ago

@Shriram-Balaji did you have a chance to follow the suggestion above on how to investigate this? This issue got stuck and there seems to be nothing actionable in its current state.

ascorbic commented 3 years ago

Hi. I'm going to close this now, as we can't do much to help without more information. If you are able to create a minimal reproduction for this then please do reopen the issue. Thanks!

dougsmith1000 commented 3 years ago

@ascorbic, @vladar, and @pieh , I had the same issue and ran gatsby build --no-uglify. This was my warning:

warn ./.cache/production-app.js
Attempted import error: 'BaseContext' is not exported from
'@gatsbyjs/reach-router' (imported as 'BaseContext').

I went into @gatsby/reach-router/index.js and added exports.BaseContext = BaseContext; to the final line of the file and it seems to build well now. Not sure why this only is happening for @shrirambalaji and myself though. I also have some custom webpack configs

FlxAlbroscheit commented 2 years ago

Got the very same issue in two completely different projects. One thing in common is that both follow a monorepo structure, are managed via yarn and have gatsby-source-strapi installed. It remains a mistery....

Doing as @dougsmith1000 suggested helps, however then I have to re-copy the edited file/package over and over again into node_modules after having changed my package.json.

This issue is definitely not dead guys!

shrirambalaji commented 2 years ago

@FlxAlbroscheit So patch-package helped me with this patching the node modules with the fix that @dougsmith1000 suggested.

https://www.npmjs.com/package/patch-package

I've moved on from the project I was working on but atleast using patch package helps work around this issue.

FlxAlbroscheit commented 2 years ago

Thanks for your kind note :) Meanwhile I was able to solve the mentioned problem by moving from yarn to npm (and deleting node_modules, of course). So maybe yarn kept an outdated version of @reach/router in its global cache, but that's just an idea.

tobeagram commented 2 years ago

I went into @gatsby/reach-router/index.js and added exports.BaseContext = BaseContext; to the final line of the file and it seems to build well now.

I just updated to gatsby@4.1 with yarn and I'm having the same issue. @dougsmith1000's hack worked to fix the problem temporarily for development, but it's not an ideal solution for use in a prod environment.

EDIT: I tried using patch-package but it would not work in prod environment when deploying on Netlify. The same error would arise:

Attempted import error: 'BaseContext' is not exported from '@gatsbyjs/reach-router' (imported as 'BaseContext').
PhilipF5 commented 2 years ago

I encountered this issue in the process of upgrading a project from Gatsby v2 to v4, and put a bunch of console logs in some places to try to understand what was happening. I was able to arrive at a solution that doesn't require editing node_modules, and I hope it may shed some light on why this is happening in the first place.

TL;DR Cause — The reach-router-add-basecontext-export-loader is adding the needed export to @gatsby/reach-router/es/index.js but not to @gatsby/reach-router/index.js, and the latter is what Gatsby is importing (in my case, at least).

TL;DR Fix/Workaround — Create your own basic loader to add the export, just like the Gatsby team did for the other file. Code below.

I wouldn't call myself a Gatsby pro, so I don't know why Gatsby in my project is using /index.js instead of /es/index.js. I'm on Node 16 LTS, if that matters. The fact that reach-router-add-basecontext-export-loader addresses this problem, but only for /es/index.js, suggests that either my Gatsby project is importing the router wrongly somehow (and perhaps some other people's projects are not, hence difficulty reproducing), or that certain projects legitimately import the router this way, and not having a built-in BaseContext patch for it like the other path does is simply an oversight.

Hopefully this information can be useful in figuring out the underlying problem. But in the meantime, the issue can be worked around by doing the same thing the Gatsby team did: create a loader that adds the export at build time. In my case, I created my own reach-router-add-basecontext-export-loader.js at the root of my project with the appropriate export format (it's different from what the ES version needs):

exports.default = function (source) {
    if (source.includes("exports.BaseContext")) {
        return source;
    } else {
        return source + "exports.BaseContext = BaseContext;";
    }
}

And then added it to the Webpack config via actions.setWebpackConfig in gatsby-node.js, making sure to test for the reach-router/index.js rather than reach-router/es/index.js:

actions.setWebpackConfig({
    module: {
        rules: [
            {
                test: require.resolve(`@gatsbyjs/reach-router/index`),
                type: `javascript/auto`,
                use: [
                    {
                        loader: require.resolve(`./reach-router-add-basecontext-export-loader`),
                    },
                ],
            },
        ],
    },
});

This yields the same effect in the build as manually adding the export to the file in node_modules, but without the complications of patching node_modules. I hope it's helpful for anyone else who runs into this until the bug is truly resolved.

dougsmith1000 commented 2 years ago

Hi all, From way back when. My issue was that I had the old directory-named-webpack-plugin active in my gatsby-node.js file and it was overstepping. I'm not sure when, but Gatsby changed their api to natively include the functionality to have absolute imports without a plugin. https://www.gatsbyjs.com/docs/how-to/custom-configuration/add-custom-webpack-config/#absolute-imports

barbalex commented 2 years ago

I am getting this error now when running a normal yarn dev on my pc, not docker. Have spent a few hours trying anything to solve.

Gatsby dependency bugs are hitting us VERY BAD. As normal with these bugs the issue is closed because of course there is no simple was to create a minimal reproduction.

barbalex commented 2 years ago

Seems that any dependency bug in gatsby gets you to install additional dependencies to try to control the used version. Which snowballs the problems. In the end I guess we end maintaining our own version of gatsby 😢

ZeldOcarina commented 1 year ago

Hi! It's over two years now and I also still have this bug. Is there any way we can help?

ahmedragab96 commented 1 year ago

Hello , I am facing same exact issue! any fix or help , please ?

kuchaguangjie commented 1 year ago

The tutorial does't work ... as described in above several comments, I've tried both npm and pnpm,

calpa commented 1 year ago

pnpm install @gatsbyjs/reach-router does work

ZeldOcarina commented 1 year ago

@ascorbic you closed this over two years ago and people are still having issues with it.. can you please reopen it now?

ascorbic commented 1 year ago

@ZeldOcarina I'm afraid I don't work at Gatsby anymore, so you'll need to take it up with someone else.

ZeldOcarina commented 1 year ago

ahah ok good to know! :)