-
Couldn't load subscription status.
- Fork 29.7k
Description
What version of Next.js are you using?
10.1.3
What version of Node.js are you using?
15.9.0
What browser are you using?
Chrome
What operating system are you using?
MacOS
How are you deploying your application?
Running locally via express
Describe the Bug
I have an Express.js server that sets up Next.js, and I want to use ES6 modules with my backend.
My package.json has the line "type": "module", which enables ES6 module support in Node.js. Everything is imported fine, but when I try to load a page, I get the following exception:
error - Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /Users/alexey/work/alexey/temp/.next/server/pages/_document.js
require() of ES modules is not supported.
require() of /Users/alexey/work/alexey/temp/.next/server/pages/_document.js from /Users/alexey/work/alexey/temp/node_modules/next/dist/next-server/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 /Users/alexey/work/alexey/temp/package.json.
at new NodeError (node:internal/errors:329:5)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1108:13)
at Module.load (node:internal/modules/cjs/loader:971:32)
at Function.Module._load (node:internal/modules/cjs/loader:812:14)
at Module.require (node:internal/modules/cjs/loader:995:19)
at require (node:internal/modules/cjs/helpers:92:18)
at requirePage (/Users/alexey/work/alexey/temp/node_modules/next/dist/next-server/server/require.js:1:1184)
at loadComponents (/Users/alexey/work/alexey/temp/node_modules/next/dist/next-server/server/load-components.js:1:795)
at DevServer.findPageComponents (/Users/alexey/work/alexey/temp/node_modules/next/dist/next-server/server/next-server.js:77:296)
at DevServer.renderErrorToHTML (/Users/alexey/work/alexey/temp/node_modules/next/dist/next-server/server/next-server.js:139:29)
at DevServer.renderErrorToHTML (/Users/alexey/work/alexey/temp/node_modules/next/dist/server/next-dev-server.js:35:1392)
at runMicrotasks (<anonymous>)
at processTicksAndRejections (node:internal/process/task_queues:94:5)
at async DevServer.renderError (/Users/alexey/work/alexey/temp/node_modules/next/dist/next-server/server/next-server.js:138:1659) {
code: 'ERR_REQUIRE_ESM'
}
Indeed, looking at .next/server/pages/_document.js, it has a var installedModules = require('../ssr-module-cache.js'); directive, which is against the rules for "type": "module".
This seems to imply that I can not use Next.js with ES6 syntax in Node - which is too bad!
Expected Behavior
I think what I would expect is that Next.js would compile in a way that's compatible with ES6 modules - i.e. when "type": "module" is enabled, it relies on import, not require
To Reproduce
I've created a minimal setup where I'm able to get this to reproduce:
package.json
{
"scripts": {
"start": "node index.js"
},
"name": "es6_import_issue",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"author": "Alexey Chernikov",
"dependencies": {
"express": "^4.17.1",
"next": "^10.1.3",
"react": "^17.0.2",
"react-dom": "^17.0.2"
},
"type": "module"
}
index.js
/*
This style works if I don't do "type": "module"
in package.json - main.jsx loads fine!
*/
/*
const express = require('express');
const next = require('next');
const http = require('http');
*/
/*
With this style and "type": "module" in package.json
I get the error described
*/
import express from 'express';
import next from 'next';
import http from 'http';
class Server {
constructor(port) {
this.port = port;
this.express = express();
this.next = next({ dev: process.env.NODE_ENV !== 'production' });
}
async start() {
await this.next.prepare();
this.express.get('/', (req, res) => {
return this.next.render(req, res, `/main`, req.query);
})
this.express.get('*', (req, res) => {
return this.next.render(req, res, `/${req.path}`, req.query);
})
this.server = http.createServer(this.express);
this.server.listen(this.port);
}
}
const begin = async () => {
const port = 3000;
new Server(port).start();
console.log(`Server running on port ${port}`);
};
begin();
And also in pages/main.jsx:
const hello = () => {
return <div>
Hello world
</div>
}
export default hello
With this setup, after a yarn install and yarn start, I see the error above. I left the require style that works fine w/o a "type": "module" directive in comments so it's quick to test that this Express+Next.js setup is in fact functional.