Node.js and its many, many new features
When was the last time you looked at what Node.js is capable of? If you're like me, it's been a while — and a LOT has changed. TSC member Matteo Collina will show us what's new and how we can modernize our projects.
Links & Resources
Full Transcript
Click to toggle the visibility of the transcript
Captions provided by White Coat Captioning (https://whitecoatcaptioning.com/). Communication Access Realtime Translation (CART) is provided in order to facilitate communication accessibility and may not be a totally verbatim record of the proceedings.
JASON LENGSTORF: Hello, everyone, and welcome to another episode of Learn With Jason. Today, on the show, we're bringing in Matteo Collina. Matteo, how you doing?
MATTEO COLLINA: Hiiiii, Jason, how you doing? I'm very happy to be here, on the show. Me and Jason, we've brushed a new times on Twitter. We finally met in London, so it was I don't know, it was a show about not JS and only new things that are in the that have been coming in the pipeline and all sorts of things, so let's do that. We have done exactly [Indiscernible] show.
JASON LENGSTORF: I'm superexcited to talk to you about this, for a lot of reasons. I've been following your work forever. I love the things you do on Fastify. You're a voting member of the TSC?
MATTEO COLLINA: Technically, I'm vicechair.
JASON LENGSTORF: Oh, cool, very cool.
MATTEO COLLINA: I don't know if that means anything. [Laughter]. Who leads the meetings and says, hello, everyone. [Laughter]. This is the technical answer. How you greet the YouTube livestream, okay, for our I don't know for watchers, or something, that
JASON LENGSTORF: Got it. Got it.
MATTEO COLLINA: Quite a few people watch the Node.js livestream.
JASON LENGSTORF: I bet, yeah. So, before we get too deep into the node side of things, let's talk a little bit about you.
MATTEO COLLINA: So, yeah, yeah, absolutely. So, hello. Matteo Collina. Started doing Node back whennnnnnnn...back when Node, you know, didn't work? You know? It was 0.2. And it was absolutely insane to do Node, to run Node in production. And didn't stop. At some point, I started finding a lot of bugs. First, bugs in libraries, then bugs in frameworks, then bugs in Node and either my approach to this has been either fix or replace. And, so far, I've been able to fix Node as much as I could.
So and there's a lot more fixes that I want to do in Node, they will break everybody, so probably can't. But, you know, Fastify was born out of my frustration with a few other very notable frameworks that you can find out there, then we have the logger, which is even more more used and quite a lot of those things. So, yeah, that's the situation.
JASON LENGSTORF: Yeah. So, I think
MATTEO COLLINA: Oh, wait, just one more thing. I recently I've been a consultant for eight years and a half. Then I decided I wanted to do product and I launched the startup and the startup is called Platformatic. So, check us out. Okay, if you're running Node.js, please check us out. Even generated API clients, quite a lot of things that are quite useful. So, yay.
JASON LENGSTORF: Yeah. I think I was taking a peek at Platformatic and it is very exciting, especially if you've been working in, like, in the team, you got to coordinate a lot of different services. I was really excited about some of the features there.
But let's talk, today, about Node.js because I think I've been using Node since about Node 6. I think that was when I really got into it, was, like, it was around the time that there was that whole split with, like, io.js. That was kind of, like, when I started
MATTEO COLLINA: Node 6 or Node 0.6?
JASON LENGSTORF: Great question. I don't know. [Laughter].
MATTEO COLLINA: Node 6 is past the renew. This happened between 0.10 and 0.12.
JASON LENGSTORF: Okay.
MATTEO COLLINA: In fact, you know, there was Node 0.10 was the last Node released, to some extent. Now we have Node.js 1, 2 and 3. Then, the Node 0.12 got merged into the io.js tree, so reality is, we are running io.js and if you want to contact the Node.js TSC, you send an email to tsc@iojs.org. [Laughter].
JASON LENGSTORF: Amazing.
MATTEO COLLINA: All of you are running io.js.
JASON LENGSTORF: I love it. I've been using it for a long time. I think that Node is one of those tools that's sort of a victim of its own success. These days, I hear a lot of people complain about it, but it doesn't feel like Node, like NPM. The challenge isn't that Node, itself has problems, it's there are challenges when you run an ecosystem of the size that Node has when you are dealing with the very, varied preferences that developers have when they work on tools.
But I think one of the criticisms that I had heard, about Node, that felt valid, was that a lot of things that felt like they should be built in weren't built in. You needed a Node, but you also needed [Indiscernible] and you'd always have to reach for a few more packages and so it felt and I think that was sort of the big selling point that you would hear from any competitors to Node is, it's all built in. It's one runtime for all of it.
Recently, I was looking at Node and it doesn't it feels like at this point, when we criticize Node for those types of things, it sort of feels like we're criticizing a ghost because that's not what Node is anymore. That was why I wanted to talk to you is because I feel like there's almost a perception of Node that's stuck in the past, where people are remembering what it was like to run Node 8 or Node 10 and we're on Node 22 now. So, obviously, like, 10 major versions, we've come a long way, right?
[Laughter].
So, like, as somebody who's very close to the project, have you felt the same I guess, like, I'm kind of putting words in your mouth. How have you felt about the public perception of Node?
MATTEO COLLINA: Okay, so, 90% probably more, I don't know. I'm making a bet. I don't know. A huge number of people that use Node.js are using Node.js like they were in 2015. A few popular article and courses being written on those, in those years. And, that's what everybody's using. Okay. To be honest, this is my, um...yep. This is my this is my take. Okay.
So, a lot of people have been using those and have been using those and creating all sorts of problems with that. Okay. So, um...basically, 2015, okay, Node became massively popular. It starts this massive growth, okay. And it's right now, no starts evolving again. It's great. Everybody gets start working on it. Okay. The success is so big that things cannot be changed anymore. Okay.
And, then, Node.js, it got stuck into the same problem of the web, in general. Okay. You cannot break the web. Okay.
JASON LENGSTORF: Uhhuh.
MATTEO COLLINA: And Node.js is essentially stuck in that, more or less, same conundrum that you can, more or less, write an application like it's 2015 and, more or less, it will stick work in modern Node. To be honest, one of the most popular framework for Node, Express, runs the same the same code of Express can run from 0.8 up to 22. Okay. This is level of stability of the project. Okay.
So, essentially, we have not breaken much. There have been breaking changes, new features, but the core of the project has not broken everybody. In fact, there is still very, very obscure, deprecated feature that we can't really get rid of because we will break the ecosystem, okay.
JASON LENGSTORF: Sure.
MATTEO COLLINA: Even stuff like domain, the domain module is so damn botched and it's still right there because so much of the ecosystem relies on it. Okay, which is a massive pain, to be honest.
So, we have experiments, we have experimental features, you know. When something lands, it is really hard to get rid of it. If it's popular, we start using it immediately and then if you try to yank it, you're in big trouble.
JASON LENGSTORF: Right.
MATTEO COLLINA: So, 2015, massive popular. 2018 all across the years, massive amount of content gets produced. Okay. There is infinite amount of content everywhere about Node. For example, there is a content about all sorts of things in in in the on [Indiscernible] or other platform. Okay.
And then, nobody updated that content anymore. Like, that's the problem when you write a blog post or you produce a video and you know it very well, Jason. You produce a piece of content and that is set in stone. Why documentation on the web can be updated, a blog post or a video, it cannot. It has a course. It has a time to live, right. It has a freshness aspect to it. Problem being, you know, I was checking recently and somebody said it's being we're publishing the same stuff of years' past, changing the year.
JASON LENGSTORF: Interesting. Okay and actually, this brings up a really valid point because one of my most popular videos I released was from 2016 and that is how to build a Node server and that still gets traffic today, despite me having released, in the meantime, like, I just wrote a new post, within the last few months, about how to set up a modern Node server with TypeScript today, which has one dependency, which is TS Node but the one I wrote in 2016 has a bunch of dependencies because those features weren't bit in. The one I just wrote isn't getting the pickup that the one in 2016 did, so how do we solve this problem? That's a really valid point.
MATTEO COLLINA: This is the main concern is, the Node.js project is shipping stuff, doing stuff and producing new things. Nobody give a damn thing about anything. Okay. You keep writing software, like it's 2015, okay. And, like, one example I'm just making one example, okay. One of the biggest problems that we had in 2013, 2014, 2015, those years, was that the support for WebSockets were not widespread, okay. And Socket.IO was one of the biggest solutions because it removed the problem and said, you can use allvalue systems and it will create the level of interactivity that you need. Great project. Okay.
However, now, WebSocket is everywhere. Okay. And yet I'm still seeing blog posts being published, content being published, video being recorded how to use Socket.IO. By the way, it makes absolute no sense to use Socket.IO in 2016. This is all few that are listening. This is just one example of a phenomenal, popular module that was great. It solve a very specific problem back then. Now, everywhere, we have WebSocket and it's working very well across all proxies, CDNs, so there's absolutely no need to use that. The support for it is rolled out across all proxy servers, there's no need to punch that wall anymore.
That's to make an example of one of the things that are bad in there, okay. And still publish Node.js can release a lot of things but one of the reason I wanted to be on this call is to talk about what's new, okay. Because a lot of people don't know, they're still doing 2015.
JASON LENGSTORF: Yeah. And I guess this is the other problem, too, is that that body of work, then, what Ester's saying is ChatGPT will tell you to use Socket.IO. [Laughter]. That's a very, like, good kind of an encapsulation of the challenge that we face, is that if we're not actively looking at what's going on with the project, itself, then we run the risk of falling into habits that were valid at the time, but aren't valid anymore. This is like jQuery, it was a giant leap forward ahead. Continuing to use jQuery is fine but you don't need to, it's extra work for no real reason and that you know, and that was the stated goal of jQuery, we want to solve this problem until we don't have to and then we'll fade away.
MATTEO COLLINA: It never did. [Laughter].
JASON LENGSTORF: It never did. It's still on something ridiculous, like, 70% of the web.
MATTEO COLLINA: And you don't know much what's the build for the CDN, by the way. Everybody using CDN. I don't remember who does it, they give the project for free, otherwise the build will be incredible. So...
JASON LENGSTORF: Uhhuh.
MATTEO COLLINA: I'm also part of the OpenJS board. I oversee all the projects, including jQuery, Webpack, Lint. We talk about budgets. [Laughter].
JASON LENGSTORF: As as it tends to go. But so so, you know, knowing, then, that a lot of the articles and tutorials might be, you know, presenting information from 2015, as opposed to, you know, 2024, like, what are we missing? You know, I was pretty surprised when I went into the Node docs and I realized there were a bunch of features people weren't talking about. I'll drop the link in case people want to see it. This is one of those moments, the light bulb came on and I was like, wait, I'm pretty sure all the things I think about Node are outdated. I'm pretty sure those problems have been addressed in the project and then I got into the docs and started looking around and realized, yeah, in fact, that's true. It's like a whole, new tool. The things that used to be really painful, like, managing ES Modules, it kind of works now. It's just there. [Laughter].
MATTEO COLLINA: It's just there. It's just there. And it's slowly getting better and better. We are plugging all the holes, essentially. And finding new bugs, it's actually very, very tricky. So, it's really, really it's really, really nice. So, um, yeah. I I really like it, to be honest.
So, part of so, right now, I was starting with one of the Platformatic clients today. One of our customer. And they have this fantastic setup, which they do the Node.js runner. They use TSX and they use the loader system so that they they write it's all TypeScript. It's all TypeScript, but they just transpile it on the fly, using Node Test Runner and things absolutely so speedy and super, super nice, like, you run it and the test runs instantaneously. You make a change, it automatically restarts itself.
It's a completely new it's a brandnew word, essentially, on those things. It's really, really, really, really nice.
JASON LENGSTORF: Yeah. And that's kind of what got me that's what got me thinking I needed to talk to you or somebody else on the Node team. It just feels like we're being we're not measuring Node on its merits, we're measuring it on its history. That's just kind of a bummer of a way of dealing with software projects because every project had issues when the platforms couldn't support these things. Socket.IO existed because WebSocket support was janky. If we held everybody to that standard, of what they could do in 2014, it's like, yeah, we're not going to make any progress ever.
Let's see if we can stand up a project and start using some of these features and see how far we can get without adding dependencies or very minimal dependencies.
MATTEO COLLINA: Absolutely. Ooohhh, my light is gone. [Laughter]. That's fine, don't worry. So, I need to move the screen so I'm not going to look at you anymore, just so that you are aware. I'm just moving the screen and putting it on the other monitor so you can see I don't I have a muchless fancy setup than you do, okay. And, I I have this, so I need to so, this is the camera and but I need to look here.
JASON LENGSTORF: Now it looks like we're both we're both looking at the code now.
[Laughter].
Okay. So, when before I start, let me do a quick shoutout. Thank you to our sponsors, Nx and Netlify. We have Vanessa, from White Coat Captioning, taking down all of these words into the link before. If you need the captions, they are there for you. And that is, you know, very much appreciated.
And then we are talking to Matteo...
MATTEO COLLINA: Hello.
JASON LENGSTORF: And your Twitter profile is here. Let me drop a link of that into the chat.
We are talking, today let me get over to a cleaner page. We're talking about Node.js. So, here is...the Node.js home page. I'm on
MATTEO COLLINA: We shipped a new website. Come on!
JASON LENGSTORF: Yeah, you shipped a new website. And I checked this out, branding. Look at this. Look at this amazing thing, that has happened. Node got a mascot. There's really like, the potential for criticism is vanishing quickly. You got a great mascot, you got a new website.
It's also modern. The website was so clunky, okay. Took forever to ship this.
JASON LENGSTORF: I can imagine because there is a ton of information on this site.
Okay. So, if I want to dig in here, and I want to try the modern Node, what should I do first?
MATTEO COLLINA: Okay. You should have Node installed. There's still a lot to go, okay. You should have a terminal, okay. And you should have something like NVM.
JASON LENGSTORF: I think I do.
MATTEO COLLINA: If you don't have it, you are in trouble. You should be installing Node using NVM. If you are on Mac or Linuxbased system, otherwise, you are absolutely it's not going to work. Okay.
JASON LENGSTORF: It's going to be challenging.
MATTEO COLLINA: Yes, bigtime. There are ways you can get a good, decent Node.js installation, but, nope. This is the only one that it's simple, you know. It just works out of the box. We have Node.js 22. So one of the first thing that a lot of people complain about, okay, you have, um...you have specific one of the complaints is Node.js is slow. Okay. And low start, low boot time. Okay. Node.js 22.1 shipped a fantastic, new feature, okay, called Node_cache. If you go this was just announced, okay, in the latest this is, you know, literally the latest release. And, it has Node_compiler. If you run this on...on on your app, you can see that it starts so much faster. Okay. You know, let's give that a very simple try, okay. Can you write a TypeScript file?
JASON LENGSTORF: Okay. I'm going to do an index.ts.
MATTEO COLLINA: Put another word in there, that's fine. Yep.
JASON LENGSTORF: So we're going to go with a console log.
MATTEO COLLINA: Yeah, just do that. And now do...you know, time. And space, NPX. Oh, no, sorry. You need to sorry about that. You do an NPM and TypeScript, otherwise it's not going to work.
JASON LENGSTORF: Okay. We'll call it here. Go through all these, good.
MATTEO COLLINA: TypeScript.
JASON LENGSTORF: Ts Node or TypeScript?
MATTEO COLLINA: TypeScript. Now let's try that. You do "timenpxtsc."
JASON LENGSTORF: 0.5 seconds.
MATTEO COLLINA: Yeah. Do the same command, but add Node _module. Equals [Indiscernible] tmp/node. And the same command.
JASON LENGSTORF: What did I do wrong? Time, NPX.
MATTEO COLLINA: Do an export.
JASON LENGSTORF: Right, right, right. I know how Bash works.
MATTEO COLLINA: Sorry about that. You need to do the export and do runtime.
JASON LENGSTORF: I gotcha, I gotcha. Let's see, that was 3:38 total.
MATTEO COLLINA: No, it's not picking it up. You need to go up the one it was at the beginning.
JASON LENGSTORF: The one that was at the beginning.
MATTEO COLLINA: The first one. Very it's not picking it up.
JASON LENGSTORF: Let me make sure that this is actually picking up...well, actually, is this where my...so that's why.
MATTEO COLLINA: Put "/tmp." You can just put it there. You can just put it on the local thing.
JASON LENGSTORF: Okay. If I can spell right. Okay.
MATTEO COLLINA: Redo the export and...
JASON LENGSTORF: And, we'll go to cache...
MATTEO COLLINA: Yep.
JASON LENGSTORF: And then...run that again.
MATTEO COLLINA: It's not picking it up. Pretty sure. Do Nodev. Try doing Node..._modules.bin.tsc. Yep. Run this. Run it with time at the beginning.
JASON LENGSTORF: That was a lot faster.
MATTEO COLLINA: Yeah, told you. [Laughter].
JASON LENGSTORF: All right. All right. This is this is very quick. So then we're we're looking at
MATTEO COLLINA: What is happening here, for some reason, this caching is not working through NPX. But if you look inside the Node
JASON LENGSTORF: What was it called? Node Modules Cash?
MATTEO COLLINA: Yep.
JASON LENGSTORF: I also feel like I'm not getting this to work.
MATTEO COLLINA: I don't know why it's picking it up on the export.
JASON LENGSTORF: I have a hunch maybe we can put this into...let's go Node Modules Cache. Nah, this isn't going to work. All right. So, this is my fault because I my my Bash is so jacked up from, like, the million things that I install every week so I'm pretty sure
MATTEO COLLINA: Try running it on the same line. Node.modules.cache.equals.
JASON LENGSTORF: This was Node and we're going into Node Modules. And that's it.
MATTEO COLLINA: Yeah. Okay. This is running.
JASON LENGSTORF: Okay. So that's running.
MATTEO COLLINA: Put "time."
JASON LENGSTORF: Do I need to put the time in front?
MATTEO COLLINA: No. Try putting the quotes between the .cache. Time needs to be there. Yeah.
JASON LENGSTORF: Oh, whoops.
MATTEO COLLINA: I don't know why your system is not
JASON LENGSTORF: It is fighting me.
MATTEO COLLINA: I have no idea what you've got on your Bash, man.
JASON LENGSTORF: It's a mess. [Laughter].
MATTEO COLLINA: Sorry. It's the wrong variable. It's Node Compile Cache. Do an "export node compile cache." Try that. I don't know why your Bash is.
JASON LENGSTORF: I'm pretty sure if we
MATTEO COLLINA: "Node compile cache."
JASON LENGSTORF: There it goes.
MATTEO COLLINA: Runtime Node.
JASON LENGSTORF: Heyyyy. Now we're cooking with gas.
MATTEO COLLINA: No, no. Wait a second. It went for 120 milliseconds to 018.
JASON LENGSTORF: It went 75% after we hit that cache. So that's that's ridiculous. And then it gets yeah. It sits right around, like, .06.08.
MATTEO COLLINA: Try zapping the cache. Rm.rf.cache. Run it again.
JASON LENGSTORF: 127 and then we run it again and now that it's cached, it's fast.
MATTEO COLLINA: You need to run it a few times.
JASON LENGSTORF: It's about .08. That's a 30percent improvement? 35%.
MATTEO COLLINA: Yeah.
JASON LENGSTORF: Yeah. And, like, we're literally parsing a Hello World here.
MATTEO COLLINA: This the TypeScript. This is the TypeScript executable. You're not running that.
JASON LENGSTORF: Oh, it's not parsing this one for us?
MATTEO COLLINA: You need to execute do the compiling. I don't know why it's not picking it up. I don't know why TSC's not compiling it.
JASON LENGSTORF: There we go. That picks it up and now that's .4 and then we run it again.
MATTEO COLLINA: Zap the cache. You're running the full project. So...
JASON LENGSTORF: And then run it like this?
MATTEO COLLINA: This is without the cache.
JASON LENGSTORF: Uhhuh.
MATTEO COLLINA: And then you're doing it again. You get that, I don't know, 3050 millisecond out of the way on startup. The more modules you load, the bigger this becomes, the more benefit you got. So, this is now, this is we got that out of the way. Let me show you something so nice.
If you go install TSX highlight. You can use TS Node, but I don't know the syntax.
JASON LENGSTORF: TSX?
MATTEO COLLINA: Yes. It's superfast. What you could do, for running your index.ts file, you could do "nodeimport=tsx." Yep. And you put the index.ts file.
JASON LENGSTORF: There we go.
MATTEO COLLINA: You can do with Watch.
JASON LENGSTORF: Oh, right. If I come in here...look at that, y'all. We didn't have to install I don't know how to pronounce it. Nodemon? They trolled in the "About" for it. I was like, come on, give me an answer. [Laughter].
MATTEO COLLINA: You can have a selfrestarting system. You have this without anything you know, if you use TypeScript, you will have to use a compiler. Okay. And, Node.js is not going to ship a TypeScript compiler within Node. Okay. One, specific reason is the TypeScript team does not recommend it to. Why? Because Node.js because TypeScript is, uh, phenomenal, like, saying the TypeScript is a language, it's not necessarily correct. TypeScript is I call it a multiverse of languages. If we added to include compile TypeScript by default, we will have to define, in stone, what's the config, like Dino has done.
My friends at Bloomberg, the first thing we did, this is the "ts.configure.json" for the company. We are likely to do that for all the Node.js users because there is a special relationship between TypeScript and Node. This is one of the critical things we are not shipping so you still need to install TypeScript or TSX or TS Node.
Let's do a change. In this thing, we can add a type module because we really like ESM. Or, actually, even better...so, remove that. Scrap that. We're done with it. Now, create a new file, over there, called "serving.js."
JASON LENGSTORF: .ts or .js?
MATTEO COLLINA: .js. Here, you use import. We're not doing anything. You can do import, okay, and you let's do "import create server." You need to extract it.
JASON LENGSTORF: It's a named one?
MATTEO COLLINA: Yes. From Node. They decided to put the Node prefix in there. Essentially, a right of firstchoosing on names, we can never overwrite everybody. We did that.
JASON LENGSTORF: That's a good move. What is
MATTEO COLLINA: You need to put a handler. You still use events. On request, unfortunately. Like, a lot of people don't know this. So, Server you need to put "server.on." And "request." And all function requests and response.
JASON LENGSTORF: Okay.
MATTEO COLLINA: Very oldschool.
JASON LENGSTORF: And so I can do something like
MATTEO COLLINA: You want to respond so you do "console log." Yep.
JASON LENGSTORF: And then we return
MATTEO COLLINA: No, you can't. This is part of the stuff I want to change
JASON LENGSTORF: Oh, right. Right. You need to request. The first one is the request. Yep, exactly.
MATTEO COLLINA: That doesn't exist. "End.send." This is the part that we did not improve. This has been the same since ever and ever so we didn't break you. This is the reason you can run your project for 2015 and it will still work just fine.
Now, what's actually cool here is, now you have to actually start your server. You know you called "server.listen," as you've always done...
JASON LENGSTORF: Server.listen.
MATTEO COLLINA: And you put in your port.
JASON LENGSTORF: We'll do 3000 because that's the classic. Now do I just Node server?
MATTEO COLLINA: It will throw a big error to you.
JASON LENGSTORF: Okay. Let's look at big error. "Cannot use import statement outside of a module." We're using the import syntax instead of the Require syntax.
MATTEO COLLINA: You have a flag. You go back in your terminal. You can do Node.js, at the top, before "server.js," you need to put, before "server," "experimentaldetectmodule."
JASON LENGSTORF: Ooohhh. Cooool. Okay. So, then, head over, here, we'll go to Localhost 3000. And it sends back...our response here. And then I've got my request coming in there, as well? Dope. This is great.
MATTEO COLLINA: Okay. The other big thing that everybody is complaining about, okay, is require ESM. And this is part of what was shipped in Node 20. Okay. Which, it's actually quite nice. So, let me okay. So, what you can do, for example, let's say that you want to, um...you know, write copy this module and let's do a CJS version of it. Okay.
JASON LENGSTORF: CJS version of this?
MATTEO COLLINA: Index.js. Yep.
JASON LENGSTORF: And you want me to do it as, like, a .cjs?
MATTEO COLLINA: Yep. Sorry. I did a mistake. Okay. I wanted the server one, not this one.
JASON LENGSTORF: Oh, I gotcha.
MATTEO COLLINA: Let's do a CJS version of it. Let's say you want to you know yep. Go back yep.
JASON LENGSTORF: Here.
MATTEO COLLINA: And this is what yep, exactly. This will work, the exact same thing. Okay. This is nice. Okay. Now, you run this. You can run this and now, what you can also do, okay, if you create another file called "foo.mjs." It's a module. A lot of people, you started publishing modules as ESM. Here, you do export "export function," yep. And you yep. That's fine. Yep. So, in "server.cjs," this is our server, what you can do, now, we can do "const."
JASON LENGSTORF: Call it "something."
MATTEO COLLINA: And you can require that file.
JASON LENGSTORF: That's exciting. We had to do an "await import."
MATTEO COLLINA: Yep. Passing in the flag...yep. And now if you run this, this will not work, you need server.cjs. And this will not work because it's you're missing something. Okay. Still a new flag, it's called "experimentalmodule."
JASON LENGSTORF: Okay. I guess we don't need the "detect module" this time, do we?
MATTEO COLLINA: No, we don't. Now, it actually works.
JASON LENGSTORF: It works and we get our ESM. This is going because we're also sending it to a web browser so we send an options request and do a "get request." So that's why we're getting multiple requests coming through.
MATTEO COLLINA: You've got two because of the [Indiscernible] request. You got your requests. So, it's it's pretty nice. Okay. You can get this done pretty quickly.
JASON LENGSTORF: I mean, this this. So, two things that I think are worth kind of pointing out. Huge complaints in the ecosystem have been about the the challenges of common JS and ES Modules and the interoperability of the two. No dependencies, other than TypeScript, we have one ES version where we're running this server as an ES Module, and we are importing it, all working in Node with no parsing, no transpiling, no detection, no webpack, no anything. It just works.
MATTEO COLLINA: Yep.
JASON LENGSTORF: That's huge.
MATTEO COLLINA: And I want to thank all the people who made it possible because it's not that all of these came for like, all of this came from a lot of sweat from a lot of people. Okay. And it's it's actually quite insane how the fact that all of this works in this way and it's it's been a [Indiscernible] effort. You need to have this support on top of existing things. It's not about everybody wanted to do this from the beginning, okay. The problem is that there was a lot of other challenges that we have been able to overcome, okay, in the latest few years.
Like, you would imagine that we broke everybody. Everybody was so damn pissed at Node team when we changed the Loaders format last year. Without that specific change, these things would not have been possible. So these things a lot of people say, Node.js has done this because x did something or y did something else. More or less, a lot of this stuff were in the plans, okay. It just that, um like, the idea of people, but we were blocked by certain changes. Okay. So, moving the loaders to another thread allowed us synchronous communication with that. So we could actually run a lot an asynchronous loader while doing a Require ESM and blocking the main thread because the loader can run asynchronously on the other side. It's pretty cool.
JASON LENGSTORF: Really, really cool stuff.
MATTEO COLLINA: All of this is actually freaking complex. It's really, really complex.
JASON LENGSTORF: Yeah. I mean, the the sometimes, I get I get a wild hair and I tell myself I'm going to go mess with an AST transformation so I can get a little bit of code and do something magic and I realize how deep this rabbit hole goes. I'm just trying to get an image tag from Markdown to HTML and the folks working on these lower levels are literally transpiling formats from one completely incompatible spec to one that is completely seamless. This is some some absolute [Indiscernible] magic.
MATTEO COLLINA: The point is doing it without breaking everybody. And support all the use cases people want to use ESM with. So and, you know, if ESM was built to only be executed synchronously, you will not have an "await import." You just have an import. In fact, all of these also work, for example, with Remote Loading of software. You can actually remove load the JavaScript file from an HTTP source. I haven't tested it. This is the [Indiscernible] there is a lot of fear and you can explain all the things. It's in very great details. Okay.
And, basically, the spec was bad. Then in 2019, the spec was fixed. Then...the word went kaboom, there was a lot of shuffling on the project and [Indiscernible] picked up the threads and thanks to, I think, Bloomberg, who funded their work for this. There was somebody that put the money where their mouth was and
JASON LENGSTORF: Yeah.
MATTEO COLLINA: And funded the work because Node.js is a project run by volunteer. We don't have magical money. Platformatic has magic money, we are trying to build a company. Node.js is not a company, it is a group of volunteers. People if you want to make something happen with Node, you need to do it. If you need to spend, I don't know, a month doing something, somebody needed to pay for your bread. If you're employed with a company, some margin for your employer, too. So, um...yeah. Thanks to all the people that contribute to Node and fund Node.js work. If you are a company that are watching this and you say, I have a bug with Node, I want it fixed, maybe ask, how can we get how can we pay somebody to do the fix? Okay. Essentially. This is a very, very important part. How can we pay somebody to do the fix for us or? How can we send the money?
If you ask, or something, it's and by the way, it will be fantastic to a lot of $10 sponsorship. But, to be honest, $10 sponsorships are not necessarily you need a lot of them. A huge lot to start making the dent. Okay. It's considered that Node.js, right now, as more or less, something around 100 collaborators working on it and maybe 50 very active ones so there's a lot of people working on this every single day and a lot of them are just literally working to keep the lights up. We're not talking about security.
Something I want to show you about a couple other features we shipped, in the last couple of years, go back to the Node.js one because I like it. Okay. Now, a very interesting feature is in the util modules, two features, okay. If you go in the util module, you can see there's been a few very nice things being shipped. So, the first one is Parse Args.
JASON LENGSTORF: Is it "util" or "utils?
MATTEO COLLINA: Parse Args is what you use to parse the argument of your code that are coming. So, you can do, for example, something like "const." You can copy. It's probably quicker than me telling you. So, you can just copy that. Okay. I just pasted it in the chat.
JASON LENGSTORF: Oh, you put it in the chat. Okay.
MATTEO COLLINA: You can go into the first link. There's stuff you can copy.
JASON LENGSTORF: Okay. Great. So, then we're going into Parse Args.
MATTEO COLLINA: Yep.
JASON LENGSTORF: So we get Parse Args.
MATTEO COLLINA: Yep. And then you can copy something like that.
JASON LENGSTORF: Okay. And now this, here, these options, this is, like, validation?
MATTEO COLLINA: Yep. And parsing.
JASON LENGSTORF: Oooooooohhhhhhh. That's okay. So, then [Laughter].
MATTEO COLLINA: A lot of people again, it's again, blog post from 2015. So, now you can you need to inside Args, you need to put you can just delete that line. Instead there, you can do...process.arg.
JASON LENGSTORF: What is happening?
MATTEO COLLINA: Args.
JASON LENGSTORF: Okay.
MATTEO COLLINA: Try that.
JASON LENGSTORF: Okay. And so here, I go, server.js, and I can say
MATTEO COLLINA: Foo. That will not work.
JASON LENGSTORF: That one doesn't work. I did it wrong.
MATTEO COLLINA: No.
JASON LENGSTORF: Oh, it [Laughter]. It worked because the validation is there so, if I do one of these and I make this into a string...now it'll work because we put the validation together.
MATTEO COLLINA: Yeah.
JASON LENGSTORF: Oh, my god. This is incredible. We used to need yargs. There were whole packages dedicated to this. Yeah, yeah. And so, to have this just built in, that's a gamechanger because now to build a CLI
MATTEO COLLINA: Even better, what you can do is use another thing in util, which is Type X.
JASON LENGSTORF: So we don't
MATTEO COLLINA: Let's say that you want to create your chat message, you do "style text." It's a function, so you put in the color that you want. So, let's say, you say green. And then you can do "values.i," I think?
JASON LENGSTORF: Values.i.
MATTEO COLLINA: Values. Let's try that. Remember what was in the yeah. Let's run it.
JASON LENGSTORF: Oh, no, look at that. Holy crap.
MATTEO COLLINA: If you put that inside an array, the green, if you put the
JASON LENGSTORF: Green inside an array. Got it.
MATTEO COLLINA: Then you add a comma and you got a string, like, underlined, under underline. Yep. Try again...
JASON LENGSTORF: Like, I mean this is this is exactly what I loved about how jQuery influenced the browser, we saw what everybody needed out of JavaScript and that got built back into the browser, the platform. This is the same thing. Node, everybody was using Commander Yargs, everybody was using Chalks. Everybody was using all these different packages. You can look at I don't know how common this is, cow paths. If you observe where the cow paths are, that's where you lay down, like, structure and so you bring that in and you make that possible so now we don't need all of those like, the amount of effort that I have spent trying to figure out what the best package is to do colored text, what the most uptodate way to do command lines
MATTEO COLLINA: Sorry. The funnest part of this is there was so much pushback on shipping because they were rightfully, a little bit concerned that their module would be affected. Okay. Now, part of this is, everybody like color text. So, at some point, Node.js decided, well, we need this feature in so we actually need to produce color text. Okay. And after we got the feature in, then the question was, well, you know, we might as well make it public.
JASON LENGSTORF: Right. Yeah.
MATTEO COLLINA: So, there is that. Okay. Um, so, I like, this is a lot to talk, probably, about the test runner, okay, too. It's pretty cool. I don't know if you want to go there. Before we go there, though, I want to show you a couple of other features.
JASON LENGSTORF: Okay.
MATTEO COLLINA: So let's do another bit of a fun example of something nice. So, one of my personal pain, in ESM, when doing ESM, was getting the current directory. I could never remember how to get it. How could I get the current directory of an ESM. Do you know, Jason?
JASON LENGSTORF: I don't remember how to get I knew how to get the directory in CommonJS but not in ESM.
MATTEO COLLINA: You can do "console.log." No need to import anything. Console.log. Import.data.[Indiscernible].
JASON LENGSTORF: We just get it now? Oh, that's huge. Also, look at this, we get process and the import.meta in the same file.
MATTEO COLLINA: Process was always there. You don't get "require."
JASON LENGSTORF: Oh, that's cool. So then, down here we've got
MATTEO COLLINA: Go up. Go up. Now we're going to use a new feature that ships in 22. Go at the top and you do...go up at the top, "import." I named ours "glob." From Nodefs/promises. This does exactly what it says it does.
Over there, you go we glob this. We want to glob that thing.
JASON LENGSTORF: I need to await it?
MATTEO COLLINA: No, you don't. No, no. You do very nice "for await." Okay. It's not, "for await."
JASON LENGSTORF: Wait, wait, wait. "Const file of"?
MATTEO COLLINA: Glob. And await after the parenthesis at the beginning. Before, sorry, the parenthesis at the beginning.
JASON LENGSTORF: There we go.
MATTEO COLLINA: Log file.
JASON LENGSTORF: And, we can style this up. Look at it go. Here we go.
MATTEO COLLINA: Let's try that.
JASON LENGSTORF: Okay. So, now, I'm going to restart it...
MATTEO COLLINA: This is this is fine. We need the glob patterns so you need to [Indiscernible].
JASON LENGSTORF: Right.
MATTEO COLLINA: After that, you need to add a string. Unfortunately, you need to concat that. You need a "path join."
JASON LENGSTORF: Let's do it this way.
MATTEO COLLINA: You want the slash. You are missing a slash. Yep.
JASON LENGSTORF: Okay. So then we do one of these and, holy crap, look at us go. We've got this is awesome. Like, this is this is great because these are the types of things that I'm always trying to do. I want access to the file system. I want to, you know, print something out that looks like. There's a million things that I need to do, when I'm building a CLI or I'm working in one of my backend services and knowing that this is just built into Node 22 and beyond this is all 22?
MATTEO COLLINA: All of this is in 22. It's some of it will be backported. Some of it can't be backported. It's a hitormiss.
JASON LENGSTORF: Gotcha. Gotcha. This is slick. This looks fantastic. Okay. And so I just we got about 15 minutes before we'll have to start winding down and I know you wanted to look at the test runner.
MATTEO COLLINA: There is one more, uh, thing I want to show here. Okay.
JASON LENGSTORF: Okay.
MATTEO COLLINA: Remove the "//." Remove the server. Document it out so at least it's yeah, okay. Perfect. It's fine. So we just get the output.
JASON LENGSTORF: Okay. Whoops.
MATTEO COLLINA: Yep. Here we go...okay. So...cool. Okay. A few files. Okay. So, let's say that we want to read the files. Okay. I want to show this to you because it's actually quite what you will do oldschool is different from what you will do it today. This is not necessarily new stuff. This is stuff we shipped around 20192020. But a lot of people haven't realized this is possible. If you go at the top, okay, you add we add we add "import create read stream," as a named import, from "node fs." If you scroll down, now we have the path. If the file ends with .js, "if files ends with .js." And remove the dot. We have a bunch of files.
You can do "conststream=createstream." We want to read all the chunks and make it capitalized. Okay. To do that, oldschool, we'll say "use on data." The output will be garbled. However, we can process them onebyone so what you can do is, um, "for await." And "constchunkofstream." And then you can do console log and use the green color so now we can do "chunk.tostring" and "uppercase," or something. Let's try that.
[Laughter].
JASON LENGSTORF: Look at it go. Oh, my god.
MATTEO COLLINA: The amount of code, these five or ten lines, the amount of code these replaced
JASON LENGSTORF: I mean, it's incredible. Like, the these are the sorts of things that when I was getting started in Node, and I would try to do something where I was reading files or I was getting into the file system, this was the stuff that always tripped me up because there were a lot of packages I needed and I was jumping between docs and unless they were using the stack I was using, I would have to think through how to match the code. The fact that this is all part of Node now, it makes it feel...so much less intimidating and it makes me feel...like I'm lesshesitant to reach for this type of solution now. I can just, oh, yeah. I can just grab the contents of that file because it's six lines of code. [Laughter].
MATTEO COLLINA: Yes. And you can and, we have also a tool called Watch that works in the exact similar way. If you not this one. Sorry.
JASON LENGSTORF: Not this one?
MATTEO COLLINA: If you go to the top of the same file, next to "glob," "comma watch." And now you can, if you scroll, command that line and duplicate that line. Put "glob" on the previous one so we don't lose it. Command 20 out.
JASON LENGSTORF: Oh, my god.
MATTEO COLLINA: And remove the "**"at the end. Now it stays up because the files is is watching. Now, save this file...oh.
JASON LENGSTORF: Text argument must be of type string.
MATTEO COLLINA: What we did wrong? No, no. Scroll down...
JASON LENGSTORF: The text argument must be of type string. 22. I know why.
MATTEO COLLINA: That's an object.
JASON LENGSTORF: That's just me, trying to consolelog something that can't be.
MATTEO COLLINA: File.filename. And import.
JASON LENGSTORF: Okay.
MATTEO COLLINA: Yep. Try that...save. Ha!
JASON LENGSTORF: And then down here
MATTEO COLLINA: You never reach.
JASON LENGSTORF: See...incredible. Like, this is this is this would be so hard 10 years ago.
MATTEO COLLINA: Yeah. Don't you know, don't
[Laughter].
No, no. Sorry. This is just hard, like, two years ago or three years ago and not ten. So, this is it's actually pretty cool, okay. It could build up a lot of these capabilities, stepbystep, and a [Indiscernible] is actually the correct feeling that I want to that I want to pass, okay.
So, I want to spend, I don't know, 1015 minutes T. It's let's take let's write a very simple file to do an addition. Okay. Something, like, a file that does 2+2. You can write in Java in TypeScript, if you like. This is fine. Write a test. This module is fine. Okay. We
JASON LENGSTORF: Do the do the test here?
MATTEO COLLINA: No, write a new file called create a new folder, sorry. Call it "test." Okay. And then you yeah, whatever you want there. I don't care.
JASON LENGSTORF: Is the test written in TypeScript?
MATTEO COLLINA: Yeah, yeah, no, we are going to use the new import the loader. So, we do "import test." From "Node column test." Yep. And then we import that module. So, "import foo." From...you need "..foo.js." Sorry.
JASON LENGSTORF: This one?
MATTEO COLLINA: This is fine.
JASON LENGSTORF: Okay.
MATTEO COLLINA: Then, you can do "test."
JASON LENGSTORF: Let's have this one actually return something.
MATTEO COLLINA: Then you can do "test." And, something, for example. And pass a function inside to it. Yeah, you can use error function, if you like it. If you're crazy, like me, you can not do that.
Then, you do we need an assertion. You can use whatever you want. But we have the Assert Module in Node. You do "import." It's not a name thing. You can do "assert." And "fromnode:assertionstrict." And you see TypeScript is complaining because it doesn't know about this module. You want "assert.equal."
JASON LENGSTORF: Assert.equal. Okay.
MATTEO COLLINA: Now, we do in the main folder sorry, in your console, you do "nodetestimport= tsx." Run it. Oh, it didn't run anything. Unfortunately, there's still a bug. You need to "test star."
JASON LENGSTORF: Come on...
MATTEO COLLINA: Look at how fast it was.
JASON LENGSTORF: Ridiculouslyfast.
MATTEO COLLINA: [Indiscernible].
JASON LENGSTORF: Right. Right. And so this is what we get when it doesn't pass.
MATTEO COLLINA: Also does with "watch."
JASON LENGSTORF: Oh, I can watch this? Oh, oh, yeah, let's watch this. Okay. So, this one is failing.
MATTEO COLLINA: Yep.
JASON LENGSTORF: So then I fix it. "Test did not finish before its parent and was canceled."
MATTEO COLLINA: Wait, let's see...oh! Because you are doing sorry. Scroll down. This is okay. Sorry, I need to see the index.ts.
JASON LENGSTORF: Index.ts. So, "test did not finish before its parent and was canceled." So is that because this is async?
MATTEO COLLINA: No, but it's fine. Should be fine. Remove the async, but I don't think it'll change anything.
JASON LENGSTORF: Canceled. Huh.
MATTEO COLLINA: Veerry odd.
JASON LENGSTORF: Do we need to await this?
MATTEO COLLINA: That's not the problem. It's, um...
JASON LENGSTORF: But it doesn't do that when you just run it straight, so it's something in Watch.
MATTEO COLLINA: It's something in Watch, that is the combination of TypeScript and Watch is still they import in Watch. Okay. It's tricky. Okay. Um, yeah. To be honest, it's in theory, you can. In practice, bugs. [Laughter]. I am I am
JASON LENGSTORF: I mean, the cancellation of the test file, itself, is, like, okay, if you know that that's what you're doing, you know you can ignore that.
MATTEO COLLINA: Now, one more thing here, that's very nice, you can pass arguments to that function. So you can, for example for example, if you run in your code sorry, in your terminal, in your console, run it with "only."
JASON LENGSTORF: Like that?
MATTEO COLLINA: Now, nothing's running.
JASON LENGSTORF: Okay.
MATTEO COLLINA: Because...it's like, if passing the actual file, okay. "only/index.ts." Because all of these is because there's no it's there's nothing. You can add "only" as an option after no. Yeah, that will work. Yeah.
JASON LENGSTORF: And there it goes...so, basically and then, does that change if I do this, here?
MATTEO COLLINA: Yeah. No, that tells you, you have specified "only."
JASON LENGSTORF: Oooookay. Okay. Yeah. So, it'll run everything if you have "only." But if you want to isolate a test, you can add the ".only." That is real slick.
MATTEO COLLINA: It's a feature everywhere. I use it all the time. Okay.
JASON LENGSTORF: Is this the sort of thing yeah, it's built in. Is there an inverse? I can say, I know this test is broken skip it.
MATTEO COLLINA: Skip.
JASON LENGSTORF: And then, with this one.
MATTEO COLLINA: It's skipped.
JASON LENGSTORF: And we're on to the next one and it shows us which one we skipped.
MATTEO COLLINA: Something really cool we can't really demonstrate this super easily. There's a really nice repo from one of the other TSC members, called Reporters. I put it in the chat.
JASON LENGSTORF: Copy link. Here we go...
MATTEO COLLINA: Okay. Scroll down. You can do this, you can pass these reporters. Now, the important part is reporter/getup. If you open it up, it will probably show a picture of it. Yeah, you will see [Indiscernible] your PR.
JASON LENGSTORF: That's handy.
MATTEO COLLINA: Yeah, it is. I use it all the time.
JASON LENGSTORF: Well, and the fact so, this is so, you need the reporter module, but the rest of it is using the builtin
MATTEO COLLINA: Exactly. You can pass them as a commandline arguments. If you scroll down, you can do "testreporter." You can add when do whatever you need from this.
JASON LENGSTORF: Extremely cool. And so the reporters, themselves yeah, this is great. And so this also means, then, presumably, you can write a reporter for any destination, like, if you wanted to report errors to your Slack, you could write a reporter for Slack. Whatever, anywhere you wanted to put that information, you have the ability to go and build one of these.
MATTEO COLLINA: Exactly. [Indiscernible] code is very if you go inside here.
JASON LENGSTORF: Yeah, let's peek at one of these.
MATTEO COLLINA: Do the GitHub one because I played with it so I know. You can just open the index.js.
JASON LENGSTORF: So we've got everything going on. How big is this? 120 lines of code to report to GitHub, which I imagine is one of the more, like, involved use cases because it requires networks requests and API keys.
MATTEO COLLINA: No. It works with changing the output and landing specific comments. If you scroll down, you can see that there is some of those things. It uses the GitHub Core Module. So, if you go up, you can see that it imports a Core Module and it's yeah. [Indiscernible] and that's what does the trick. But in the end and then you can see, there's a "for await," this kind of stuff.
JASON LENGSTORF: Okay. I see what's happening here. This is this is slick. And then, yeah, you add some extra pieces here to grab out the right details, but this is this is pretty like, I don't know. Chat, I hope your gears are turning on the types of things that open up with this. You can probably do this with other test runners, as well, but the fact that you don't need the other test runners, you can use Node Test it's just nice to think about how much project you can build without having to install a bunch of additional projects.
MATTEO COLLINA: Yes, yes, absolutely. So, this is what I wanted to go on. And we didn't talk about Fetch.
JASON LENGSTORF: Because Fetch is guilt in now.
MATTEO COLLINA: Yes. And you can thank me and the rest of the team. Back in 2018 there's a video on YouTube of me. The path of getting this to Core. Last October, we were able to call it stable. So, it took, I don't know...a few years to get there, okay. And, right now, we are still investing a lot of effort in making it faster because it's still slow, from old point of view. But we are working a lot on making it faster, making it better, all sorts of things.
It's great and it just works out of the box so you know how use Fetch, more or less, it works case. We are improving. We're getting there.
JASON LENGSTORF: Extremely cool. So, we are we are effectively out of time so I'm going to send everybody back to your Twitter if they want to follow along with what you're doing, what you're working on. [Laughter]. You made Fetch happen. [Laughter]. You can go find the Node docs here...and, is there anywhere else you want people to go?
MATTEO COLLINA: To be clear, this was a massive team effort. I laid out the plan and everybody else did the work. I worked on the lowlevel piece to make it happen, the lowlevel API that made it possible, then other people, like [Indiscernible] and Ethan and a lot of others contributed back and get this where it is right now. It's not just me. Absolutely. I'm not trying to I'm just saying my basic contribution was, this was the plan. [Laughter]. And, you know, I throw the built the first version and then everything happened after that.
JASON LENGSTORF: So, where else should people go if they want to dig deeper? Is there a specific article or a resource you'd recommend?
MATTEO COLLINA: On Fetch or what?
JASON LENGSTORF: On modern Node.
MATTEO COLLINA: It is a problem. There isn't much. The website contains a lot of it. Probably still we need a lot of help on how do we communicate this in the best way, in a better way. Okay. Part of me being here, Jason, is for sharing it with others, making it making it possible telling people these exist, okay, because, to be honest, a lot of people don't, okay. All the stuff is not there. We are currently thinking of starting an ambassador programs an ambassador program, for Node, to help us teach people all this new stuff. Okay. Which is not there. A lot of people don't know about it. How can we tell people how to use all of this? Okay.
And of course
JASON LENGSTORF: And so, this is a good note to anybody watching. If anybody's out there thinking, I want to write more, I want to create more, I want to make more videos, there's a huge wealth of new information about Node that is not being covered so this is a great way to kind of help push the web forward with your content because if we can make enough content that it starts to take the place of those articles that are being pushed now, that show 10yearold Node code, we can modernize the whole internet together so this is a good opportunity to get out there and build some projects using these new features and write articles about how maybe you don't need the dependencies. You can actually build it with builtin Node modules. Those are really impactful things that you can do right now.
MATTEO COLLINA: Exactly. So, yeah. Like, volunteers. Node.js is built on volunteers. We have no we have nobody directly funding the work. Okay. There are a lot of volunteers and their companies sponsor their work. Okay. And, but there's no straight on anybody working on this on the project.
The only person that is working fulltime is helping us on security. We have some money from the [Indiscernible] but only working on security. Very active on the security front. Okay. And as you probably all know, ships a lot of security releases. And, you know, you should upgrade to latest Node.
[Laughter].
Pretty please. The world will thank you.
A lot of you still not using that, so, there is I don't know how to fix it, but a lot of people you, you're watching, you should upgrade now.
JASON LENGSTORF: Right now. Do it today. [Laughter].
MATTEO COLLINA: You're not updating Node. Your Node is not uptodate. Okay. The numbers tell me that Node you're not updating Node. So, part of my presentation was, you're not updating Node. So you can and, that's cool. Okay. So, yeah, that's that's all of it and thank you for having me, Jason, and thank you, all, everybody, for watching.
JASON LENGSTORF: Yeah, thank you so much for being here, Matteo. One more shoutout to Nx and Netlify. Thank you to Vanessa for doing the live captioning today. While you're checking things out on the site, make sure you go and check out the schedule because we've got so much good stuff coming up. Get over there, check it out. Hit the "like" button. Get on the newsletter. Do all the things. Thank you all, so much, and we will see you next time.
MATTEO COLLINA: Bye, bye, byeeee.
JASON LENGSTORF: Okay. Bye, for real. [Laughter].
Learn With Jason is made possible by our sponsors: