vercel / next.js

The React Framework
https://nextjs.org
MIT License
126.89k stars 26.97k forks source link

Error: Must use import to load ES Module #25454

Closed Laci556 closed 3 years ago

Laci556 commented 3 years ago

What version of Next.js are you using?

10.2.2

What version of Node.js are you using?

14.16.1

What browser are you using?

Edge

What operating system are you using?

Windows

How are you deploying your application?

local development

Describe the Bug

When importing the react-konva package I get this error

Server Error
Error: Must use import to load ES Module: C:\Users\bucsa\dev\atomic\node_modules\konva\lib\Core.js
require() of ES modules is not supported.
require() of C:\Users\bucsa\dev\atomic\node_modules\konva\lib\Core.js from C:\Users\bucsa\dev\atomic\node_modules\react-konva\lib\ReactKonvaCore.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 Core.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from C:\Users\bucsa\dev\atomic\node_modules\konva\package.json.

The same error was thrown when I tried to import the chessops library but managed to work around that by dynamically importing it when the component loads. Neither that nor importing with next/dynamic could solve the issue with this package though.

Expected Behavior

I expected the components to be imported and not throw an error.

To Reproduce

Install react-konva and konva

import { Stage } from 'react-konva'

const Example = () => {
  return <Stage></Stage>
}
JacobLey commented 3 years ago

It sounds to me like you are using type: module in your package.json? So your server-side code is executing native ESM?

Thats the way I have mine set up, and it is possible, but NextJS is dragging their feet on native ESM support. So you have to hack around in a couple places... If you don't really want/need ESM you can disable it and just rely on NextJS's transpiling to CJS.

If you are determined to use native ESM, I can point you to a couple PR's/discussions that help get around these issues.

Laci556 commented 3 years ago

The issue was solved by importing dynamically and with ssr: false. It's still weird though, I didn't use "type": "module" in my package.json and the error came up in a fresh nextjs installation too. Even without using the components, just importing them. Only typescript complains about the components because they are not the default export from the package but that was solved by wrapping my component's import with dynamic. Haven't looked at the chessops library yet but I guess that should also work inside my dynamically imported component.

steven-tey commented 3 years ago

@Laci556 I'm trying to do the same thing as well for my project but I'm running into a similar issue.

I tried importing react-konva dynamically without ssr (refer screenshot below):

CleanShot 2021-06-16 at 10 23 39@2x

While that worked, it gave me another error – I wasn't able to set a useRef() tag on any of the elements that I imported (Stage, Transformer), because they are Lazy Components:

CleanShot 2021-06-16 at 10 25 03@2x

I suspect the initial error that we both faced has something to do with NextJS not supporting ES modules, and I was wondering if you ran into the second issue as well? If so, how did you fix it?

Laci556 commented 3 years ago

@steven-tey I did not try to use the components with refs so I haven't faced this issue but after a bit of testing I found the solution. Instead of importing these components in the page, create a component that handles all the canvas logic and import that dynamically without SSR. Inside that component, you can use the react-konva components normally.

Before:

// pages/some-page.js
import React, { useRef } from 'react';
import dynamic from 'next/dynamic';
const Stage = dynamic(() => import('react-konva').then((module) => module.Stage), { ssr: false });

export default function Home() {
  const stageRef = useRef();

  return (
    <div>
      <Stage ref={stageRef} width={500} height={500}></Stage>
    </div>
  );
}

After:

// pages/some-page.js
import React from 'react';
import dynamic from 'next/dynamic';
const MyComponent = dynamic(() => import('../components/MyComponent'), { ssr: false });

export default function Home() {
  return (
    <div>
      <MyComponent></MyComponent>
    </div>
  );
}
// components/MyComponent.js
import React, { useRef } from 'react';
import { Stage, Layer } from 'react-konva'; // notice you can import from react-konva normally

export default function Home() {
  const stageRef = useRef();

  return (
    <div>
      <Stage width={500} height={500} ref={stageRef}>
        <Layer></Layer>
      </Stage>
    </div>
  );
}

It should be as easy as copying and pasting everything from the page and maybe passing the url params to your component as props if you don't have any content that must be rendered server side.

For my project I realized SSR is unnecessary for 99% of the pages especially with all this headache from fighting with next dynamic imports so I just switched to bare react.

curiousercreative commented 3 years ago

FWIW, the latest NextJS@11 produces a similar webpack error when importing of an ESM-only npm package.

omar-dulaimi commented 3 years ago

@curiousercreative What do you suggest to fix that kind of issue? (typescript with a library that uses type: module in package.json)

curiousercreative commented 3 years ago

@curiousercreative What do you suggest to fix that kind of issue? (typescript with a library that uses type: module in package.json)

I work around the problem by using this: https://www.npmjs.com/package/next-transpile-modules. Has worked well with several dependencies that otherwise produce the err described above.

anargiris commented 3 years ago

I am running into the same problem using 'globby' for generating website's sitemap.

Anyone has any solutions that work?

sidwebworks commented 3 years ago

Same issue, any updates?

zipang commented 3 years ago

Same issue here with Next.JS 10.2.3 with Sindre Sohrus's p-limit which effectively uses the "type": "module" in its package.json. I haven't been able to make the next-transpile-modules workaround work...

Module parse failed: Unexpected token (7:6)
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
| 
| class Node {
>       value;
|       next;
|
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /.../node_modules/p-limit/index.js
require() of ES modules is not supported.
require() of /.../node_modules/p-limit/index.js from /.../.next/server/pages/_admin/upload.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.

Has this fix been pushed to the 10.x.x branch ? Best Regards,

engelmav commented 3 years ago

This actually happens intermittently with ReactMarkdown.

Frosty92 commented 3 years ago

Thanks @Firanolfind! That fixed the following error:

Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /vercel/path0/node_modules/react-markdown/index.js
-
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /vercel/path0/node_modules/react-markdown/index.js
--

Note that I had to add webpack5: false like so:


const withTM = require("next-transpile-modules")(["react-markdown"]);
module.exports = withTM({ webpack5: false });
ypratham commented 3 years ago

Anything for remark-gfm @Firanolfind

timothyerwin commented 3 years ago

@Firanolfind perfect. looks like that fixed my issue.

This actually happens intermittently with ReactMarkdown.

Found solution for ReactMarkdown

next.config.js

const withTM = require('next-transpile-modules')(['react-markdown']);

module.exports = withTM({
...
})

and import it like that import ReactMarkdown from 'react-markdown/react-markdown.min';

cassus commented 3 years ago

If you need to include a lot of packages in the transpiler list you can generate the list like this:

cd node_modules
for d in $(ls); do grep '"type": "module"' "$d"/package.json >/dev/null 2>&1 && echo \"$d\", ; done
IzioDev commented 3 years ago

Why is this closed? Couldn't we add a babel post-processor in order to transpile ESM?

sodhisaab commented 3 years ago

This actually happens intermittently with ReactMarkdown.

Found solution for ReactMarkdown

next.config.js

const withTM = require('next-transpile-modules')(['react-markdown']);

module.exports = withTM({
...
})

and import it like that import ReactMarkdown from 'react-markdown/react-markdown.min';

You almost saved me 2 days πŸ˜„ I was struggling to find a solution and tried a lot of things.

Now I get this warning in the terminal. any suggestion?

markdown-warning

actually fixed by adding order prop to the li element

   <ReactMarkdown
              children={page.content}
              components={{
                li: ({ node, ...props }: any) => (
                  <li className="list-disc" ordered="false" {...props} />
                ),
              }}
          />
motdde commented 3 years ago

Thanks @Firanolfind

hatamsoyunov commented 3 years ago

@Laci556 Thanks! πŸ™‡πŸ»β€β™‚οΈ

PButcher commented 3 years ago

Anything for remark-gfm @Firanolfind

No idea if this is a good solution or not, but I followed the errors and built on the solutions by @Firanolfind and @Frosty92 and got react-markdown and remark-gfm working with this next.config.js:

const withTM = require("next-transpile-modules")([
  "react-markdown",
  "remark-gfm",
  "micromark-extension-gfm",
  "micromark-util-combine-extensions",
  "micromark-util-chunked",
  "micromark-util-character",
  "micromark-util-sanitize-uri",
  "micromark-util-encode",
  "micromark-util-classify-character",
  "micromark-util-resolve-all",
  "micromark-factory-space",
  "mdast-util-gfm",
  "ccount",
  "mdast-util-find-and-replace",
  "unist-util-visit-parents",
  "unist-util-is",
  "mdast-util-to-markdown",
  "markdown-table",
]);

module.exports = withTM({ webpack5: false });

CC: @ypratham

andreyroth commented 3 years ago

For anyone that's struggling with react markdown, version 7 introduced (in August 2021) a breaking change by forcing the use of ESM. There's a neat little guide to fixing issues with ESM packages here

dlbnco commented 3 years ago

Thanks @Firanolfind!

To keep the types, you can declare the following in a globals.d.ts file:

declare module 'react-markdown/react-markdown.min' {
  import ReactMarkdown, {
    Components,
    Options,
    uriTransformer,
  } from 'react-markdown';
  export const Components: Components;
  export const Options: Options;
  export const uriTransformer: uriTransformer;
  export default ReactMarkdown;
}
rtritto commented 3 years ago

@zipang @surferwat did you resolve?

Same problem with p-limit v4.0.0 and next.js v11.1.2.

I did some changes:

Result:

Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: C:\test-nextjs\.next\server\pages\_document.js
require() of ES modules is not supported.
require() of C:\test-nextjs\.next\server\pages\_document.js from C:\test-nextjs\.yarn\__virtual__\next-virtual-23e0d520d9\0\cache\next-npm-11.1.2-b1c338c95c-c5a6d01b6d.zip\node_modules\next\dist\server\require.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 _document.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from C:\test-nextjs\package.json.
...
Powersource commented 3 years ago

Couldn't get remark-gfm to work. Tried some solution here. Ended up 'solving' it by just downgrading remark-gfm to 1.0.0, away from esm.

tiavina-mika commented 3 years ago
import dynamic from 'next/dynamic';
const MyComponent = dynamic(() => import('../components/MyComponent'), { ssr: false });

fixed my issue with React-konva

eric-burel commented 2 years ago

Hi guys, I am facing this issue in a fresh install, I don't know what I do wrong when building my package.

You can repro here: https://github.com/VulcanJS/npm-the-right-way

It might be a mistake in the way I build the package, but I can't tell what's wrong. I am trying to build a solid demo of how to build full-stack packages for Next with modern tooling.

Edit: ok https://github.com/vercel/next.js/issues/25454#issuecomment-862571514 fixed it, I need to import in 2 steps as described, I cannot dynamically import the npm package.

balazsorban44 commented 2 years ago

This issue has been automatically locked due to no recent activity. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.