Gatsby: Gatsby Build Fails when using export { default } syntax

Created on 7 Mar 2019  Β·  21Comments  Β·  Source: gatsbyjs/gatsby

Description

When I have a page that looks like:

// in pages/my-page.js
export { default } from '../../components/hello-world';

gatsby build fails, even if that default export is a component. However, this works, even though it's functionality identical:

// in pages/my-page.js
import HelloWorld from '../../components/hello-world';

export default HelloWorld;

Steps to reproduce

  1. Add a new page to the boilerplate with just an export { default } from '',
  2. Run yarn gatsby build
  3. You should see a build error

Minimal repro repo: https://github.com/liamfd/gatsby-boilerplate/tree/export-default-minimal-repro/src. Make sure you're in the export-default-minimal-repro branch. Then run yarn gatsby build. develop seems to work fine.

Expected result

It should build!

Actual result

The build throws "error [/Users/liam/fabric/test-gatsby-site/src/pages/page-4.js] The page component must export a React component for it to be valid".

Environment

(gatsby info --clipboard is pretty cool!)

  System:
    OS: macOS High Sierra 10.13.6
    CPU: (4) x64 Intel(R) Core(TM) i5-7267U CPU @ 3.10GHz
    Shell: 5.3 - /bin/zsh
  Binaries:
    Node: 8.10.0 - ~/.nvm/versions/node/v8.10.0/bin/node
    Yarn: 1.12.1 - /usr/local/bin/yarn
    npm: 5.6.0 - ~/.nvm/versions/node/v8.10.0/bin/npm
  Languages:
    Python: 2.7.10 - /usr/bin/python
  Browsers:
    Chrome: 72.0.3626.119
    Firefox: 65.0.1
    Safari: 12.0.3
  npmPackages:
    gatsby: ^2.1.23 => 2.1.23 
    gatsby-image: ^2.0.31 => 2.0.31 
    gatsby-plugin-manifest: ^2.0.22 => 2.0.22 
    gatsby-plugin-offline: ^2.0.24 => 2.0.24 
    gatsby-plugin-react-helmet: ^3.0.8 => 3.0.8 
    gatsby-plugin-sharp: ^2.0.25 => 2.0.25 
    gatsby-source-filesystem: ^2.0.23 => 2.0.23 
    gatsby-transformer-sharp: ^2.1.15 => 2.1.15 

Theory/Suggestion

I'm guessing that this check is the problem:

    if (
      !fileContent.includes(`export default`) &&
      !fileContent.includes(`module.exports`) &&
      !fileContent.includes(`exports.default`) &&
      // this check only applies to js and ts, not mdx
      /\.(jsx?|tsx?)/.test(path.extname(fileName))
    ) {
      includesDefaultExport = false
    }

It seems like the es6 default export check should be expanded to support at least the es6 export from syntax options:

export { name1 as default, … };
export { default } from …;

It might also be worth considering support for the export-default-from proposal. It's stage-1, but I think a fair amount of people use it or its predecessor:

export default from "mod";

I'm happy to try my hand at a PR, assuming this behavior is not intentional. It does seem a little tricky to check this stuff robustly without using an AST.

help wanted feature or enhancement

Most helpful comment

Now the validation check is:

    if (
      !fileContent.includes(`export default`) &&
      !fileContent.includes(`module.exports`) &&
      !fileContent.includes(`exports.default`) &&
      !fileContent.includes(`exports["default"]`) &&
      !fileContent.match(/export \{.* as default.*\}/s) &&
      // this check only applies to js and ts, not mdx
      /\.(jsx?|tsx?)/.test(path.extname(fileName))
    ) {

But it still fails to match export { default } from './whatever'.

As a temporary fix, I just use // export default.


Also, before finding out about this issue, I was really confused when it was not working only on production builds (since I was messing with import aliases just before) and that while debugging with commented code, I realized that it was now working!?

Now, I'm wondering why this check even exists at all?

  • It fails to accomplish its goal right now by making valid code fail to build with a cryptic message.
  • It's really _not_ future proof since it will fail again as new syntax or use-cases are created.

If it's that important for newcomers to have this message, I feel like a warning should be enough. πŸ€”

All 21 comments

Just to follow up a bit - I wonder if it would be a good idea to update the error message copy to more closely match the check that's triggering it:

The page component must export a React component for it to be valid

That sent me down a bit of a rabbit hole, trying to figure out why the import might be broken.

Perhaps something along the lines of:

The page must have a default export, which must be a React component.

There's a fair amount of complexity here, but we'd happily take a PR tweaking documentation or error messages for this!

We could (and probably should!) handle the use case you're describing, but a quick win is certainly just updating the error message, like you said.

Any interest in PRing that?

@DSchau sure, happy to, might be a bit before I can do so.

I have similar problems.
When I use export default build fails with the following errors:

Module build failed (from ./node_modules/gatsby/dist/utils/babel-loader.js):
SyntaxError: /src/components/index.js: Support for the experimental syntax 'exportDefaultFrom' isn't currently enabled (1:8):


> 1 | export ChartsGrid from "./ChartsGrid";
    |        ^
  2 | export ChartList from "./ChartsList";

Add @babel/plugin-proposal-export-default-from (https://git.io/vb4yH) to the 'plugins' section of your Babel config to enable transformation.
    at Object.raise 

I've tried to install @babel/plugin-proposal-export-default-from pluging, as suggested in error log, but it did not help.

When this will be fixed?

@markvital ah! OK - so that's separate to this issue, but thanks for letting us know!

Here's a quick example I just whipped up that shows how to do that. Specifically check out this file

So -- unless I misunderstand, there's nothing to "fix" here re: that proposal, specifically.

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! πŸ’ͺπŸ’œ

@DSchau I'm looking at this issue a bit now. In your example above, I'm noting that you've installed @babel/plugin-proposal-export-default-from as a dev dependency. To implement, wouldn't you need to set up a custom .babelrc file, as noted https://www.gatsbyjs.org/docs/babel/#how-to-use-a-custom-babelrc-file?

@samageloff hi!

I provided the example, were you able to check it out? I actually used the onCreateBabelConfig hook in gatsby-node.js -> https://www.gatsbyjs.org/docs/node-apis/#onCreateBabelConfig, specifically used here. This allows us to more cleanly extend the default babel-config, rather than re-creating it in a local .babelrc.js.

@DSchau - I missed this! Thanks for pointing it out.

@DSchau where do you think would be the best place to expand the docs? In the Babel guide? https://www.gatsbyjs.org/docs/babel/

It would be great to get this improvement in, if anyone feels like taking it on!

How's the state of this?
Stage 1 export something from 'something-else' form is not the problem here, but the fact that the official export { default } from 'something' form isn't supported, as @liamfd correctly pointed out.

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!

As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request. Check out gatsby.dev/contribute for more information about opening PRs, triaging issues, and contributing!

Thanks for being a part of the Gatsby community! πŸ’ͺπŸ’œ

Now the validation check is:

    if (
      !fileContent.includes(`export default`) &&
      !fileContent.includes(`module.exports`) &&
      !fileContent.includes(`exports.default`) &&
      !fileContent.includes(`exports["default"]`) &&
      !fileContent.match(/export \{.* as default.*\}/s) &&
      // this check only applies to js and ts, not mdx
      /\.(jsx?|tsx?)/.test(path.extname(fileName))
    ) {

But it still fails to match export { default } from './whatever'.

As a temporary fix, I just use // export default.


Also, before finding out about this issue, I was really confused when it was not working only on production builds (since I was messing with import aliases just before) and that while debugging with commented code, I realized that it was now working!?

Now, I'm wondering why this check even exists at all?

  • It fails to accomplish its goal right now by making valid code fail to build with a cryptic message.
  • It's really _not_ future proof since it will fail again as new syntax or use-cases are created.

If it's that important for newcomers to have this message, I feel like a warning should be enough. πŸ€”

@emileber 100% agree, this is a dumb restriction and very confusing because dev and prod builds don't work the same way

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!
As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request. Check out gatsby.dev/contribute for more information about opening PRs, triaging issues, and contributing!

Thanks for being a part of the Gatsby community! πŸ’ͺπŸ’œ

Not stale

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!
As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request. Check out gatsby.dev/contribute for more information about opening PRs, triaging issues, and contributing!

Thanks for being a part of the Gatsby community! πŸ’ͺπŸ’œ

not stale

Hope with this will be supported soon, since it is very useful for very long imports name. The build error is not that verbose which code breaks in gatsby build command, since this issue was also confirmed in my environment.

@JamesDelfini just add // export default (in the meantime) in the file and then it won't trip the check and gatsby should treat it as valid.

@JamesDelfini just add // export default (in the meantime) in the file and then it won't trip the check and gatsby should treat it as valid.

I did some alternative for this since export default from './Home' doesn't accept as typescript syntax to this one

import Home from './Home'

export { Home as default }

As one of the valid validation check's you've said. Thank you.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

benstr picture benstr  Β·  3Comments

magicly picture magicly  Β·  3Comments

KyleAMathews picture KyleAMathews  Β·  3Comments

jimfilippou picture jimfilippou  Β·  3Comments

brandonmp picture brandonmp  Β·  3Comments