-
-
Notifications
You must be signed in to change notification settings - Fork 160
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
Migrate to ESM-first #608
Comments
I'm personally very pro-esm, and umzug is one of those libraries I think could be fully converted to ESM (dropping support for CJS) without being a huge problem because it's often used indirectly. The sequelize cli will be undergoing a complete rewrite in ESM, so umzug going ESM would not be a problem for the cli team. That being said, umzug can be used with ESM, but you need a custom resolver to replace the default resolver: https://github.com/sequelize/umzug/blob/586675894c3b099bb50ad2f07e46d89277ee29bb/examples/2.es-modules/umzug.mjs I would argue that, at a minimum, the default resolver should be changed to use a dynamic |
I don't want to drop commonjs support, but yes, I agree that esm should work out of the box, although as @ephys mentioned it does work already with a little extra work. For the current major version, it would probably need to be limited to looking for a .mjs extension. In general, I want to make sure umzug stays framework agnostic and unopinionated - sequelize is an important consumer but not the only one. |
Absolutely, please take my comment as coming from a user of umzug that pushes for ESM but is unrelated to umzug even if we're in the same org |
CJS is natively supported by ESM, the opposite is not true. This is due to the asynchronous nature of ESM. |
By "drop support for CJS", what we mean is that CJS codebases won't be able to Dynamic import is available to both CJS and ESM, so we can support ESM migration files without dropping support for being imported by CJS codebases by replacing the dynamic But doing this is indeed a breaking change, because hooking |
I see, you mean that |
I would like umzug to take a side in the holy war of support-commonjs vs don't-support-commonjs, but not in the holy war of esm vs commonjs - esm is almost certainly the way of the future, but some OSS maintainers don't want to support developers who live in the present and are stuck with commonjs. I do want to support such developers, partly because I'm one of them in my day job. It shouldn't be too hard to support everything. We can start using microbundle or similar to compile the package, so it has a commonjs and an esm import option. And we can pretty easily add support for .mjs in the current major version. If someone wants to open PR(s) for either of these things, feel free to. Otherwise I will aim to do it some time in July. In the next major, we could default to assuming .js is esm instead of commonjs and look for .cjs for commonjs. But I'm in no particular rush to make that change. |
I very, very strongly recommend that you do not provide separate builds for esm and commonjs. That inevitably leads to issues as both version end up loaded in the same application but are incompatible with each other. I opened yet another bug report about this today in Apollo server. If you want to support being imported by both cjs and esm, write the library in cjs and provide an esm wrapper that declares the named exports. If you need a real life example, look at how Sequelize 7 handles this. You also don't need to assume anything regarding whether
Users could have require hooks to run the file through something like babel or ts-node at the time it gets loaded |
This is pretty close to the status quo already. Despite it being mentioned earlier in this thread I forgot that we have an example of using esm, both for the I see this issue as a feature request, to make the above scenario boilerplate free (ideally, no need for
You are probably right - there may be no need for microbundle (partly because umzug in general doesn't need "bundling" anyway), and a (Re the issue you opened, I'm guessing you're referring to this one? This is helpful, thank you!) |
I have been bundling my code and libraries at work for both ESM and CJS for years even on projects with hundreds of files without having any issue. May I suggest that the libraries you are having issues with may not know how to bundle ESM and CJS in different exports?
It is impossible to support every niche use case. Production should be the target and I sincerely, deeply, profundly hope that nobody is running
I don't believe that to be a proper solution. This is how we end up having so many libraries still written in CJS in 2023 because people do not want to move forward. I'll let you people decide how you want to handle this situation as we seem do have relatively opposite views on the matter. If you want help to migrate to ESM, I'll gladly help you. 👍 |
Please see https://nodejs.org/api/packages.html#dual-commonjses-module-packages, and apollographql/apollo-server#7625. This is a very real issue, you just haven't encountered it yet.
That's still a breaking change, and should require a major release
If we want to support both CJS and ESM, it is our only option. I don't understand why it bothers you that the library uses CJS internally if it has no observable impact on you as an ESM user. The only people it impacts are the ones maintaining the library |
Searching on current status of ESM support at umzug I found this discussion. Just dropping my 2 cents: in a full ESM project, using top level await, running migrations with umzug fails because it is CJS.
That is a bummer in 2023. One vote for ESM. |
Sorry, I forgot to answer you when I read your response.
I see no issue with major releases.
CJS is more a reflection of a refusal of change. Every Node.JS developers knows (or is lying to themselves) that CJS will eventually disappear. Maybe not in the following years but it is bound to disappear. I will never understand engineers or anyone involved in science that simply pushes back against progress. Aren't we supposed to be the one pushing progress? To me, by hard-rooted in CJS and refusing to change is not a good sign for the future of the library. It's not like ESM was released yesterday, it's been over 7 years now. I just want to emphasize that I am not meaning any harm or offense here. I am just voicing my disappointment in the JS community overall that happens to be somewhat reflected here. |
Released (as |
@SmashingQuasar I am hopeful that #613 is a satisfactory solution to this. It's worth noting that it's only possible for #613 to solve the use-case here without breaking others' use-cases by not migrating to ESM-first. (Hence the title "ESM support" rather than "ESM migration"). It's worth reading @ljharb's comments in eslint/rfcs#88 which IMO articulate why well. As the maintainer of umzug (a package) - I think sticking with CJS is the right call. Nothing about that decision prevents you, a user of umzug (and presumably maintainer of an application) from modernizing to ESM. That eslint RFC also covers the (non-)benefit of applying @ljharb sorry for the @ mention out of the blue, no need to respond! |
Closes #608 This adds some esm-vs-commonjs "smartness" to umzug: 1. use `require` for `.cjs` migrations and `import` for `.mjs` migrations (and their typescript equivalents) 2. use `require` for `.js` migrations _if_ `typeof require.main === 'object'`, and `import` to `.js` migrations otherwise 3. use the same criteria to create (c)js vs mjs templates when creating migration files 4. add `"moduleResolution": "Node16"` to tsconfig.lib.json to make sure `import(filepath)` doesn't get transpiled into `__importStar(require(filepath))` (see [here](microsoft/TypeScript#43329 (comment)) and [here](microsoft/TypeScript#43329 (comment))) Tests/examples: - add a `vanilla-esm` example to make sure using `import` / top-level await works - add a step to the `test_pkg` job to make sure vitest isn't hiding gnarly import problems - this is installing the compiled library as a `.tgz`, and with no other dev/prod dependencies like vitest or ts-node having been installed, so should be very close to what end users will do Didn't: - add a wrapper.mjs file in the compiled folder as suggested in #608 (comment), mostly just because it didn't seem to be necessary? It seems to work fine when imported from an ES-module, using top-level await, etc., even though umzug is itself a commonjs module. <details> <summary>original body</summary> ~Related to #608 - although does not close it.~ ~This adds built-in support for `.mjs` and `.mts` files. `.mjs` should "just work" - write migrations as ESM modules and they'll be imported in the right way. For the current major version, `.js` will continue to be assumed commonjs. ESM-fans will just have to type that extra `m` in their filenames.~ ~This PR _doesn't_ add a wrapper file so that the umzug library itself can be imported as an ES module. That can be done in a follow-up PR. In the meantime, ESM users can use `createRequire` as in the [existing ESM example](https://github.com/sequelize/umzug/tree/main/examples/2.es-modules).~ </details> --------- Co-authored-by: Misha Kaletsky <mmkal@users.noreply.github.com>
Released in v3.5.0. |
Hey!
So this may seem like a feature request, but it actually falls under the bug category in my opinion.
As of today,
umzug
is written and built in CJS.The problem is, this breaks applications written in pure ESM because
umzug
is using a dynamicrequire
.This problem is currently affecting several ORMs (including
sequelize
).I think migrating to ESM-first is necessity since ESM supports importing any kind of module unlike CJS.
I am willing to write a PR to that effect if reviewers are available to check it.
This will obviously create many changes within this dependency. It should not, however, create any breaking change.
Let me know if you are willing to migrate and if you want a PR implementing this change.
The text was updated successfully, but these errors were encountered: