Copy of Anthony Fu === Paul: [00:00:00] Hi there, my name is Paul and joined with us is Anthony Foo. We've had Anthony on before and we're having him back again because we had a great conversation last time. Today we're gonna dive back into ~the ~the guttural depths of JavaScript. Specifically, we're going to talk about his recent blog post moving to ESM only, excited to dig in. This will probably be a spicy one. Welcome to the podcast. Anthony. Anthony: ~Yeah. Um, ~Thanks for having me. Paul: Yeah, it's going to be a,~ um, you know, ~like I mentioned, I think this might be a little bit of a spicy one because there are some folks that are purists with the old way, the JavaScript. Can work and there's people that are open to embracing new things. This has been a big point of contention. Some libraries, some frameworks not working with one another. So the blog post is titled moving onto ESM only, so What is esm if somebody's listening and they're newer to javascript? What is esm and then let's you could just hop right into what made you want to ~like ~write this blog post and Start shifting the perspective in your motivations Anthony: ~Yeah. All right. So yeah, ~ I'm actually a little bit hesitant about ~like ~[00:01:00] writing this blog post because ~you, you know, like, I mean, I mean, ~I know this is going to be very ~like controversial, ~controversial. ~It's like. It's a, ~it's a little bit harsh topic, indeed. So, about ESM, ~it's like, uh, ~it's Emacs script module. ~So ~Emacs script is actually ~the, ~the formal name of JavaScript, because JavaScript is actually ~not, uh, I mean, it's ~a trademark,~ uh, by, or, ~so ~it's like, ~we couldn't use that name. ~So, ~actually, JavaScript is actually called ~ES. ~EMAC script, which is ~uh, ~ES and so ESM stand for emac script module, which is a standard module format ~to ~in the JavaScript ecosystem. While the other thing is called CJS, which is common js, it's something like people doing. ~Uh, ~to require modules before ESM was a thing. ~So ~this is like mainly introduced by Node. js and a bunch of things. So that was a kind of ~like ~de facto standard,~ uh, ~back the time. ~Uh, ~where ~that ~JavaScript ~doesn't, ~wasn't designed for being modular at all. So now with ESM, it becomes a standard, which is actually, ~it's ~hard to imagine. It's already over a decade,~ uh, ~since this standard comes [00:02:00] up. ~Well, that's, ~we're still ~like ~fighting against CJS and ESM, and the whole ecosystem is still adopting to it. Paul: you think that ~um ~oracle will never sort of ~uh ~budge on their trademark there and Anthony: Yeah, I don't Paul: I know there was something that came up ~kind of ~last year, right? About them getting challenged on this. The time of this recording is,~ uh,~ March, 2025. Anthony: Yeah. ~I think, ~I think right now is still not really progressing ~from my, like,~ from my radar, it's just ~like, ~Dino is trying hard to ~kind of ~make these for the community to ~kind of, ~let's get back to the name because JavaScript becomes a term that's already used. It shouldn't be a trademark that's doesn't have any effect. ~Right. So, uh, ~but I think for the Oracle side, it seems to be a little bit, I don't know, ambiguous. It's ~like, ~just, you don't know what's their attitude about it. ~So. ~Yeah, for now that's still quite ESM. I don't know if someday we can call it JSM something,~ but,~ but we'll see. Paul: Do you think that,~ um,~ this sort of divide between ESM ~and, ~and the common JS and classic,~ uh,~ formats you might see have [00:03:00] caused any sort of stiflement in these JavaScript ecosystem? Cause you could also argue that the. bifurcation of two different ways or a few different ways to include other packages ~and ~and essentially deal with modules ~in your ~in your code. Those several different ways have ushered in More creativity, more work to be put into writing libraries and stuff. ~But you know, ~the low hanging fruit is no, it's not good. ~And it's, ~and it's causing rigidity in the way that we assemble our applications. So curious on your take there, global Anthony: I'm actually relative young ~in the, in, ~in this ecosystem. ~Uh, ~when I starting to get into ~this, ~this word, I think ESM is already something that people discuss about, but I know that,~ uh, but I, I don't know the full detail, but I know ~before we have more formats. Even more, it's like AMD, UMD, IIFE, something like that. It's just like people trying to, because there's something missing and there's no standard for it. So like people trying to invent things and trying to build conventions. And also you have JavaScript working in the node and working in the [00:04:00] browser, different, totally different environment. And. So the context is different and something like that. So like UND is like trying to be like universal. It can ~like ~act as a IFE in the browser while that's being requirable as common JS in Node. js, something like that. ~I mean. ~I guess that at that time that would be more chaotic, but right now, I think the same is like, because ESM is actually the standard and the only standard of JavaScript. So I think that's something that's everybody is a great sound to ~kind of ~move forward to the standard. ~And, ~and then ~like, ~we can see that still ~like. Uh, ~people are starting to moving to ESM. ~Well, ~that's still ~some, ~some part of ~like ~CJS is still remaining mostly because some of the package that didn't get updated at all, or,~ uh,~ there is some like compatible concern. It's just ~like, ~because if you change CJS to ESM, because the format is different. So there'll be a breaking change and that can break people's code or they will never upgrade. Paul: Do you think that developers who are very tied [00:05:00] to CJS or developers who are maintaining,~ uh,~ packages and libraries that might be based Are they going to just need to bite the bullet and get used to ESM? Do you think this is something that is going to cause a certain population to be left behind and be permanently fragmented. That's something that's totally happened in, in land before, where there's just like a cohort of folks and they say, ~you know, this is, ~I think this is just how we're going to do it. And then you end up having two different things living forever, which is ~kind of ~what we have now. But looking, long term sort of ~your, ~your vibe check on the ecosystem surrounding this. Anthony: Yeah, I think indeed there is a like multiple voice, like different direction, different concern, but I think in general, like people are positive about moving to ESM, but it's still ~like, ~it's a calculation between like trade off, right? It's like the cost of migration, the cost of ~like ~breaking the ecosystem over like the benefits ESM [00:06:00] could get. ~So, uh, ~I think for like front end frameworks or front end libraries ~that ~that could be like more. ~Uh, more like ~beneficial by moving to ESM because you got ~like ~static analyzed, tree shaking or something. So you can ship less code ~to, ~to the browser where that's like the code you don't, you will never go into is good that you can, they can be removed while the CJS, like the tree shaking, it will be like way harder and. Also less accurate, but also like on the other hand, like some package were never designed to be shipped into the browser. Like some Node. js packages, like they're designed to ~kind of ~write the files, like accessing to the file system or accessing to the IO, which they don't get a direct benefit of moving to ESN because CGS would work. So that's something, but ~I, ~I also don't think that's a, like two. Distinct word between ESM and CJS because now ~ I,~ you can interop between CGS and ESM, so ~you can have, ~you can have an ESM package that's requiring, or depending on a CGS package,~ that's, ~that's [00:07:00] totally fine. Most of the time you don't really notice that ~if, ~unless you dig into the code.~ So, but on the other hand, I think before like that was, uh, ~the trickiest thing is ~like, uh, you couldn't, ~you could use CJS inside ESM, but you couldn't use,~ uh, ~ESM inside CJS. So ~in a, ~in a CJS module, ~you couldn't, you couldn't, ~you couldn't import an ESM because ESM is naturally asynchronized. It's designed to be asynchronous because it was designed for JavaScript and JavaScript mostly runs on browser and we're requiring a file. Usually the browser needs to do a network request. So that's network request can take time. ~So, uh, ~naturally ESM is designed to be asynchronous when you import a file. ~What does ~What does CJS require? Require module, which is designed to be sync. So then,~ like,~ the two things are incompatible.~ So, um, ~that ~thing's ~changed until very recently, ~that ~Node. js is starting to ship required ESM feature. ~So ~that allows you to require ESM if there is nothing in the module tree that is async. So node can kind of block the thread or something to work that way. ~So ~that allows you [00:08:00] to import in ESN in CJS. ~Uh, ~so that's make this like a blend between like switching between these ~two mode, ~two module system, a lot ~more ~easier ~than, ~than before. So that's also one of the reason I think that's probably. Should be the time for us to move forward to ESM because there is ~some push, there are ~some pushback or some concern like preventing us from moving to ESM when it's like, you couldn't use ESM in CJS, but now you could, ~I mean, uh, I mean, ~after ~two months, like ~two months when ,~ uh, ~node 18 gets,~ uh, ~end of life and then ~like, yeah, Uh, the latest patch, ~the latest patch of ~20, uh, ~version 20, 22, ~they all get, ~they'll get this ~like ~require ESM feature. ~So, ~after two months, ~like all the ever, like ~the, ~it's like. How to say ~long term support node version would get this feature. So library author could more ~like ~confidently dropping CJS and for people to ~kind of ~migrate to ESM. Paul: Would you say that in general, a developer who is maintaining an open source package would end up spending less time maintaining [00:09:00] their work if they were to migrate from either a hybrid or a CJS codebase into ESM? Because, hey, do it now. You can go both ways, require both ways. And now you don't have to maintain ~two different types, ~two different areas of pluggability. Anthony: ~I'm sorry. Uh, yeah. So, I, I mean, ~before actually moving to ESM only, there's also approach that's like you mentioned hybrid,~ uh, ~we call dual module. Do module means that you ship CGS and ESM at the same time with different entry. So nodes would actually smartly detect who is going to using it. So if you require a module and this module provided CGS version. You're going to use the CJS version, and if you import a module,~ uh, ~using ESM, ~so ~it'll use the ESM format. ~So, ~that's something like you could supporting the DAX usage and the new ESM usage at the same time. ~Um, ~so ~that's the, ~that's the trade off ~like ~a lot of libraries are doing. ~Uh, ~right now to ~kind of ~supporting ESM while ~like ~being [00:10:00] backward compatible. ~Uh, ~but yeah, that's the thing that I'm trying to ~even ~push ~it ~harder a little bit to say ~like ~we can go ESM only now because you don't need to maintain. ~To ~version because of you, we have required ESM and also ~the tooling, uh, the, ~the top level tooling that consume the code,~ uh, more, more, ~more and more ~that ~they support ESM natively. Paul: What's one of the biggest pains you see developers facing when they have to maintain this dual format package? Is it just work? ~Is it, ~is there a larger bug spread typically,~ um,~ that might be a stain? ~You know, ~like a big red X on some dual format packages,~ like,~ hey, You don't know what's in here. ~Uh, ~yeah. Curious how that particular checkbox of it being dual format might affect what you're using Anthony: Yeah. ~Right. So, um, there is a, ~there's a bunch of tool that's kind already helping that. So you just like, for example, like on build or TS up. They all offer like dual module outputting. So basically the common practice is like you authoring your code ~in, ~[00:11:00] in ESM and then ~you use a, ~you use a build tool ~to ~to bundle your app, ~to bundle, ~to bundle a library, and then you can ~like ~to do a TransParenting and to convert ESM to CJS, which is, ~I mean.~ Easier because ESM is,~ uh, ~it's ~like, uh, ~static and analyzable. What does CJS will be harder. ~Uh, ~so ESM is easier to convert to CJS in that case. So there's a tool that's already making is very simple. It just. Format, colon, and then an array, you put ESM, the CGS, it will output two formats. And so in terms of ~like ~authoring experience, I think that should be fine. ~And ~I think ~the, the, ~the challenge becomes to be like ~the, ~the distribution or like shipping,~ how, ~how you export,~ uh, this, ~this library, ~like as a. ~As an MPM package to ~kind of ~have two entry while that conditionally, so ~there's a, ~there's ~like ~some tricks or some article to explain these things. So ~if you know, well, ~if you do, ~do, do~ it very carefully, you should get it right. But ~what ~I think that's the most challenging part is ~like. ~Fundamentally, CJS and ESM are designed different. [00:12:00] So ESM has a default export and NAND export. So that means a module could have multiple, it can export multiple functions, or it can export multiple objects. While ~that's, ~CJS have only one export. And that exports, usually people export ~an object, ~an object with the keys of ~the, like, ~some functions. But, There's ~a no defaults, uh, there's a ~no defaults export in CJS ~or, ~or the object itself is export. So that depends how you think it,~ uh, either, ~either you have only defaults or only named, but then ~like, ~it doesn't mapping into the formats, the exports ESM has. So that becomes the challenge because,~ uh, ~when you ~kind of ~export default and function, ~and then ~how do you present that in CJS? So usually you export an object with default key as the function, but then it has a conflict because usually when you import that module in ESM, you get the function. But when you require [00:13:00] that, then you get an object with the key of default. So then you have the interrupt. So usually what we do is ~just we ~check if there is a default key in the object. And ~if you, ~if we do. And ~we got a, ~we got a key of it. So that's a little bit dirty and also depends on how you export to the users. That can be a little bit tricky. Paul: Are there any other areas of uncertainty or ~like hack ~hacky ~sort of, uh, ~connections that need to be done in order to bridge the ESM world to the CJS world? ~up the same alley.~ Anthony: ~Yeah, I think, ~yeah, ~I mean, ~there is also like some problem like types. So ideally ~you should have, ~you should expect the same type. It's actually because CJS and ESM expose differently. So the type is actually different. So you basically need to duplicate your. Types into two file. And you know ~that's, ~we have ~do ~do JS as a file extension. And then because of c js and esm, now we have DO CJs and do mjs ~and like ~as a file extension. And for type three usually you have a type definition file called do D Ts. [00:14:00] And now with that you have D cts and D mts. So that's ~a. ~Very tricky and then usually you need to ship ~like both like ~all three of them in order to get these things, right? So yeah, that's a lot of things ~to to kind of ~concern and also because of that sometimes when you're shipping it You don't even notice until you and your user ~can ~consume it So it's really hard to do the test because that's not part of your logic That's part of ~like ~the integration or ~like ~how you compose this package. So that's A risk of ~like ~a wrong time error that's, you couldn't catch ~with a, with a ~types score, with a linker. Paul: If you're thinking about your end user experience here and you're assuming the maintainer of a package right or some library ~um,~ Anthony: it's ~the, ~the consumer of the library. Paul: the Right the consumer ~in ~in this scenario that we're talking about, right? ~um, ~but on the other end of the stick like if you're the person who's watching your consumers Using your library or using your code. ~Um, ~and [00:15:00] you want to think about switching to ESM. What are some of the things you think would go into assessing if that's the right time for your code base, for your repo? ~Like, ~is there ever a scenario, Anthony, where it's just so much work and not worth it, that you just would prompt a full rewrite, or do you think in general the tooling? And what's out there for maintainers is sufficient no matter what to ~sort of ~tackle this. And are there any other things you would look at when examining a open source piece of code, or any code for that matter, that makes you say yes,~ like, don't. ~Don't do all the work to put this into ESM. It's not ready or it's not the right time. Anthony: ~Do you, ~do you see that being a reality at any point? I think it depends, indeed. Depends on what stack ~your, ~your project is using. And if you are using like,~ uh, ~I don't know, latest. Libraries, latest framework, most of them are now built on top of Vite and the Vite is ~like ~designed for ESM ground up. Anthony: And that's ~kind of ~the fact that [00:16:00] allows you to ~kind of ~use any ESM library you want. So ~that, ~that should be fine, like for your library to be ESM only. So I think ~that ~the top level tooling are catching up ~while that's, ~if you're ~kind of ~still on Webpack 4 or something, that would be a little bit challenging, ~I guess.~ ~So, um, yeah, ~but I think ~like ~if we're ~talking, ~talking about Webpack, then we're probably talking about ~like ~front end project, right? So then,~ um, ~if your build tool doesn't support ESM, Which means they'll be ~very, ~very old. ~I mean, ~the automotive tool support that. So you should probably ~cons ~consider ~like ~upgrading ~to the, for, for your, ~for your build tools ~first ~or for your bundle first. And ~then, ~then you can be ready to adopt ~to ~e sm. ~And, ~and I think on the other hand, ~like if you, ~if you're talking about ~like ~no js, ~like ~applications, like a backend or something, or like a COI or script something. Then we require ESM, that's ~a, ~a feature ~like ~shipping the latest node. That shouldn't be a concern. Then you can use ESM and CGS interchangeably. You don't really need to concern about that. ~So, um, ~yeah, I think the [00:17:00] only case ~you, you, ~you'll be trapped in CJS. That will be, you're still on a very legacy,~ uh,~ view tool, which hopefully nobody has that issue right now. Paul: Yeah. And that's also interesting where it's ~like, ~if you are in such an old build tool,~ go, ~go do that first. ~That's, ~that's probably more important. And then. No matter what, it might be a good time to transition over to ESM if you're a developer. ~Um, ~let's say you're looking through your packages as a developer and tools that you're importing and using. ~Um, ~you might benefit from knowing how they're written, right? And how they're structured. And you have the Node Modules Inspector,~ right,~ Anthony? What is that? How does it work? And how do you hope people will use it to bring value to themselves and their team? Anthony: Yeah. So initially I come out with the idea, like I want to check ~how, ~how many packages in my node modules are ESM or Cjs. So basically I want to know my dependencies, ESM adoption. So I know who is still lagging behind and if I could help them or not, or if we [00:18:00] can, like moving on. To an authority or something. ~So, ~I want to check in that. And I will first link building a CLI to present it. I find, oh, actually there is way more data to present. And CLI is not a good interface to present this complex data. ~So, ~I end up with a UI. Like a front end UI, like you will send the data, ~like ~parse the data of your node modules, the whole tree and the whole relationship to the front end, and the front end would use like a graph library to show the relationship with ~Each, ~each dependency, each package. So you can search for a package to know why you have that package and who is depending on that and the worst version you are on and how old these dependencies are. And I actually find ~my, ~my oldest dependency in my node module is actually over 12 years. So that's a little bit scary in a way with the tool, you can see that. Paul: And it graphs it all out ~sort of like in ~like an obsidian format almost like a tree. Anthony: ~I mean, ~right now it's in its own, like UI and [00:19:00] it's interactive. You can search, you can filter something like that. But yeah, I think maybe I could ~like ~figure out like a better presentation for ~like ~API usage. So maybe you can gather data and then you can render it yourself,~ uh,~ in a way you want to do it. Paul: Where can people find this tool and is it called the node modules inspector? Is that like the proper name for it? Anthony: Yeah. ~If, ~if it's on NPM is no module inspector with stash,~ uh, ~in between, or I have a deployed version, it's like nodes. Dash modules dot dev and you can ~like, it's like, ~it can, you can run,~ uh,~ install in your browser and then you can get the tray of it and you can inspect it. Paul: Nice. Do you,~ uh, ~plan to use this for security purposes at all? ~Uh, ~naturally being able to inspect your packages and find one that's 12 years old is very useful. And that's almost security related. Do you plan on ~like ~developing more on this, adding more in any way? Anthony: Yeah, I think right now the project ~is, ~is ~kind of ~adopting very fast because people are sending PRs and throwing me ideas. So [00:20:00] I recently add like a deprecation window. So like you can know ~that's ~which packages or which versions are being deprecated and their deprecated message. It's more ~like a ~intuitive rather than ~like a, ~a red message ~in ~when you install it. So now you can see ~that ~why you have that modules or something. ~So, ~yeah, in terms of security,~ uh, ~I don't know exactly how to do that, but ~I, ~I think I probably could ~have ~fetched some ~like a ~security database to know which version is in invulnerability and we could present it for sure. And also that ~also ~depends on. ~Like ~not every vulnerability is relevant to a project, even if it's in your dependency. If you don't use that feature, that's not relevant to you. ~So, ~yeah, ~I mean, you, ~you give me a great idea and I could probably ~kind to ~see ~that's ~how we can bring this, Paul: Yeah, there's got to be like some open database out there or something of threat Intel coming in But it's just really cool to be able to view it in a tree. ~Like ~that's neat ~I ~I have no idea what packages my stuff's using. So Again, it was node dash inspector dot dev the [00:21:00] hosted version Anthony if people want to check it out~ Well, ~what was the web address? ~It was ~it was node inspector dot dev Anthony: It's node modules. dev. Paul: Known modules. dev. Awesome. Okay. Thanks ~Um, ~so we're getting close to the end of the podcast. We do this thing at the end. ~Uh ~now called quick round So i'm gonna ~like ~shoot some questions at you and the whole purpose is just to see what rattles off your head ~Uh ~without a ton of thinking so do your best and ~um, ~we have three questions. So let's get through them Starting with question number one What's the one thing you wish package maintainers knew about making the switch to ESM? Something that maybe they don't know right now. Anthony: ~Um, ~yeah. ~Um, ~there's a new feature called required ESM in Node. js, which is going to be. ~Uh, ~available, like in all the evergreen node versions. So that means you can ship ESM only more frequently ~without ~without concerning about breaking the others. ~So,~ Paul: ~That's, ~that's a great, that was a huge one that we were just talking about in the podcast. Like it's going to enable so many people to actually move forward ~and, and, ~and not have that other complaint. So that's gotta be it. ~Um, ~[00:22:00] okay. Question number two, if someone is on the fence about moving to ESM only, what would you say to convince them? Anthony: yeah, I think that, that would, it depends on the use case. I would say first you can go to dual module, dual format to be safe. And then you can evaluate like your use case, like all your users, how they use. Or how you consume your libraries. And if they are all like ~most ~majority of them are ~on the, on the major, uh, ~on the modern tools and supporting ESM that you can probably consider like moving to ESM because they are already being ready for that. Paul: And what is the number one reason for folks to go ESM only, and this can be on either the package maintainer or the typical developer side. What's the number one reason? ~Question number~ Anthony: Yeah. I think the number one reason is ESM is the only standard of JavaScript modules and that's future proof. And that's the direction that everybody's moving to. Paul: Awesome. That was short and sweet. Not knocked all the nails on the head. Thank you, Anthony. ~Um, ~ [00:23:00] So as everybody's listening knows,~ uh,~ from your intro, like your developer right next labs,~ um,~ you're hugely invested in the JavaScript ecosystem. ~Like ~Anthony's even putting out tools like we have the,~ uh,~ The node module inspector is coming out now. ~Um, ~so I'm sure people are going to want to keep up to date with more stuff. You're putting out Anthony and your blog. That's where we learned about this. This posting by you going to e SM only. So if people want to ~like ~go to your blog, what is the blog address? And we'll also have it linked in the show notes. Anthony: ~Yeah. My, my blog post is my, my blog is a n tfu.me.~ Paul: ~Uh, one more time. Anthony,~ Anthony: Yeah. It's a NTF u.me. ~Yes.~ Paul: A-N-T-F-U Do me. Got it. Okay. And then if,~ uh,~ people wanted to keep up to date with you professionally, like more on the social side,~ uh,~ where do you recommend folks follow you? Is it like a LinkedIn or a Twitter or a blue sky or all of them. Anthony: Yeah, I'm mainly on BlueSky right now, and it's the same as ~my, ~my website. So now it's ~like, ~it allows you to bind the domain to it. So you can find that, or ~you can, ~you can go [00:24:00] to my website and there's a link to it. Paul: Awesome. All right, Anthony. ~Well, ~thank you so much for your time. It was interesting for me ~to, ~to learn more about ESM and what the temperature of the ecosystem was, because it's always this like cloudy nebulous thing that's up there. It's ~kind of ~like floating around. ~So, um, ~and it's exciting to hear that we're going to have bi directional required. So maybe we'll see a big move in the ecosystem. ~Uh, ~but yeah, thanks again for your time. It was awesome to learn about,~ uh,~ where the ecosystem setting. Anthony: Yeah. Thanks a lot for having me and thanks for the chance ~to, to having me ~to talk about this. And I hope everybody would give a chance to ~kind of ~consider it and,~ um,~ helping the ecosystem to move into ESM. Yeah.