serverless-nextjs / serverless-next.js

⚡ Deploy your Next.js apps on AWS Lambda@Edge via Serverless Components
MIT License
4.47k stars 457 forks source link

Lambda@Edge Builder fails on ESM modules #2391

Open shishkin opened 2 years ago

shishkin commented 2 years ago

Issue Summary

I've tried building Lambda@Edge using the latest Next.js v12.1.0 release with "type": "module" setting in package.json, which got recent support. The builder fails with an error suggesting that next.config.js is treated as ESM and needs to be renamed to .cjs. Renaming it confusingly produces the same error.

Actual behavior

Error: Command failed with exit code 1: ./node_modules/.bin/next build
error - Failed to load next.config.js, see more info here https://nextjs.org/docs/messages/next-config-error

> Build error occurred
ReferenceError: module is not defined in ES module scope
This file is being treated as an ES module because it has a '.js' file extension and '.../package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.

Expected behavior

Lambda@edge builds without errors.

Steps to reproduce

  1. Create new Next.js project
  2. Add @sls-next/lambda-at-edge dependency
  3. Set "type": "module" setting in package.json
  4. Run yarn build
  5. Run yarn exec exec build-lambda-at-edge .

Screenshots/Code/Configuration/Logs

See above.

Versions

Additional context

Checklist

shishkin commented 2 years ago

The error still persists in the 3.7.0 version.

I've traced it down to the function createServerlessConfig which is called by the builder. That function overwrites next.config.js file with a CommonJS config which then fails in an ESM environment.

The only purpose of config overwrite is to assign a target option which has been deprecated in next 12 anyway.

Would it be possible to remove that intrusive blocker from the builder?

florianbepunkt commented 2 years ago

Running into the same issue. A quick and dirty workaround:

https://github.com/serverless-nextjs/serverless-next.js/blob/e6367b585fb98608cd2e9327e2c8d4058ba73b00/packages/libs/core/src/build/lib/createServerlessConfig.ts#L48 Change the entry to .cjs extension and rename the next.config.js in your app's root folder to next.config.cjs

As ESM adoption increases, a proper fix would be great. For example instead of defining a config directory, specify a config file and derive the config directory from it (which seem to be used for other stuff). Or check for the existence of .js, .mjs and .cjs by default. I put together a PR, but as @shishkin pointed out: The function may be obsolete anyway.

2478 targets this, although not handling next.config.cjs

revmischa commented 2 years ago

I tried to handle next.config.mjs but it caused other problems

Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/cyber/dev/sst-prisma/web/next.config.mjs not supported.
Instead change the require of /Users/cyber/dev/sst-prisma/web/next.config.mjs to a dynamic import() which is available in all CommonJS modules.

I tried to fix that issue but ran into a different issue, described in the PR #2478