Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Node.js ESM support #1781

Closed
kossnocorp opened this issue May 17, 2020 · 27 comments
Closed

Node.js ESM support #1781

kossnocorp opened this issue May 17, 2020 · 27 comments
Milestone

Comments

@kossnocorp
Copy link
Member

Unfortunately, Node.js didn't add support for "module" field that is supported by bundlers such as webpack, and introduced their own resolve logic.

To add Node.js ESM support instead of /esm submodule we need to add .mjs version next to CommonJS files. That would be a breaking change so we should introduce it in v3.

Thank you Node.js, very nice.

See the issue: #1779

@karlhorky
Copy link

@kossnocorp maybe it would be an idea to move to pure ESM for v3, like Sindre Sorhus has been doing with his modules:

https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c

@marnusw
Copy link
Contributor

marnusw commented Feb 24, 2022

@kossnocorp it is possible to support native Node.js ESM without breaking changes. I've just done so successfully in date-fns-tz. There are a few things to do:

  1. Change all imports to use the complete file names including the extension, e.g. ./format to ./format/index.js
  2. Add "type": "commonjs" to the main package.json
  3. Add a package.json inside the ./esm folder containing {"type": "module"}
  4. Change the build script so it adds "type": "module" to the package.json of each function in the esm folder
  5. Add the exports field to the main package.json similar to what I've done in date-fns-tz#package.json.

The last will be a proper mess because there are a gazillion files being exported from date-fns, but it should work...

@ocavue
Copy link

ocavue commented Jun 27, 2022

This PR should solve the ESM import for date-fns without bring break changes: #3099

@kossnocorp
Copy link
Member Author

@karlhorky, personally, I'm not too fond of this approach. The only way for us to move forward is to have a dual package. I hope @ocavue's PR will work and the very next version will have ESM support.

@nskazki
Copy link

nskazki commented Sep 20, 2022

Node supports type as of recently https://nodejs.org/api/packages.html#type

@MickL
Copy link

MickL commented Nov 11, 2023

date-fns is not working within Nuxt projects deployed to serverless edge functions (e.g. Cloudflare Workers, Vercel Edge Functions). Can the PR #3099 get merged or is anything missing? It is open for more than a year but I am not sure what is blocking the merge.

Issue on Nitro side: unjs/nitro#1889

@kossnocorp
Copy link
Member Author

Node.js ESM support is coming in v3.

@karlhorky
Copy link

karlhorky commented Nov 13, 2023

Nice, judging by the fact this issue is now closed, I guess v3 will be released imminently (in the next days)?

Looking forward to it 🙌

@kossnocorp
Copy link
Member Author

@karlhorky nice try guilt tripping 🙌 Follow official Twitter for updates https://twitter.com/date_fns

@karlhorky
Copy link

Oh, didn't mean to guilt-trip.

It's just pretty common across open source to leave issues open until they are completed - otherwise, users will have a harder time finding them, may think that v3 is already released and may even open new issues because of confusion.

Anyway, thanks for your effort here!

@MickL
Copy link

MickL commented Nov 14, 2023

He said it is already in main, so thats why it is closed. Lets see when v3 gets released :) I didnt see any info on Twitter tho.

@kossnocorp
Copy link
Member Author

kossnocorp commented Nov 14, 2023

@karlhorky you're welcome!

@MickL, as you might've guessed, I can't promise anything as it's a lot of effort and moving parts. If you follow the Twitter account, you'll know first when I have v3 ready.

@karlhorky
Copy link

Saw on npm that date-fns@3.0.0-alpha.1 was released, in case anyone wants to give it a try.

@karlhorky
Copy link

@kossnocorp Btw date-fns@3.0.0-alpha.1 has some problems with TypeScript types for ESM and CJS, using the "Are The Types Wrong?" tool by @andrewbranch

No types

Import resolved to JavaScript files, but no type declarations were found.

Missing export =

The JavaScript appears to set both module.exports and module.exports.default for improved compatibility, but the types only reflect the latter (by using export default). This will cause TypeScript under the node16 module mode to think an extra .default property access is required, which will work at runtime but is not necessary. These types export = an object with a default property instead of using export default.

Screenshot 2023-11-16 at 10 23 30

@kossnocorp
Copy link
Member Author

@karlhorky thank you for the heads up, but I'm not sure what this all means 🫠 I tested it on a TypeScript project, plus I added smoke tests that builds fine: https://github.com/date-fns/date-fns/tree/main/examples/typescript

But I'll investigate more.

@karlhorky
Copy link

karlhorky commented Nov 16, 2023

Since you're aiming to dual-publish ESM and CJS (which I've heard is challenging to get right when "rolling your own"), you may want to consider trying out tshy from @isaacs to reduce the complexity:

Other recommendations include egoist/tsup, privatenumber/pkgroll, denoland/dnt:

@kossnocorp
Copy link
Member Author

@karlhorky thank you for the suggestion, but the current setup works very well now. Please check it out and tell me if you encounter any problems.

@andrewbranch
Copy link

Please check it out and tell me if you encounter any problems.

This is what https://arethetypeswrong.github.io/?p=date-fns%403.0.0-alpha.1 is doing.

I tested it on a TypeScript project, plus I added smoke tests that builds fine

The grid that @karlhorky showed represents a matrix of TypeScript projects under different but valid (and common) configurations trying to import things from date-fns. Your smoke tests only cover the top-left four cells, which are all problem-free. The rest of the import paths, under the rest of the moduleResolution scenarios, have real problems that real users will encounter as red squigglies. I know it’s a ton of information to take in, but there are thorough docs describing exactly what each of these problems is and why it’s occurring linked in the report that @karlhorky linked. Happy to help advise on the specifics but I would recommend checking those docs out first.

@kossnocorp
Copy link
Member Author

@andrewbranch thank you, I appreciate the offer! It was a challenge indeed to get around all the quirks, given that I had no idea about them before, but now it's all green:

image

Anyone who wants to try, I shipped it as date-fns@3.0.0-alpha.2

@carbdias
Copy link

carbdias commented Dec 7, 2023

Thank you all for the input. So do you advice using v3.0.0.0-alpha.2 to avoid adding to all the imports /index.js ? And other issues (as subfolders that don't have index.js).

I'm having an issue with date-fns/fp at the moment

@kossnocorp
Copy link
Member Author

There's date-fns@3.0.0-rc.2, it most likely will be the final release.

@nskazki
Copy link

nskazki commented Dec 8, 2023

Final as in the last release this lib will ever have?!

@kossnocorp
Copy link
Member Author

@nskazki yes

@nskazki
Copy link

nskazki commented Dec 8, 2023

Thank you for the reply. I’ve looked around for an announcement, but haven’t found any. Should we expect one? Is there a short version?

@kossnocorp
Copy link
Member Author

@nskazki yes, I'm working on a blog post. There's a change log in the repo. You can follow me or the official Twitter account for updates.

@alexander-mart
Copy link

alexander-mart commented Jan 12, 2024

Try to import some FP-version functions from date-fns (version: 2.30.0):

    import { startOfMonth, formatWithOptions } from 'date-fns/fp'

Compile error ERR_UNSUPPORTED_DIR_IMPORT on Vercel:

Error [ERR_UNSUPPORTED_DIR_IMPORT]: Directory import '/vercel/path0/frontend/my-app/node_modules/date-fns/fp' is not supported resolving ES modules imported from /vercel/path0/frontend/my-app/.svelte-kit/output/server/entries/pages/sales-bonus/_page.server.ts.js
Did you mean to import date-fns@2.30.0/node_modules/date-fns/fp/index.js?
    at new NodeError (node:internal/errors:405:5)
    at finalizeResolution (node:internal/modules/esm/resolve:320:17)
    at moduleResolve (node:internal/modules/esm/resolve:946:10)
    at defaultResolve (node:internal/modules/esm/resolve:1132:11)
    at nextResolve (node:internal/modules/esm/loader:163:28)
    at ESMLoader.resolve (node:internal/modules/esm/loader:835:30)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:424:18)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:77:40)
    at link (node:internal/modules/esm/module_job:76:36)
Emitted 'error' event on Worker instance at:
    at [kOnErrorMessage] (node:internal/worker:300:10)
    at [kOnMessage] (node:internal/worker:311:37)
    at MessagePort.<anonymous> (node:internal/worker:212:57)
    at [nodejs.internal.kHybridDispatch] (node:internal/event_target:757:20)
    at exports.emitMessage (node:internal/per_context/messageport:23:28) {
  code: 'ERR_UNSUPPORTED_DIR_IMPORT',
  url: 'file:///vercel/path0/frontend/my-app/node_modules/date-fns/fp'
}
Node.js v18.18.2
 ELIFECYCLE  Command failed with exit code 1.
Error: Command "pnpm run build" exited with 1

@kossnocorp
Copy link
Member Author

@alexander-mart v3 supports Node.js ESM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants