gatsby: gatsby-config/node.js doesn't support ESM import/export

Summary

Node v14 is out and with it the removal of the Experimental Modules warning! šŸŽ‰

I installed it, added "type": "module" to package.json, used export default in gatsby-config.js and took the default starter for a spin. This is what I got:

Error: [ERR_REQUIRE_ESM]: Must use import to load ES Module: gatsby-config.js require() of ES modules is not supported. require() of gatsby-config.js from node_modules/gatsby/dist/bootstrap/get-config-file.js is an ES module file as it is a .js file whose nearest parent package.json contains ā€œtypeā€: ā€œmoduleā€ which defines all .js files in that package scope as ES modules. Instead rename gatsby-config.js to end in .cjs, change the requiring code to use import(), or remove ā€œtypeā€: ā€œmoduleā€ from package.json.

Sounds like Gatsby, specifically gatsby/dist/bootstrap/get-config-file.js, stands in the way of using ESM import/export syntax. I think it’s time to make gatsby’s config and node APIs ESM-ready. šŸš€

Basic example

export default {
  siteMetadata: {
    title: `Gatsby Default Starter`,
    author: `@gatsbyjs`,
  },
  plugins: [
    `gatsby-plugin-react-helmet`,
    // ...
  ],
}

Motivation

Would be really cool if we could finally use a single import/export system all throughout our Gatsby projects! As the release announcement states:

It is our belief that the current implementation offers a future proof model to authoring ESM modules that paves the path to Universal JavaScript.

If that doesn’t get you excited, you must be in the wrong line of work. šŸ˜„

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 6
  • Comments: 37 (23 by maintainers)

Most upvoted comments

@LekoArts @KyleAMathews Node 16 is out, this is no longer experimental and should be reopened.

Yeah, Gatsby not supporting ESM will become a big problem in the next weeks as people upgrade to the latest remark packages, which are full ESM.

@LekoArts would recommend the team reopening this one - it should be an issue, not a feature request.

cc @wooorm

@tujoworker thx, but that method doesnt work with remark ecosystem. i’ve tried that before.

@Ir1d - I haven’t found a solution to using import/export in gatsby-config/node.js. The closest I got to using import/export in gatsby-config/node.js is by using the esm npm package to require serializable js files and convert to es modules to use in gatsby-config/node.js. For example, I had config/site.js, which contained serializable javascript like so:

// site.js
const site = {
  title: `my title`,
  description: `my description`,
  url: `https://example.com`,
};

export default site;

and I use esm npm package to convert site.js from esm to cjs:

// esm.js

require = require('esm')(module)

const {default: site} = require('./site')

module.exports = {
  site
}

this way, I can use site (which is esm) in gatsby-config.js:

const {site} = require('./src/config/esm')

module.exports = {
  siteMetadata: site,
  ...
}

However, this no longer works if you try to convert .js/jsx to .ts/tsx files. I know you can convert .jsx files to .tsx in Gatsby, but esm npm package cannot read .ts files so I am unable to update my Gatsby sites to use TypeScript at the moment. I’m probably better off using Next.js at this point if I want to continue using my config files

I’m facing a similar issue as @thecodingwizard where I want to use the latest unist-util-visit v3.0.0 (which is ESM only) in Gatsby. I’ve also tried using the esm package and also adding "type": "modules" into my Gatsby package.json, but it doesn’t work.

Same problem here. Several gatsby-remark plugins are created inside the ./plugins folder of my project. They fail to require the latest unist-util-visit. I tried to convert them to .mjs and .cjs files without much success. The code work with unist-util-visit version ^2.0.3 and fail with ^3.0.1. I believe the problem is in how gatsby load local plugins more than in the unist-util-visit. This is an extract of the error:


 ERROR #11321  PLUGIN

"gatsby-transformer-remark" threw an error while running the createSchemaCustomization lifecycle:

Must use import to load ES Module: /home/user/website/node_modules/unist-util-visit/index.js
require() of ES modules is not supported.
require() of /home/user/website/node_modules/unist-util-visit/index.js from
/home/user/website/plugins/blog-md-url/index.js is an ES module file as it is a .js file whose nearest parent package.json contains
 "type": "module" which defines all .js files in that package scope as ES modules.
Instead rename /home/user/website/node_modules/unist-util-visit/index.js to end in .cjs, change the requiring code to use import(),
 or remove "type": "module" from /home/user/website/node_modules/unist-util-visit/package.json.




  Error: [ERR_REQUIRE_ESM]: Must use import to load ES Module: /home/user/website/node_modules/unist-util-visit/index.js
  require() of ES modules is not supported.
  require() of /home/user/website/node_modules/unist-util-visit/index.js from /home/user/website/plugins/blog-md-
  url/index.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in th
  at package scope as ES modules.
  Instead rename /home/user/website/node_modules/unist-util-visit/index.js to end in .cjs, change the requiring code to use import(
  ), or remove "type": "module" from /home/user/website/node_modules/unist-util-visit/package.json.
  
  - errors:363 new NodeError
    node:internal/errors:363:5
  
  - loader:1126 Object.Module._extensions..js
    node:internal/modules/cjs/loader:1126:13
  
  - loader:989 Module.load
    node:internal/modules/cjs/loader:989:32
  
  - loader:829 Function.Module._load
    node:internal/modules/cjs/loader:829:14
  
  - loader:1013 Module.require
    node:internal/modules/cjs/loader:1013:19
  
  - v8-compile-cache.js:159 require
    [gatsby]/[v8-compile-cache]/v8-compile-cache.js:159:20
  
  - index.js:9 Object.<anonymous>
    /home/user/website/plugins/blog-md-url/index.js:9:15
  
  - v8-compile-cache.js:192 Module._compile
    [gatsby]/[v8-compile-cache]/v8-compile-cache.js:192:30
  
  - loader:1138 Object.Module._extensions..js
    node:internal/modules/cjs/loader:1138:10
  
  - loader:989 Module.load
    node:internal/modules/cjs/loader:989:32
  
  - loader:829 Function.Module._load
    node:internal/modules/cjs/loader:829:14
  
  - loader:1013 Module.require
    node:internal/modules/cjs/loader:1013:19
  
  - v8-compile-cache.js:159 require
    [gatsby]/[v8-compile-cache]/v8-compile-cache.js:159:20
  
  - create-schema-customization.js:45 
    [gatsby]/[gatsby-transformer-remark]/create-schema-customization.js:45:28
  
  - Array.forEach
  
  - create-schema-customization.js:44 Object.module.exports [as createSchemaCustomization]
    [gatsby]/[gatsby-transformer-remark]/create-schema-customization.js:44:11

Let us know if we need to open a new issue.

I’m facing a similar issue as @thecodingwizard where I want to use the latest unist-util-visit v3.0.0 (which is ESM only) in Gatsby. I’ve also tried using the esm package and also adding "type": "modules" into my Gatsby package.json, but it doesn’t work.

@bytrangle No known way currently. Gatsby is only compatible with packages that are NOT pure ESM. Downgrade to older versions for use with Gatsby.

The Gatsby team is apparently ā€œnot againstā€ moving to ESM (tweet from @wardpeet), but I’m guessing it will still be some time before you can use this in your projects.

If you absolutely need to use the new versions now, you may want to try experimenting with bundling / precompiling the dependency to CommonJS, although this may be complex.

Ah, the reason I can’t find it in the docs is because returning a function in gatsby-config.js is only for themes:

@DSchau: Exporting a function from gatsby-config.js is reserved for themes. Are you trying to create a theme?

https://github.com/gatsbyjs/gatsby/issues/16013#issuecomment-514235110

And yeah, that doesn’t support promises / async functions:

@sidharthachatterjee: Themes do currently accept a function (as you’ve mentioned) but we expect it to the sync.

https://github.com/gatsbyjs/gatsby/issues/19644#issuecomment-558073951

This isn’t a ā€œnice to haveā€ or ā€œhas a workaroundā€ - Gatsby just doesn’t work with new versions of many packages.

Not «that» complex, see the this doc: https://support.gatsbyjs.com/hc/en-us/articles/1500000294121-Using-ES6-Module-Syntax-in-Gatsby-API-Files-on-Gatsby-Cloud

Sure, I agree, having that build in, would be very nice!

indeed. afaik, no one has ever been able to make gatsby work with esm module unist-util-visit

For xdm specifically, I’ve tried a variety of techniques to import it into Gatsby (including using the esm package) and none of them worked. Did anybody have better success importing esm libraries into gatsby-node.js?

Fair enough. Although it’s probably a good idea to start looking into this now.

As always, corporate users should wait to upgrade their production deployments until October when Node.js is promoted to LTS. However, now is the best time to start testing applications with Node.js 14, and try out new features.