7 ms·
Move on to ESM-Only
- ilrwbwrkhv 2y ago[flagged]
- pfych 2y agoSee this is why I only hire high-quality assembly only developers. Not low-quality C, Python, or Rust developers!
- hombre_fatal 2y agoSounds like the circlejerk mindset I want my competitors to have I just ship code.
- cjonas 2y agoCalling typescript devs "low quality" while also citing python as "high quality" actually made me laugh out loud. Thank you for the chuckle.
- pjerem 2y agoWe’ve gotten this discourse for decades. I remember it being for PHP, Java, JavaScript … in fact anything used in production. It just happens that you get developers for what the market is offering and that the quality you’ve got depends more on experience than anything else. Oh and of course, juniors just learn what can make them land a job. But they are still junior and you still have to manage them.
- airstrike 2y ago> The Toolings are Ready > Modern Tools > With the rise of Vite as a popular modern frontend build tool, many meta-frameworks like Nuxt, SvelteKit, Astro, SolidStart, Remix, Storybook, Redwood, and many others are all built on top of Vite nowadays, that treating ESM as a first-class citizen. > As a complement, we have also testing library Vitest, which was designed for ESM from the day one with powerful module mocking capability and efficient fine-grain caching support. > CLI tools like tsx and jiti offer a seamless experience for running TypeScript and ESM code without requiring additional configuration. This simplifies the development process and reduces the overhead associated with setting up a project to use ESM. > Other tools, for example, ESLint, in the recent v9.0, introduced a new flat config system that enables native ESM support with eslint.config.mjs, even in CJS projects. I think the author and I must have very different definitions for the word "ready"
- vosper 2y agoHow would you define “ready” here?
- paulddraper 2y agoIn my experience, the biggest obstacle to ESM in production systems is every observability/tracing tool relies on require-in-the-middle or in some other form CJS require().
- o11c 2y agoEven "require at the start" (mandatory for transparent polyfills) seems incompatible with the way ESM wants to do things.
- jauntywundrkind 2y agoThey key thing is that require(esm) shipped in node 22, and is being back ported to node 20. Since Node 18 maintenance ends in less than a month, this means all Node versions will have good esm support, including for consuming esm-only libraries (which until recently did not work!) This is noted somewhat in the article, but basically is the whole story to me. Its now possible to stop doing CJS libraries entirely. And with that, I don't see why we would do CJS at all.
- 3np 2y agoThere are still maintained and supported older versions of node.js by the likes of Debian, Ubuntu, Enterprise Linuxes. They backport security fixes and such during a longer extended window but are unlikely to port ESM-require support. It may not be relevant to you and obv nobody's obliging you to also support those users, just saying it's not that binary.
- mattmanser 2y agoIs that really "support those users"? If they need to use a new library version, they can install their own version of node instead of relying on the OS supplied one. All the OS version is doing is supplying the convenience of not having to install it. Or have I misunderstood how those versions of node are used?
- 3np 2y agoSometimes the entire reason why they are still on that older LTS dist is because they still need (e.g.) node 12 for some reason.
- mattmanser 2y agoThat really becomes a "not your problem" as a library author. If a user wants to use an old version of node, they'll have to use an old version of the library that still supports cjs.
- 2y ago
- Klaster_1 2y agoOn a side note, I recently experimented with native TS support in Node.js and it felt like magic: no need for extra flags; debugging and watch just work; types are simple to re-use between browser and server. Erasable syntax seems like the way forward, can't wait for it to land in browsers.
- normie3000 2y ago> can't wait for it to land in browsers Presumably for download size and backward compatibility everyone will still serve JS to browsers.
- eddd-ddde 2y agoBut it'd be nice not to /have to/. Specially when working on new projects with no build step.
- WorldMaker 2y agoTypescript Types don't add that much to download size and generally compress very well.
- madeofpalk 2y agoIt is really nice. I'm glad the Node and Typescript teams finally starting making pragmatic decisions to actually be useful. Now typescript just needs some better defaults from tsc --init to match :)
- Shacklz 2y agoSame here - it's really quite something. The future is looking good! That being said, there are currently still some hurdles. Necessity for explicit file-extensions in the imports is definitely the big offender (it's invalid typescript syntax without the allowImportingTsExtensions-flag). The trend is definitely clear though, most devs want ESM, most devs want types; it's just a matter of time until the ecosystem adapts. I suppose for types to finally land in the browser, TC39 will have to undergo the "progress is one funeral at a time"-principle, which will probably take another while.
- graypegg 2y agoHuh, oddly no mention of native browser support in the form of <script type=“module”> and importmaps! To me, that felt like the last platform to offer ESM support. I also feel like browser support “feels” more official than support from bundlers. Just weird to leave out a mention of that.
- deleted 2y ago[deleted]
- akoboldfrying 2y agoIt's certainly nice, and makes possible Vite's very quick reloads of developer code, but even Vite still makes (ESM) bundles for performance reasons, both for production (with everything, using Rollup) and for dev (with just the external deps, using ESBuild). My understanding is that HTTP 2 pipelining was supposed to make requesting lots of ESM modules from the same site fast enough that bundling could be consigned to history, but for various reasons it didn't work as intended and it was ultimately removed from most browsers.
- deleted 2y ago[deleted]
- dieulot 2y agoHTTP/2 “pipelining” (multiplexing) is still there and works as intended; but bundling is still much more efficient. This article delves into just that: https://csswizardry.com/2023/10/the-three-c-concatenate-compress-cache/ https://csswizardry.com/2023/10/the-three-c-concatenate-comp... The first pair of waterfall graphics illustrates the problem clearly. (What you vaguely remember as not working as intended is probably Server Push).
- chrismorgan 2y agoHTTP protocol changes were never, ever, going to make bundling unnecessary. No one actually involved in the things said it would, or thought it would. It was less-deeply-involved people misunderstanding things that led to that popular impression. HTTP/2’s better multiplexing helps a little, but you’ve still completely got the waterfall problem: so you have at an absolute minimum of overhead the dependency graph depth times the round-trip time—frequently multiple seconds. HTTP/2 Server Push could have improved it in some regards, as it can in theory break out of the waterfall problem, but in practice it would have required much more complex servers, and was missing important pieces so that it was completely useless anyway (a way for the client to tell the server what resources it has cached), and they eventually just removed it all round rather than inventing and implementing the missing pieces, with which it still would have been a good deal less efficient to execute than bundling. Minifying and bundling is just better, no matter what.
- deleted 2y ago[deleted]
- porridgeraisin 2y agoAny kind of migration breaks code. Every single line of practical code hit by a breaking change should be considered a bug. Before the security theater takes the stage, let me clarify by saying that I don't mean we should not have breaking changes at all, but that only by explicitly treating them as serious bugs, can we even hope to set up a process to minimize them. Of course, the minimization objective will have multiple other variables -- security being one of them. Therefore, when it is possible to not break practical code, it should not be done. This is the "linux philosophy", if you will. Among JS runtimes, Bun is a great example. In bun today, you can, in the same file (!!), with zero code changes, 100% transparently: 1. require() a module regardless of whether it is cjs or esm [1] 2. synchronously `import` a module regardless of whether it is cjs or esm. 3. do either of this with typescript or javascript Some of these required changes in JavascriptCore, which were implemented - it's good to see a lack of cribbing about "it needs to be supported in upstream" and a focus on practical end-user usage. Any runtime/kernel that doesn't put this level of effort into not breaking code is just not serious. While Node is at least moving in the right direction, supporting require(esm) with some restrictions, Deno is completely hopeless - CJS code is completely unusable on Deno. The reasoning is crazy too - how does it matter if ESM is the "standard", if millions of lines of practical, real world code is using CJS? It does not matter that popular libraries move to ESM. Even a single internal tool that's locked into CJS for some reason means that a project cannot move away from it easily. Then like someone mentioned below, many "plugin architectures" and "command architectures" are pretty much locked in to require(). The whole Deno project screams "ideology > pragmatism". Hopefully, just like they came to their senses w.r.t node compat [2], they implement CJS interop as well. [1] You cannot require() an ESM module that uses top level await [2] In contrast, bun's node compat story is very good, they run the Node.js test suite on every commit to Bun, and pass a huge majority of the test cases. Track the progress here: https://bun.sh/docs/runtime/nodejs-apis https://bun.sh/docs/runtime/nodejs-apis There is even some effort put into V8 APIs(in a JSC runtime!!). This helps with using Bun with the usual debugger in the chrome browser/VSCode, modules that use `node:v8`, etc,. Read about it here: https://bun.sh/blog/how-bun-supports-v8-apis-without-using-v8-part-1 https://bun.sh/blog/how-bun-supports-v8-apis-without-using-v... There is also compat the other way - there are the beginnings of node/browser polyfills for Bun-only APIs: https://github.com/oven-sh/bun/tree/main/packages/bun-polyfills https://github.com/oven-sh/bun/tree/main/packages/bun-polyfi...
- shpx 2y agoVS Code still doesn't support ESM in extensions, you have to transpile to CJS. https://github.com/microsoft/vscode/issues/130367 https://github.com/microsoft/vscode/issues/130367
- mdhb 2y agoAs a side note it was so depressing reading the release notes of the latest VS Code. It was all just more and more AI slop related nonsense. You could feel the enshitification happening in real time. I don’t think there was a single new feature in there I was even remotely excited about.
- Sloowms 2y agoECMAScript modules
- bilalq 2y agoThe way this cutover is being handled is reminiscent of Python 2->3. To this day, I still run into compatibility issues between things that only work with ESM and things that only work with CJS. It's frustrating, to say the least.
- notanaverageman 2y agoMeanwhile I'm trying to adapt ESM only packages to CJS since Goja (JS runtime library for Go) doesn't have ESM support. [1] And yes I know that Grafana has a fork called Sobek that has ESM support, but it is tailored for k6 and they don't have plans for making it easier to use. [2] [1] https://github.com/dop251/goja/issues/348 https://github.com/dop251/goja/issues/348 [2] https://github.com/grafana/sobek/issues/49 https://github.com/grafana/sobek/issues/49
- jakub_g 2y agoDid anyone make a large TypeScript codebase work with ESM + TS + node (together with IDE support and yarn pnp support?) The thing that is annoying with ESM is that it requires to have extensions in imports, i.e. `import .. from '/foo.js'`. This gets messy with TypeScript, where your files are named `foo.ts` but you need to import `foo.js`. The previous "best practice" in TS world was to have extensionless JS imports, so this move would require a massive codemod to update all imports in an entire codebase. For now, we've been using `ts-node` with swc under the hood, but without ESM. I tried `tsx`, but the compilation time of esbuild is way too slow, some of our node CLI tools written in TS take 15s to boot up, which is not acceptable (with `ts-node` it's 3-4s) (tbh, it's probably partly a fault of our CLI framework, which crawls all workspaces to discover all CLI tools, and as we have a lot of them, tsx has a lot of useless work to do).
- gauben 2y agoHey! Not sure how modern your codebase is, but you can consider the following tsconfig settings: - rewriteRelativeImportExtensions: this will allow you to write `import foo from './foo.ts'` and have tsc transform it to `import foo from './foo.js'` - erasableSyntaxOnly: this will error on non "erasable" syntax, that is, TypeScript code that has a runtime output (e.g. enums) With these two settings enabled, you'd be able to run TypeScript code directly with Node: `node src/index.ts`, and cut boot up time substantially
- hombre_fatal 2y agoTo add, those are the recommended tsconfig.json settings in Node's docs on native TS stripping. Here are the rest: https://nodejs.org/api/typescript.html#type-stripping https://nodejs.org/api/typescript.html#type-stripping
- WorldMaker 2y agoAlso there are eslint rules older than erasableSyntaxOnly that can also be useful in doing a "rip-the-bandaid-off-refactor" using all the lint warnings/warnings-as-errors to add extensions everywhere in the case where your brownfield also needs to be a version or two behind on Typescript.
- sarreph 2y ago> Although a significant portion of packages still use CJS, the trend clearly shows a good shift towards ESM. Does it? The chart being used in the opening argument is far from compelling. When I hold my phone sideways, it looks as though the ESM portion is plateauing or feebly (at best) increasing. Maybe by 2040 we’d see widespread ESM adoption? Jokes aside, I prefer ESM (and would prefer if everyone else preferred it), but leading with adoption rates is weak sauce.
- codedokode 2y agoI am surprised they still use outdated syntax when there is a standard for modules. Also, it is much better when you specify full path to the file and do not have to remember the resolving rules. Also, last time I tried to use ESM in a browser with Vue and unpkg without builders and web server, it didn't work (probably because one cannot import modules from a local folder). I wish support for ESM and localhost was improved also. I don't want to use a webserver or a bundler because it is easier without them so I switched to legacy scripts without modules.
- tpm 2y ago> one cannot import modules from a local folder Pretty sure this works and it is indeed possible to use ES modules without builders and a webserver, I recently rewrote a Node app this way (with Claude's help even because I'm a ES noob). No idea about Vue and unpkg though, there could be an issue with that. edit: eh you mean like "import 'file://module.js'", but I don't understand why would you need that when you can use "import './module.js'"
- codedokode 2y agoDoesn't work in a browser [1]: > file: URLs are supported by many non-browser runtimes such as Node, since scripts there already have file: URLs, but they are not supported by browsers due to security reasons. If you open HTML file directly in a browser, it cannot import ES modules from a filesystem. It can import legacy scripts, but they, as I understand, cannot import anything at all. [1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
- tpm 2y agoYou don't need file:// module URLs when you say open a index.html from your local drive through file://C:/index.html but then in that index.html you have a 'script type="module" src="src/index.js"' and from there you go through usual relative paths without protocol. This works in Firefox, I have one project open like that right now. Chrome blocks that because of their CORS policy, but that's another issue, can be mitigated by some commandline options (--allow-file-access-from-files --cors-exempt-headers "*")
- plopz 2y agoThe main problem with es modules is mocking in tests. How do people work around that issue?
- codedokode 2y agoYou don't use modules as a replacement for DI?
- giorgioz 2y agoYou either use Vitest for new projects or you use jest.unstable_mockModule for old Jest tests
- WilcoKruijer 2y agoDefine an interface, mock the implementation. How people outside of JS/TS have been doing it for years.
- patwolf 2y agoI was working on a legacy CSJ project, and I tried to upgrade an OIDC library, but the newer version would only work with ESM. I decided to use that as an excuse to migrate our project to ESM. However, I hit a bug using dd-trace with ESM. Over a year later, that bug hasn't been resolved. I try to use ESM as much as possible for new projects, but it's not always simple to migrate existing projects to ESM.
- darepublic 2y agoAll these new bundling libraries (vite/rollup) always claim to just work, chefs kiss, 100 emote. And then you actually try to use them for basic use cases and you find yourself googling or knee deep in the documentation. If at all possible I try to avoid bundling libs altogether. That's the future I want. No more vite or rollup or webpack.
- thiht 2y agoUh? That’s completely alien to my experience with Vite. Setting up a Vite/React/Typescript project with Tailwind/Tanstack Query/Tanstack Router is an absolute breeze, you just follow the docs. Adding ESLint/Prettier is also just following the docs. What problems did you encounter specifically? Did you report them?
- winrid 2y agoVite is probably the only one that just works? If you follow the first 3mins of Getting Started it works great.
- eternityforest 2y agoMy experience with Vue/Vite is in fact chef's kiss 100 emote. I would not want to set up a new project from scratch myself, but with the templates it works great, as long as you don't have to do anything outside of what they want you to do.
- bhouston 2y agoI've been ESM only for the last 2 years and it has been amazing. Now to be fair, I am doing it on new projects so that probably simplifies things, but it is very freeing and performant.
- Sephr 2y agoTo achieve an ESM-only future, we can't have features that only work in non-ESM. Browsers don't support synchronous blocking loading and execution of ESM scripts.