 Um, so I want to just kind of maybe start with some questions, um, you know, maybe just like say some terms and then maybe just like raise your hand if they're familiar. CommonJS, for those who aren't familiar, CommonJS is the module loading algorithm and implementation that Node uses right now. So, Equiskrip modules, the version of module loading that's specified in Equiskrip is 5. Um, I say like specified in a weird way because parts of it are specified and parts aren't. Like the loader itself is not fully specified and that's what makes things kind of complicated. Um, transparent interoperability. So, transparent interoperability is a word that we deprecated that I were just going to stop using. Um, because it's confusing, but when I say it, I'm specifically referring to being able to require any SM module or import CommonJS module and not have to know, you know, what the format is that it exposes. Um, we currently, for example, in our implementation have transparent interoperability but only to import CommonJS and only the default object to kick it into exports. Um, you can start to see how this gets really education. Um, so let me plug in and get started here. I figured what would be like a good way to start before we kind of jumped into discussion is just like a quick history. I'll save you all like the longer, fuller slide deck. Um, if you watch me not get my password ready for the time. It's very much like it is day to day for me. Cool. So, right here what you can see is a markdown file that you can find in the NodeJS modules. The zoom. Okay. Yeah. Um, for those who set up the zoom, I don't know about this. Oh, that is great. You can't even see what I'm doing. For those of you who are wondering what that is, that's a corner of a really beautiful water color painting of Calvin and Pops. So you didn't even get the exciting word of the water. Let me fix this. I've been talking as if you could see my screen. Um, so to just, I guess, set the tone. Just stop me if I'm not making sense. Um, well, this is what I was coming and talking about, except in terms of service. One second, folks, if you need a second mind for talking, because a lot of people are streaming and stuff. This table. So we have a situation where I need to run as before. Sure. Okay, cool. I'm sharing my screen. Yeah. Yeah. Cool. So, um, I'm going to get started by going through this document and a little bit of history. So, Okay. I did that on purpose because I believe that that is set up with audio to the mic. Yeah. Or not. Okay, whatever. Um, so a little bit over a year ago, maybe even closer to two at this point. I don't know dates, but we released ESM and no, um, we did an initial implementation that landed behind the flag. I believe that was in a version of node. Sevens. I don't know. Um, but so it landed in people were not super. Role with some of the implementation details. Um, some of the stickier points, for example, where the requirement of the dot and jazz extension for ES modules. Um, but, you know, there are, there are a number of different critiques. Um, in response to this. Um, and this is actually kind of a cool thing. If you're not familiar with it in general, the TSC keeps, we started doing, um, this thing called strategic initiatives. Um, we could look at the history and see how old these are. Um, this is something that was talked about, but kind of was kicked off by Mike Dawson in October of 2017. And the strategic initiatives are things that we've identified that are like really, really important high level. Um, things that we should be focused on as a technical steering committee as a project. Um, it was a bit of a shift that we made then around the TSC being much, uh, more forward thinking, uh, than being responsive. So a lot of things that TSC was focused on beforehand was like, Oh, there's a fire. We've got to put it out. We wanted to have a shift, um, to be much more forward thinking and thinking of the future and kind of, um, dealing with existential threats to, to know itself. Um, and so you can see one of the first ones on there was modules. Um, and I was the champion of it. We should actually probably update those links, but there's this original like EPS. That's from 2017. This kind of was how the initial implementation was like spec down and then implemented. As I mentioned, it was not extremely well received. Uh, I myself was glad that we had something as a starting point that, um, people couldn't agree on the stuff. So what we did is we spun up this modules team. Um, after about six months of just like yelling and bike shedding, we came up with a plan. Um, and the plan was this idea that we called, uh, the minimal. Um, oh, so no 8.5 is, is where I landed. Great. Um, so the idea of the modules team did is we kind of, uh, permutated a whole bunch of use cases as well as different, uh, different needs that we had from the module loader. So if you actually go here and go into the issues here and look at one of the 213 closed issues, um, you can see lots of different issues that were opened up for like, you know, well early ones around the governance, but later ones around stuff like, you know, import maps proposal for their imports. Um, upstream changes to note. If you go into the modules repo itself, um, we have a list of these different features. Um, that was based on number 55, which was the collection of kind of tracking all of those. And so we have all these different use cases that we identified that we would need. Although it was also kind of identified early that, Hey, some of these use cases, don't, aren't able to coexist. So we can want everything, but we're going to kind of have to figure out what works and what doesn't. So what we came up with was this plan, um, with different phases. So phase zero is what branching off of the current implementation. Um, phase one was this concept of the minimal kernel. So what we did is we just stripped back features from the current implementation. And so we had a baseline, um, and that baseline was not really usable. Um, but that baseline was, Hey, what are the common features that all the potential future iterations that we're talking about and all of the use cases that we'd like to see happen. Um, are possible with. So what are, what is a baseline that we were all to go and fork node right now and try to make our perfect implementation of modules. We can all fork from the exact same. Point and at least build upon the same shared idea. Um, and then phase two was fleshing up that implementation with enough functionality that could actually be useful. So the phase one minimal kernel was like absolutely useless. Let's make it kind of useful. And we shipped phase two with no 12. Um, and now we're in phase three, which is extending that MVP with a better user experience and edge performance. Um, and that's kind of where we are right now. And throughout throughout that, the entire phase, one of the things that we came up with as a group was these kind of like goals and guidelines and vision that everyone agreed to, even if we couldn't agree about, you know, like specifier resolution or transparent interop. We could agree that we wanted, um, our implementation to be spec compliant. We wanted as much for it to be browser equivalent. So, we wanted the loader in nodes for as much as possible match either the browser or the direction of what the browser's capabilities may be in the near future. Um, and we also wanted to not do anything that broke common JS. So any of the changes that we were, um, planning to do couldn't just, you know, go under the hood and completely break our currently existing ecosystem. So, um, with phase zero, starting from the current shipping node, the following changes remain to strip out most of the 8.5.0 experiments and modules. So the first thing we did is remove support in the import statement for a common JS, uh, JSON and native modules. So that was all of the transparent interop that existed. Um, we also removed dynamic path searching so that meant, um, no automatic adding of extensions, um, no directory resolution support. So support like slash index and slash. Just being able to import a directory and no support, even for the main fields. So there was, there wasn't really even support for very important, uh, very important being when you just give, um, a specifier, um, there's a map. Um, and a specifier would be something like, you know, require a low dash. That's an example of a very specific, um, and in the package JSON, you're able to use, um, the main field, um, to specify like what that resolves to. Um, but we even stripped data from this kind of phase zero. Um, we completely removed the VM module implementation. We also completely removed the loader implementation. Um, in these changes were implemented. Um, we also removed the loader implementation. Um, in these changes were implemented in this pull request, uh, over here. We don't need to wait for it to load. Um, the next phase that we did, which was, was called the minimal kernel was introducing a few more features into the implementation that were necessary to just kind of like, they were the baseline features that I've already agreed on. So that included module create require from path, uh, a now deprecated API because it turns out it's really annoying to use. Um, we talked about things like import meta require or having the important statements have transparent to rock. Um, but we decided that none of that would be in the middle of kernel because we didn't have, uh, consensus around it. And each of those features actually would negate other potential features that people were thinking about. Um, we made import statements only support the.mgs extension. The idea being here that we were planning as a group that we would always work on a chance. So even if we found a way to have.js files as ESM, there will always be a need for completely unambiguous file extensions. Um, so we kept support for imported ESM, but only for NGS files. Uh, we included import meta URL. This is something that exists in the browser as well. It just gives you a file URL to the file that you're in. Um, we kept dynamic import that was another feature that we had pretty much large consensus. This will always work. Um, and we did still allow for support for built in modules with named exports. Um, so that would be something like, um, what it would be like import, um, we thought I could spell. So stuff like this continued to work. We all agreed. Hey, we're never going to change that implementation. We're always going to want to be able to work the built in libraries. We're always going to want named exports. Um, built in libraries, the built like the built in libraries in note, even though they're implemented in common JS is all known to us at compile time. So we can do some fancy stuff with our built ins that can't be done with your system modules, but we pretty much have consensus that any implementation moving forward will have that featuring. So, um, the combination of all of those make the minimal criminal. Um, if you're wondering timeline here, this is probably about like 15 months into discussion. We finished to get there. Um, but what ended up being really amazing was like by the time we came to this decision by actually just stripping things away instead of trying to add things and having that, that shared understanding of the space. It just unlocked a whole bunch of stuff because now we weren't, we at least had a fundamental place that we were all on the same page about. So the next bit was phase two and there was a lot of debate to kind of pick the features that went into phase two and actually a lot of research to land on them. Um, but what eventually landed into phase two was one was defining its metrics for importing a package entry point. So that's like, you know, the main field and, um, there was a file specified resolution, um, proposal, um, that is referenced here and the full request that landed it. Um, and so it's kind of went through how that would be implemented, how this would be resolved and how that would work. Um, yeah, sure. Oh yeah, absolutely. So if you want to go to the MDM session, few of us are leaving now to that. Thank you. And, and please in general, if you want to walk out for the bathroom, personal grievances, other session, please, um, I'm boring. I don't know. Um, that would seriously, like if you need to go to the other session. Um, so we define the semantics for package entry points. We define the semantics for determining when to load resources as either common JS or JS modules. Um, this was the introduction, introduction, um, um, the type field in the package JSON. So you can now do type module. And if you do type module in the package JSON.js now resolves to ESM instead of CJS. Um, and it did involve the creation of a new dot CJS extension, which I'm pretty excited about. So like I actually, now for me, um, we've got three extensions and this is like, obviously CJS, um, let's see if this works. Um, I have like a shorthand to expand to the shorthand. So just assume that that means shrubby. Um, and that's ESM. So I'm not saying to do this in your book today, but like this is actually a way in which you could organize your code. That would like always work in pretty much all environments. Um, but that was a big part of it because if we had importing of dot JS. Allow and dot JS is always ESM. Well, how do you still import any common JS files? Um, the other thing is like these semantics are all bound to the package stuff. So if you make a folder and that folder has a package JSON, um, that will define the semantics from that folder down in the folder hierarchy. So you can kind of have JS files throughout your project. And as long as there's a package JSON irritable, use the nearest package JSON to resolve what type of file it is. And this is really great because it's purely static. So, you know, build tools or any sort of tool can crawl, uh, the file source of, uh, a project and, and a whole bunch of nested projects. And this is deterministic and static. So it's pretty consistent. It's very different than, for example, if we did something like, Hey, if you have a dot JS and it could be either ESM or CJS, and we do some sort of like pre-parse of the AST and then determine the type of the loaded, that would have been completely dynamic. And then there would be no way to like statically determine that without actually parsing all of the files. So, I don't know, I prefer this, just me. Um, we define this semantics for enabling ESM treatment of source code for a VAL. Um, that was the entry types proposal. Um, it was originally, you can see we renamed it a couple of times. That was actually, amazingly, like sheds that we had when we made the upstream PR, which is the name of this one feature in its functionality. Um, the other thing that we also did, this is something I'd actually love to talk to the room a little bit more in a minute, was we disabled file extension directory searching by default. You can turn it back on with this flag. But what that means is that, you can't like import dot slash folder slash thing. Um, you need to include the file extension to do it. And if you don't include the file extension, um, it better not have a file extension or we're not going to find it for you. Um, a big motivating factor for this was browser equivalents. Um, there are things like import maps that are going to allow for some fancy stuff. Um, but generally browsers are not going to like hit the server three or four times to determine the file extension of a resource. And so by introducing this constraint into our loader, um, we're, my personal opinion, significantly improving the possibility that, um, that we have equivalents. Um, another thing that landed in phase two that's not in here was experimental JSON modules, which, excitingly, I'm not, I think Dan Aaronberg is somewhere in here. Um, you went over. Well, uh, Dan did the work with some people on spec text and JSON modules actually landed in the HTML spec just a couple of weeks ago. And has a vendor interest from every major browser to implement. And we have now in nodes experimental loader, um, a spec compliant JSON loader with the first implementation of it, which I'm pretty excited about. Um, so we're in phase three right now and that's kind of removing the experimental modules. And there's a handful of things that we can figure out to report. And, you know, kind of after reading this will be a really great place to start a conversation. Um, so the first is a loader's solution that supports all the items in the features list. So there's like custom loaders, the ability to say, Hey, when you import a file, like run this dynamic code first instead of just loading it. Um, that is something that we need to figure out. We have an implementation of loaders that currently exists. The team is not super happy with it. We have the beginning of a new implementation. It has all sorts of memory leaks. And it's also built on top of, um, the worker friends implementation. That still needs some kind of tweaks to be urban ergonomic together. Um, so if you're looking for somewhere to work and you have some really great C plus plus drops, that's somewhere where you can come in and help us today. We need to map the path with the in modules, providing a similar functionality as the browser's import maps. We have a package exports proposal. Uh, Yon over here, you raise your hand really quickly. Um, Yon has come up with a lot of those ideas package exports. I think is really, really cool. It's the idea and name pending that you would make like an exports field and the exports fields here, you could say like, uh, you know, like, uh, import and, um, specify, you know, like file. And now you'd be able to like import, um, like this without any file extensions and you could specify the specific deep imports. Part of the idea we have here that I'm pretty excited about would be actually walking down and not allowing just the traversal inside of the module itself. It is possible that you could just do something like this. The semantics are still up in the air. That would allow like kind of infinite deep searching. Um, but the plan would be twofold one to kind of make more of a public and private definition for modules. So you could be really clear about what interface you're exposing to users. Um, as a module author myself, I've definitely been surprised when I find out like that people are going in and like randomly importing or requiring a specific utility function that I did not design as a public facing API. And now you're supporting it. It's great that you're bringing people who are depending on you. Um, export maps would make it far easier to define that interface. The other thing that would be really cool import maps is a browser spec. That's, I think in an origin trial right now, but it could be mistaken. Um, but import maps are what are going to allow this kind of like their imports to exist in the browser and to like turn that module into like no, no modules slash modules slash to entry point. Um, the same thing that we have with package JSON in May import maps are going to be like a static file that's at the top level of your application. It's loaded. Um, I believe as like a source tag or something. I'd have to re look at the spec, but what would be really cool with this exports is a tool could statically crawling while installing your module graph, like actually specify all of those deep imports. So when we're talking about browser equivalence, if you're being explicit about this, um, tools would then be able to statically generate all of this and we'd be able to have the exact same kind of import, um, interface for both the browser and. Um, so this is a proposal that I think I bet you might also be in the room. Dyer Europe. As over there, I think guy has an implementation of this somewhere. Um, but it's something that we definitely want some more feedback on. Um, we also are interested in having this be part of common chance as well. So we need to figure out, Hey, like is this something that people would use or are there things that we would break that we're not aware of? Um, that's something I would love to bring to the audience as something that we can talk about. Um, there's a proposal that's still being debated whether or not we want to do it, which is like having some sort of reference inside of the package to reference itself. So you could import. Um, here's some like really naive syntax. I don't think that this would be it, but if we have names, spaces and node, we can have like, um, something like self or this or me or like some sort of specifier there. Um, that means your own module because there's a lot of places where you may work for your own modules and then you have like the paths and docs and whatnot. And it's not great. It's like a bit of a refactoring hazard potentially. So that's one thing that we're exploring. Uh, this is another one that came up as a potential inconsistency from common JS and ESM and that's a debate within the modules group as well. Like should we be introducing new features like this to ESM if we're not able to have the same capabilities in common JS, would implementing something like this in common JS even be possible or breaking? I think we're not 100% as we explore game spaces as a possible thing. That opens up the design space, but doing it right now without game spaces, I don't think would be possible within a super major, but love to hear what you can do with that. Um, limited module type declaration. Um, I'm not sure what that one is. That's, Oh, that's the utility method for determining the type of a module. There's an upstream PR for this right now. So if you have feelings, you can jump into this. This is like util methods that you can run on source text and it can tell you if it is ESM. Um, I think that there's, yeah, it's like contain module syntax as current API. It kind of looks like this. I think there's some debates about whether or not this is the best API, what the API should look like. Um, that's part of phase three. Um, another one is provide a way to make ESM the default in node instead of common JS. So how do we move us to that just like using the node binary expect CSM instead of common. Um, dual mode modules is a really contentious topic right now. So the ability to have a module that you can import that could be either common JS or ESM. So you can both require it and import it. Um, with the same specifiers. So like, this is important for module authors. If you are a module author and you want people to be able to like both import low dash and require low dash. Um, and just kind of have that work. That's what we would call dual mode. I have some of my own opinions. I don't actually exist, but I won't take into it because I don't want to poison you with my bias too early in this discussion. Um, but that's something that we are actively debating. Like, how should this work? Um, shouldn't even work. Uh, the current implementation that we have with only the single entry point name that share between common JS and ESM. And with the file extension turned off, it's actually not possible anymore. I think that's a feature people disagree. Um, so that's something that we're debating. And we also need to finalize the behavior of importing common JS. So we want to be able to import common JS and have named exports, but right now we can only do a default export that has something to do with the specification and being spec compliant. You can't have, um, it's just not possible. We can dig into that more afterwards. I always tried to go to TC 39 a couple of times with different approaches to how we can allow for dynamic modules where like exports, the names of things and resolves those later. Um, but we've been unable to do that in a way that can get consensus at the committee. So there was debate about whether or not we should even should have that transparent interoperate default only because you still even need to know that it's a common JS module. Anyways, that's a debate. Um, one of the things that is done, the only thing that we actually finished right now is we, um, made a better mechanism for require with require. So you can now do, um, import, um, create require from module and then, uh, create require import meta URL. And then that literally gives you a require inside of the module that you can use. Um, this little bit of, uh, ritual is not the best user experience, but we haven't come up with a better way to do it. Um, having something available immediately on import meta require is something that we discussed. And the problem is that it doesn't fail early. That doesn't exist. So if you take some code that's been written in yet, that is import meta require and you bundle it into a browser module and then they're using require dynamically somewhere deep in like an F statement. Um, that's going to blow up in really weird and unexpected ways, which is one of the reasons why we didn't want to introduce that API, although that API would be like a million times better for the user experience standpoint. Um, and that kind of sums things up. And I think that that last example I talked about is the perfect example of the struggles that we've had this whole time, which is finding the balance between like foot guns and salgo and user experience. Um, I guess with that, um, thank you for letting me talk at you for like 30 minutes. And I open it to the floor for questions and discussion. Hey, um, I'm not sure if you can guess what I will ask, but has there been any, could you talk a little bit about how, uh, we as APM readers can look into the port features to get notified when things are imported and possibly modify things on the fly. Yes. So that would be the loaders that I was talking about earlier. So right now. Dang. Um, we look here. This is dash. It's like the best thing ever. If you haven't had it installed on your computer, you should do it. There are open source versions available for Linux and Windows as well as just an offline document version. Uh, you're a really great fussy search. So this is the experimental loader books that exist right now. And so you can make a result book right now, which changes what's resolved, but to your point that doesn't really change. Like if we think about module loading, there's a couple of different phases. So there's kind of like fetch, resolve and transform. And so like, um, it's in this order. So like resolve is what takes like a specifier and turns it into a path. So that's what would turn like low dash into, uh, node modules. It would be like file, like in the whole path to node modules. Um, fetch is what can then take, um, a path and turn it into like the actual source text. And it's a little more complicated under the hood. This is all happening with like source text module records. Like under the hood, this is kind of the high level. And then the transform is what can, you know, like take that source text and then turn that into like the actual object that is then inside of, inside of the cache. So each of these phases are kind of like different phases that you may want to look into. So, um, you know, this specifier to file path, for example, um, with just a hook there, you can implement the file extension resolution algorithm. But you don't need to look into any of these other things. Um, for fetching the source text, that's how as an APM vendor, for example, you could fetch your own custom implementation of FS instead of our implementation of FS. Uh, for transform source text, you know, combined with resolve specifier, that's how we can implement like built-in type script support by like transforming that source text before actually executing it. So the newer version of young. Um, just, just, since you're talking about an S, most likely you can go, there's a very good point. Um, just because I'm just thinking of it, uh, what you just described would most likely not work if an APM vendor, for example, wanted to influence the implementation of hb.create server, because it would be a name export on a core module, and most likely they would not be able to modify the core module source text, or they also would be able to do that. I think the guy may have more insight into the loaders right now, but I may be wrong. I believe that we would allow for intercepting of any modules that are being meshed. Sure. So if it's a core module like HTTP, what we've done right now in supporting named exports on core modules is we've set those up as live bindings. Um, so if you, if you have the common JS version of HTTP and you have a write create server, um, that's going to have data in the ES module live binding as well because it's a proxy. So, uh, we've got that on core, but for third party modules, yes, APM on the named exports is tricky because you actually need to inject into that source code and update those ES module live bindings with all the exports, like the, if you've got export let or export function, you actually want to be updating that export and you can already do that from within the module if you can't do it from outside of the module, so that will be an APM section. One thing that I've been thinking about, this is by no means even close to solution. We were playing around, I actually didn't mention this in here at all is web assembly modules. So we shipped an experimental web assembly module implementation, uh, last week or two weeks ago, I don't know. Um, but it landed and I started playing with building stuff with scripted. One of the first things that I noticed was like when we built it out and we did the tests for it, we didn't actually like compile web assembly with scripted. We took what's known as, um, WABM, what is it? Um, there's an intermediate representation of the AST, so last. And we, we directly compiled last to wasm so that it was like a pretty, pretty clean translation and all of our tests and everything that we've implemented works with last to wasm, but almost no one is like writing last by hand. Um, those people are taking like C code and then compiling that to web assembly. And if you use in scripted and scripted is embedding its own, uh, sysroot and that includes like a whole implementation of just things like how do we convert printf or any sort of the system calls that exist into things that are actually happening. And scripted does that right now by actually like wrapping all the code and like thousands of lines of JavaScript that's expecting to execute and have available. And then it's expecting there to be like the source object. Um, that's available that just has specific things implemented in it. There's no way for us today to like inject on a per module scope like things to say, hey, if you try to import source in only this module, it will resolve to this thing. Now this is actually a thing that import maps are introducing. So that's something that we could think about exploring, but one of the things, um, that may help with APMs, but I'm not 100% would be some sort of support for a kind of like injecting or changing the scope of what happens when you import specific modules from the context of one module. So we try to from inside of a WebAssembly module import something called source and it doesn't exist anywhere else. Can we inject like a particular thing for that namespace? I don't know if this is possible and I don't know if there's a way for us to do that with spec compliance, but because of like this edge case that I've seen with WebAssembly, it's something that I'm thinking about. And that would be kind of similar, I guess, in a way to proxy wire, but not exactly. It would be a bit of a different thing. Do we have anybody in the modules right now representing APM vendors? There are people who are definitely thinking of those use cases. As I mentioned with the loaders, we need more people who are coming and working on it. I believe that we had initially wanted that to be kind of a blocking thing to removing the flag, but as we get closer to like October and as the rest of the implementation gets more stable, we are actually getting closer to making a decision to just keep loaders behind an additional flag and potentially unflagged without these capabilities and I understand where that would be really detrimental to APMs. So we should likely think on that and see about how well we could get the right people focusing on that problem. Any other questions? Yeah, so there's a lot here, I think, for module authors to absorb. And in addition to actually doing all the great implementation, will you be publishing any kind of recommendations or documentation for module authors to understand what they need to do in order to support the most versions of node as possible because it sounds like at some point there's going to be things that are I guess maybe mutually exclusive you can't support. Yeah, so the question for the people on this stream is how are we going to do things to make it ergonomic for module authors to support multiple versions of node? Is that an answer? So that is like kind of what's actively being debated with dual node modules and so dual node modules would be something like if we had like what I would consider a really nice solution would be having a module field like this and then having a separate name. Yeah, that would be like a giant solution to the problem space. We're just doing this for things like Babel and I think that there's a whole lot of things for defining multiple entry points on the outside. One of the things that I'm familiar with is that this does not mean the same thing in node that it means to Babel and Webpack. It means multiple entry points but generally when you're using Babel and Webpack it's multiple time, not multiple entry points at one time. So this is a huge hazard for module authors that are running code of node because what it would then mean would be like the specifier for my module would be two different things depending on the loader that you're in and would potentially create weird cache duplication. So the common JS cache and the ESM cache are two separate caches and so when you import a common JS module today the way that interop works what we do is we get the source text, we instantiate it, we create it we create a reference to it in the common JS cache and then we create a pointer and reference to it in the ESM cache with both of them pointing to the same table. Where this gets really weird would be the common JS cache has no reference to the ESM cache. So if you're in a module that started as ESM and you imported a module you would instantiate this source text you would create that record inside of the ESM cache and then if later on down in your tree someone required the exact same module in the exact same like general module context so not just like before it's a different thing it would actually create a new instance inside of the required cache with a completely different singleton and in many cases this may just kind of work but having worked on things that are expecting behavior in that singleton or shared state between your app that just creates these like really really weird errors and these really weird hard to track down and hard to even know what's going on problems in the tree that sometimes don't even manifest until production and sometimes not even until like you know two weeks in production. So I mean it obviously sounds kind of tricky like do you think that the real recommendation would be for module authors to sort of cut over to ESM at some point and only support it you know going forward on say you know 12 or whatever ESM modules but prior to that it's all CJS or how would that work? So we're still debating that and if you have opinions and interests on that like one of the things I've been challenging people to think about is like come up with the user journey come up with the user journey of like I am a module author who needs to who wants to upgrade my module to be ESM and once that transition happens so I'll show you an example of one that I've created I'm a module author I have this module called NonoSC NonoSC is a library for doing open sound control primarily used by like artists and musicians so not people who necessarily have a really deep understanding of our ecosystem and all the subtleties that I've been talking about for the last 40 minutes. Here's an example of new experimental ESM implementation where all I've done is I've created a deep entry point called ESM.MJS this can land in December minor you can see that all that ESM.MJS is doing is actually just importing all the common JS things and then exporting them as a default but also exporting them as named exports. This creates an ESM interface into the common JS that will work will have named exports. If we had the export map proposal that I'm talking about we'd be able to drop the .MJS from it. Then what I have is this branch called NEXT where I'm in the process of slowly converting everything over to ESM completely. It hasn't happened yet but the idea would be that we would have legacy CJS support and no JS left and in December minor on the prior December major you could still introduce that slash CJS entry point as the same as the main and so this isn't perfect it's definitely not as ergonomic as just having a shared main but I actually think that this is pretty reasonable it creates like explicit entry points if you're supporting it slash CJS and slash ESM could always work as explicit entry points and you could basically flip which one is the default in a December major. This is we've documented this recently in a pull request I think Jeff over in the chat has pointed to it right here and this is like our current recommendation and that kind of documents the pattern that I was just talking about we're open to other patterns and other user journeys so the more people who can put brain power on this problem and think through it we're open to kind of talk through it and try to figure it out I recognize that this is one of the biggest problems that we will have as an ecosystem and we get pretty fired up in our meetings when we talk to people on this should be because we know that it's extremely important for the adoption of ESM but also be really important for module authors who are going to have to do this to continue to support all of the different people who are going to use their modules I think Joey you had your hand up and to the people who are dialing in on the stream I've now got your comments on the screen I'm sorry we don't have you connected to the mic but if you have particular questions as well please feel free to put them in the chat and I will try to get to you Joey Is the plan to get the ESM in addition out of experiment as soon as you drop the flag or is there any plan to keep it experimental while the flag is dropped That's a really good question to be honest we haven't discussed the possibility of relieving the flag but still keeping it experimental I know that we've done that for some other implementations I think like my bet on it is that people want ESM so badly that the moment that we remove it the flag a lot of people are going to just start adopting it so I don't know it might be good to even keep it experimental like remove the flag before LTS and maybe try to remove the experimental flag in December minor remove the experimental status at some point I think it changes that what we do with HTTP2 remove the flag and then upgrade it later so that's definitely an option that we haven't really discussed and everything that we definitely want to try to do is back to 10 if possible but we're kind of we're waiting to see where things land before we see what we can back to 10 it may also just be possible to back to 10 like the basic capabilities but just a different implementation but a lot of the same behaviors but we're waiting until we remove the flag before even starting to tackle that thank you Michael Dawson I'm just wondering about importing native modules to work through that yeah so native modules there's kind of two different things that are going on actually let's see I'll show you some code so it's not guy what's the one where we resolve the specifiers it's not translators it's like I'm trying to remember the name of the... oh default resolve there we go so this is how we're actually doing the file extension resolution itself and you can see that we have two different format maps so we have the extension format map and a legacy extension format map and so basically when you're in the legacy build which is essentially when you don't have type module or you have type legacy inside of your package JSON this is what the file extensions will resolve to so cjs and .js resolve to the common JS translator and that's in translators.js this is actually the implementation of those different loaders there's the wasm loader there's the JSON loader there's the built-in loader this is the common JS loader and that's the main module loader it's actually surprisingly not a lot of loader but so when you're in the legacy mode these are what the extensions map to and you'll see .node maps to common JS when you do mode when you do type module we actually don't support anything out of the box right now that is not like browser equivalent so we don't support native modules but that's only within the boundary of your own package so if you import a package that's a native module it will still resolve and work the only limitation is the same limitations of common JS you won't get named exports you'll only be able to import the default namespace if you want something that feels a little bit more like named exports you can use create require to create a require function and then require it and do structure the require or you can do structure the default export it's not the most ergonomic but it's the only way that we can do it right now that's that compliant one of the things that we do have though is the WASM stuff I'm confused that I'm not seeing .wasm in our extension map I'll look into that afterwards but essentially we're actively exploring WebAssembly and specifically WASI and I think there's some members of the Missility Networks on WebAssembly in the room back there the WebAssembly WASI stuff is system interface we're actively exploring the WebAssembly system interface as being kind of the next generation native modules as an alternative approach and being one that could potentially have browser equivalents but you know these are still up in the air we could choose to change the way that this is supported but I think in general like you wouldn't be writing a ESM module that's using the legacy native module system so as long as you have package JSON that doesn't have type module in it in your module that's a native module anyone can import it they just can't do named exports so there's support there but it's limited support which I think is a break of time do people want to have any more questions or should we call it and have some coffee in our shoes say hi to all our friends okay cool here's a large hand pat thank you everyone good job Miles just to remember actually really quickly before we go hey people on the chat you have any questions before we disconnect 5 4 3 will there be modules after the break definitely there's a session later on modules and security but not just general modules any more questions okay be free