question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Serverless is incompatible with server-side modules that use `esm`

See original GitHub issue

Because the esm pkg is not intended to be used with webpack, it doesn’t work quite right with target: 'serverless'.

More details can be found in the original issue filed with now-cli: https://github.com/zeit/now-cli/issues/2569.

Despite the advise esm gives to prefer the module key, this is not actually feasible or a proper solution.

This mainly boils down to two reasons, broadly speaking:

  1. The module field is largely a browser field, not a Node.js field.
  2. Many packages are published with a CJS (main) variant that does not use the default key, meaning the non-standard switch to ESM breaks packages that work in Node.

The only viable options is to transform source code to remove esm.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:10 (6 by maintainers)

github_iconTop GitHub Comments

5reactions
Timercommented, Jul 25, 2019

browser typically indicates a UMD build or similar, not a bundler-friendly build. That’s why browser code is under the module key, because it spawned from webpack (first-and-foremost, a front-end bundler).

Ultimately, we have too few field choices to work with here.

For maximum ecosystem compatibility, in my experience, you must:

  1. Avoid using the esm package for things intended to be used in browser and Node. This package works great for Node-only packages.
  2. Ship ES Modules code, compiled down to ES5, under the modules field
  3. Ship CommonJS code, compiled down to oldest non-EOL Node version, under the main field.
  4. ☝️ both of these bundles should be isomorphic, working in a Node and Browser environment if you need them to (typeof window or typeof process, never process.browser).

However, more projects are moving towards compiling ./node_modules/ which allow you to ship ES.Latest under the module key. Next.js will do this soon. Some other parts of the ecosystem still need to catch up, so this isn’t generally safe yet. Do note, compiling other users code is not a safe behavior, but works in most cases.

The code shipped under the main key still should be compiled down to the oldest-non-EOL Node version.

TBH, for your specific case, I would:

  1. Publish esmodules code under module key
  2. Have a main field with the value of index (note no extension), this allows users to resolve .mjs first if they desire in their bundler, otherwise gives .js w/ CJS
  3. Include a index.mjs that re-exports the module key’s entry point (or, preferably, skip this all together since ESM in Node.js isn’t a real thing)
  4. Include a index.js that contains compiled commonjs code

☝️ unfortunately there’s no esm in this picture since your code is designed to be used in browser and server.

Whilst this will actually be solved in Next.js soon (and you can use your current setup, with esm as-is), you may find other users / tools having to customize their setup to accommodate it.


Edit: Just want to add/reiterate:

The above suggestion is an opinion based on my experiencing maintaining two popular DX Toolboxes. There is no right or wrong answer because none of these fields are based on standards.

These practices also do not reflect the direction the ecosystem is potentially heading in the future, because they’re concerned with present-day maximum compatibility.

As an anecdote, you’ll see Node 12 uses a completely different behavior and that users are beginning to ask for ES.Latest to be published.

2reactions
Timercommented, Jul 25, 2019

No @ericelliott, because they end up being bundled by webpack which converts them into commonjs.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Serverless is incompatible with server-side modules that use ...
The esm package is largely an attempt to solve this behavior by ensuring the main and module key are identical and isomorphic (until...
Read more >
Imoprting ESM-only dependencies/Running as ESM Module
I solved this issue by making a separate handler module that imports the index. mjs file and calls the handler in it, like...
Read more >
Setting up a Serverless Project with Webpack, Babel, and Knex
The solution I went for is to use a Babel plugin to transform ESM to CommonJS Modules which is the standard for Node...
Read more >
State of the Web: Deno - ByteofDev
In contrast, Deno only works with entirely standards-compliant ESM. Using one module format makes using Deno a lot simpler for both users ...
Read more >
Gotchas - Remix
To fix it, move the import into a different module named *.server.js or ... import some CommonJS modules that are incompatible with being...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found