JavaScript was born in the browser, Node brought it to the server embracing unix primitives and async I/O and lately Cloudflare Workers & Deno Deploy have brought it to the edge. Let’s take a look at where JavaScript runtimes are heading and how it will shape the software we write.
The Future of JavaScript Runtimes
From:

Node Congress 2022
Transcription
Hi everyone, my name is Aron and I'd like to thank you for joining me at Node Congress. Today I'm going to talk about the future javascript runtimes. And so we're going to look at how javascript runtimes have evolved from browsers to servers and how Node and other technologies have evolved over the past decade and how that will shape the runtimes of tomorrow, the ones we'll use in five years, in 10 years. I think it's an interesting exercise. Obviously neither me or others can truly predict the future, but the interesting thing is since some of us work on runtimes, we have the ability to impact it. And so I think with this talk, I want to open up that conversation, get the conversation started and basically hear other thoughts, because I think there is a lot of room to innovate and there's still a lot of room for javascript to progress. So yeah, let's jump in. So I think, as I mentioned there, we'll look at what will runtimes look like in 2025, 2030, what new capabilities will these runtimes have, what new use cases will they enable, what kind of primitives will they have, what kind of ergonomics will they have, how will that impact the software we build and write, or how we deploy software, how we use it. I think there's a lot of different angles that we'll look at as we step through this. And so a quick disclaimer is obviously I work at deno, so I'm slightly biased. I like deno, obviously, but I would say that these are mostly my personal views. I've been working full-time on javascript runtimes for less than six months. There's people on my team at deno or even at No Congress today who have years or decades of experience building runtimes. So I'm quite new to this. And then also, of course, my talk won't be and can't be exhaustive. I'm mainly going to be focusing on the CLI and cloud side of things. Obviously, browsers and desktop and mobile are huge trends and huge facets of javascript, but that won't be the focus of today's talk. So anyway, let's jump right in. So first, let's take a look at the historical trends and how javascript has evolved, and that will inform a little bit how it might evolve in the coming decade. So let's take a quick look at the timeline. So javascript was first created by Brendan Eich in 1995 in 10 days, which is pretty extraordinary. Obviously, there came some trade-offs. And javascript continued to exist in browsers, and it was only up until 2008 when Google shipped V8 and Chrome that web applications really became a thing because V8 radically changed the performance of javascript runtimes and really enabled modern javascript-heavy applications that weren't really possible before. And then only less than nine months later, Brian then built and shipped the first version of Node in 2009. I think that Node's impact is not to be understated. We're obviously all here because of Node. Node has enabled us to build server-side applications in javascript, and it's also enabled a ton of tooling on the front-end side, etc. So I think that's quite impactful. Obviously, this timeline is not exhaustive. There's other key events, but once again, I'm trying to stick to the points that I think are relevant. And then I think another key event in the timeline is Microsoft shipping typescript in October 2012. And so it takes some time for typescript adoption to grow, but I think today we're starting to see that typescript is maybe one of the dominant forms or dialects of javascript that teams are using to build new applications. So looking back at 2010, we can see a few key trends, such as front-end. Obviously, not to say that front-end didn't exist before 2010, but it really wasn't the same game. Before 2010, you had jQuery. Now you have react, JSX, vue. And obviously, with these modern libraries came modern tools, such as Babel, ESBuild, webpack. And that also enabled modern frameworks like next.js or Tailwind css. And so front-end has changed really quite radically in the 2010s, and especially in the second half of 2010. typescript obviously came along. The TS node has somewhere in the region of 18 million downloads per week on npm. So it's really quite widespread. serverless became a thing, for better or for worse. We now have lambda, Google cloud Functions, Firebase. But I think there's a few differences between serverless, lambda, and then the modern clouds that we'll get to later in the talk. Then obviously, desktop and mobile. So yeah, a quick recap of some of the technologies that have changed. yarn came around. We switched from callbacks to promises. We switched from jQuery to react. We switched from CommonJS with requires to Atmoscript modules and imports. We switched from XHR to fetch. It's hard to understand how much javascript has changed over the past decade. And so I think when you think about javascript, obviously there's a core language. And that's not going to be the focus of my talk today. I'm not going to focus on the core language, which is still constantly evolving. There's lots of interesting things coming, like immutable records or tuples, which are extremely interesting additions that I'm looking forward to. But today I'm going to focus more on a javascript runtime, so you can think of that language plus specific primitives to an environment. And so I think when you look at javascript holistically, it was born in the browser, which gave it these core compute and document primitives. And then Node essentially brought Unix primitives into javascript, exposing Unix sockets, TCP sockets, the process model, spawning and forking child processes, all that kind of things, which have made it powerful and useful to build CLI and server applications. But I think it makes sense to ask, what's next? Are we going to stick to these same primitives or are we going to come up with new ones? And when we think about the modern cloud, should we bring cloud-first primitives into javascript? Something worth taking a look at. So yeah, I think the takeaway here is javascript is constantly evolving. It's evolved over the past 20 plus years. And then the interesting thing is we can shape its future. So let's take a first look at browsers. I won't focus too much on browsers, as I mentioned before, but I think there's some interesting, quite notable improvements that kind of impact us as Node and deno users. I think something that's quite notable here is the invention of web containers. So StackBlitz released this thing called web containers a few months ago, and it enables you essentially to run full Node-like applications in the browser. And it does it quite efficiently. It's not emulation. I don't want to get too much into it, but it essentially kind of polyfills key parts of Node and then it re-implements a TCP stack using service workers. There's a lot of interesting technology there. And I think the key thing is that it's essentially kind of Node packaged into the browser. But yeah, let's move on to that because browsers aren't the focus of today's talk. So let's take a look at CLIs such as Node, deno, Bun, and many others. And let's maybe take a look at how they might evolve in the coming decade. And so one of my first predictions is oxidation. We'll see more and more kind of core javascript runtime technology built in rust. And the reason there is C++ is nice, but it's also painful. If V8 is built in C++, it will likely never be rewritten. But rust is a much more modern language that makes it easier to build key technology. And we're already seeing this. deno is built in rust. It's got wrappers around V8 and rust. But besides V8, nearly the entirety of deno is rust. And that enables, it provides some safety guarantees, but it also, I think, increases the speed of iteration on the runtime, making it much, much more accessible for people to contribute to. We're also seeing the rise of rust in tooling such as Roam or SWC. These are pretty interesting involvements and they're mainly motivated by speed. People don't want to wait for their front-end apps to build. They don't want to wait for their linter. They don't want to wait for their formatter. So there's a lot of interesting things that are happening there. And there's been the introduction of, you know, the add-ons have evolved to an api and there is a wrapper called an NAPI.RS, which allows you to build an api modules in rust. And this is used by prisma, next.js, Rollup. So we're probably seeing kind of adoption of rust technology in the tooling and in the runtimes, both on the Node and deno side. And so I think that will continue. So this isn't so much necessarily on the runtime implementation. This is more on the ergonomics and APIs. I think we'll continue to see the quote-unquote webification. You know, Node when it first shipped didn't really align with the web APIs. And I guess also I think web APIs matured a lot over the past decade. And so a key milestone is Node is shipping ECMAScript modules, HTTPS imports, and fetch in Node 18. And that's a major step forward. I think, you know, as these web APIs have matured, I think they're essentially becoming the standard and we're able to kind of phase out some of these older legacy Node APIs in favor of standard APIs, such as, you know, Nodes require crypto being replaced by web crypto, or HTTP and HTTPS being replaced by fetch. Even though in practice, a lot of people already use Node fetch. My personal experience is that HTTP built-in APIs into Node aren't necessarily the most pleasant to use. And so I've seldom seen people use them bare bones. Anyway, moving on. I think if we move away from Node for a second and look at deno, deno very much considers web APIs as first class citizens. And it goes, yeah, we try to implement them as thoroughly as possible. We try to be as spec and plan as possible. We really think that there's a lot of value in kind of implementing these modern web APIs. And we've pushed this quite far. We run WPT tests, which are the same test that browsers run. And in fact, in some cases, deno is more spec and plan than some of these browsers. If we take a look at Node crypto, for example, deno is more spec and plan than Chrome and Firefox, only slightly behind Safari. I think it's really quite interesting to see a CLI and server runtime kind of embrace these modern web APIs that have evolved and matured over the past decade. So going back to some of the trends, we saw that typescript was a major trend of the 2010s. I think that typescript will become the de facto dialect that teams and programmers use. It's extremely widespread and there's tons of benefits to it. The tc39 organization is considering ignorable typing. And what this would allow is essentially for V8 and other javascript engines to execute typescript out of the box. I mean, they wouldn't understand the types, they'd essentially ignore them, but they would be able to essentially run typescript untransformed, which is really quite interesting. I think another evolution is JSX has changed the way we build front end. It's essential today. And I think given that it's become essentially a de facto standard, it's possibly worth considering bringing JSX into the language itself. That can be quite controversial, but there's a lot of potential upside. And as I mentioned earlier, TS Node has nearly 20 million weekly downloads, which shows huge adoption. Obviously, a lot of that's probably CI, but it's fair to say that typescript is no longer the underdog today. And Dino supports typescript out of the box because we think it deserves first class support. I think another key evolution that we'll see in the coming years is I think runtimes, Node kind of led to this explosion and all this innovation with all these different tools. And I think that was necessary and quite important, but it also leads to a lot of fragmentation day-to-day workflows. And so I think we'll see kind of consolidation with these batteries included runtimes. And we can see that here with Dino and Bun, for example, which include built-in watching, linting, formatting. I think runtimes will essentially kind of tend in this direction. Obviously, Dino's current implementation isn't perfect, but we're continuing working on it and improving it. I think one of my last points is Node is currently the dominant javascript runtime. Dino is kind of the underdog. It's up and coming and growing. And I think these two runtimes will converge. How they'll converge is still open and undecided, but I think we see different trends. We saw that the webification of these runtimes are embracing web APIs more and more, which kind of gives them these shared APIs that they can both build off. Dino has Node compatibility that can run non-trivial applications such as Express, Cua, front-end tools like vite. It can run package managers like npm and yarn. The Node compatibility hasn't officially shipped yet, and my colleague Bartak has given a talk about it, but it's really getting quite powerful. And also, Native is evolving. We're evolving beyond add-ons to Wasm and NAPI. And we're experimenting supporting NAPI and Dino out of the box. So I think there's a lot of room for Node and Dino to converge. I think the main driver there is fragmentation for developers is just not fun. It's not great. So it's one of those things that we'll kind of wait and see what happens there. But I'm looking forward to it. So moving on from CLIs, let's take a look at clouds and cloud runtimes. I think some of you may be familiar with IaaS or infrastructure as a service, which is kind of what aws defined. And so I think kind of clouds in the past decade have mainly been defined by aws, azure, JCP, and kind of the commodification of primitives such as compute and storage. And I think in the coming decade, we'll see infrastructure as a service become isolated as a service. And I'll get a little bit, I'll dive into what I think that means in a few slides. If we take a step back and kind of look at hypervisors that are used in the cloud, traditionally, we would have VM hypervisors. And VMs are, they're extremely flexible. You can run any operating system, but they're quite expensive. They take seconds to boot. And in recent years, we've seen, for example, Firecracker VMs, which are also technically VMs, but they're much lighter weight. They don't try to emulate a full machine. They still build off KVM and other key technology. We've also obviously seen the emergence of technology like LXCs and Docker, essentially containers. And so the hypervisor there, the domino hypervisor is kubernetes. And so containers are less secure than VMs, but there's a ton of improvements in DX and kind of boot performance that make these appealing. And I think the last evolution in these kind of hypervisors that we're getting to now is these isolate hypervisors. Instead of having hypervisors that juggle VMs, we're getting hypervisors that will manage isolates. And these are much, much, much, much more lightweight. They boot an order of magnitude faster than both containers and VMs. And there's a lot of interesting primitives and things that we can enable if we embrace isolates first. And so if we take a step back at one of the things, for example, that you can think about isolate hypervisors and modern isolate executables, I think there's this interesting idea of declarative entry points. And so for example, we've seen cloudflare ship this, and this is something we're actively thinking about at deno with deno Deploy. This essentially allows you to declare a program declaratively. So instead of having essentially all these declarative imports, and then having an entry point that is imperative that extracts arguments from Rv or sets up a listener, you essentially export functions. And that has a lot of interesting benefits. You can expose multiple entry points in a javascript file. So a single javascript file is now self-sufficient to describe a full program. And then it encourages this javascript first, and it's composable all the way down via imports and exports. This doesn't have to be an entry point. You can just re-import some of these functions and rewrap them again. So you can get this nice, pure javascript composability. Another thing that's enabled by these isolate hypervisors is you get these things such as, for example, when we build traditional clouds, we often have multiple services called microservices, and we'll have to talk to them. And that will often happen over the network. It will be a HTTP call or a TCP call. And I think one of the interesting things is when you have the isolate hypervisor that manages all these runtimes, it can actually, instead of sending these calls over the network, it can send them directly through memory. And so you get these really interesting gains in efficiency and things that aren't really possible in these classical abstractions, because in the classical VM setup or container setup, we're still working with IP stack as first-class citizens. Whereas here, you have essentially a fat hypervisor that profoundly understands these isolates and knows how to route between them. So yeah, when we think about why isolate hypervisors, I think the main argument is there's these extreme efficiency gains. When you're trying to run hundreds, thousands, or tens of thousands of multi-tenant programs on the same machine, that's not really possible or viable with VMs. It's not possible with containers either. Only isolates have sufficiently low overhead to enable a kind of multi-tenancy. And I also think when we look back at the cloud of the past decade, it's essentially preserves some of the key abstractions that we've been working with that have served us well but are maybe a bit outdated. And so I think these modern isolate clouds will embrace isolates instead of VMs as their compute primitive, instead of having internal IPs and VPCs and private networks and NATs that replicate traditional infrastructure. You have directly routable isolate services where you don't care where the other service is running. It could be running elsewhere in the world. It could be running on the same hypervisor machine. It gets routed. And then there's the emergence of blob and KV stores to replace block devices. And there's opportunity for these hypervisors to be as native, such as we're seeing in cloudflare workers or Dino deploy. And so with these isolate hypervisors, which are essentially kind of the implementation of the runtime, I think we'll see the emergence of a CloudWorker spec. Dino deploy and cloudflare service workers were a good starting point, but add event listener fetch is outdated. It's not the future. cloudflare still supports it. Dino deploy still supports it. But we know that we need to go beyond that. And I think the key thing here is in these clouds, we're no longer just packaging node and containers. It's truly new primitives and a new process model. And that potentially warrants a new spec. So moving on from the cloud, and there's tons more to say. But unfortunately, I only have a little bit of time. So let's take a quick look at some of the more exotic use cases that javascript could break into or how javascript runtimes could evolve. I think we can see this is not a new topic, but I think it will be revisited. We see javascript producing WASM or javascript being compiled ahead of time. So we see this both assembly script or Microsoft static typescript. I think we'll also see javascript runtimes embedded in more and more applications. Dino is built to be highly embeddable. We've seen people take Fabrice Bellard's Quick JS runtime and run that in WASM. So you get javascript in WASM hooked into a javascript runtime, which is quite interesting. And so I think in the coming decade, there's the opportunity for javascript to be embedded into more and more portions of our infrastructure. cloudflare brought javascript into the CDN, essentially. I think people might bring javascript into databases or other key parts of infrastructure and make that scriptable. I think one of the key changes in, I think, programming and software in the past decade is machine learning. It had an undeniable impact on how we build software and the products we consume. And Dino, for example, has first-class support for webgpu. And if you combine that with tensorflow.js, essentially you have the possibility to have GPU-accelerated training and inference, natively supported in a runtime. And obviously, that's Python's bread and butter today, but I think it'd be interesting to see javascript gain some ground there. And so though it's not as extreme as machine learning, Python is the de facto language for data science. And I think there's room for javascript there. At Dino, we've experimented with first-class support for Jupyter notebooks and allowing you to write typescript in these Jupyter notebooks and have charts and all that kind of just seamlessly built into a coherent experience. Yeah, so unfortunately, I don't have so much time, so I have to wrap up. But I could have spent a lot more time, I think, going into detail about the cloud side of things and these ISOL hypervisors and what they enable and the future of that at cloudflare and with Dino Deploy. But to leave you some closing questions, the web currently handles about 150 million requests per second, history requests per second. And I think it's interesting to wonder what fraction of that will be processed by some javascript runtime, whether that's Node as the upstream origin or whether that's aws's Cloudfront Edge, lambda, cloudflare Workers, Dino Deploy. I think it'll be interesting to see essentially, will there be a future where 50% of all HTTP requests go through javascript at some point, whether that's for an edge router or they're upstream? I would also like to ask you, do you think javascript is too fragmented? Do you want this consolidation? Do you want this consolidation in formatting, bundling tools? Yeah. And yeah, I mean, would you like to see javascript expand beyond development? What are your key use cases? Would you want to use javascript for microcontrollers, for game development? Yeah, I'd love to hear about these use cases. And then I think lastly, it's important to really consider typescript. Will typescript become the de facto language used for all javascript development in the future? I think it has a good shot. Anyway, I'd like to thank you all for taking the time to watch my talk and attend today. We're going to have some time for questions and answers. I'm very much looking forward to that. Here's where you can find me online. Feel free to shoot me an email or ping me on Twitter if you have any questions. And that'll be a wrap. Thank you very much, everyone. So now let's discuss the answer to your poll questions. Let's see what the people answered. So which platforms running on the edge have you used? 15% have used cloudflare workers, then 25% lambda Edge, and 15% and 15% Versa and then Deploy and 5% Netlify Edge handlers. What do you think about this, Aaron? Like, this surprised you, or this is what you were expecting? Or now it keeps moving? Yeah. I mean, in some sense, I'm not surprised. And it kind of reflects a lot of my understanding, right? cloudflare has really, I think, changed the game and people's perception of these modern kind of worker runtimes. They've done a great job at that. I think they've done a fantastic job. lambda is aws, which a lot of people use more or less indirectly. And then it's interesting to see Deploy, which is the product I work on. It's got a decent amount of usage. We're still in beta, obviously, but it's good to see traction there. So yeah, I mean, I'm pleased to see this. And yeah, I mean, I think there's a lot to go. We could maybe even talk about the differences between these edge runtimes. They all run javascript differently. They all run javascript ultimately, but there's kind of different trade-offs in each of those runtimes. Thank you. Let me go back to... So yeah. And now let's see some questions that people have asked you. So the first one is, why would you isolate clouds, replace the container clouds if they're less flexible and can only run JS and ones? That's a great question. The short answer is containers and VMs will be around for a long time still. But I think isolate clouds will replace a lot of typical usage of containers and VMs for javascript because they're much, much, much more efficient. There's a huge gains in efficiency. cloudflare has talked about some of these. I mentioned some of these in my talk, where you can have zero cost inter-service networking, much more memory efficient. They can be much more compute efficient. And I think the more interesting thing is that these isolate clouds can enable new primitives, things that weren't simply possible before. So they're not going to completely replace each other. But I think this decade will see a huge boom in people switching over from classical VMs and containers to isolates. They'll be the best place to run javascript. Thank you. James is asking, any known plans or rumor for aws to support an official dinner runtime for lambda? Yeah. I'm sorry. I think this actually came up in the Dino room earlier. So there's currently a community lambda runtime for people to run Dino on lambda. I think after this conference, I'll look into if we can talk with aws and maybe put together an official lambda layer. That's definitely something that's interesting. I think the Dino company, we want to embrace people to use Dino everywhere they can and want to, whether it's on aws or on Dino Deploy or DigitalOcean or other providers. So we'll definitely look into that. Thank you. That sounds promising. Like, yeah. James is now talking about a standard JS lib. Is that how you think Dino now will converge or do you expect one runtime to replace or the other in the limit? Yeah, that's a great question and a difficult one. I think the fragmentation is painful. So Dino and Node might not be able to coexist forever in the limit. I think five, 10 years out, they'll either merge in some form or one will replace the other. But I think to James's point, over the past decade, we've seen a lot of expansion and kind of innovation in javascript. And I think we're kind of going from an expansion phase to a consolidation phase. And I think a standard javascript library that share pre-knowledge runtimes is a great idea. So I think they'll converge there first before possibly replacing each other, one or the other. Yeah. Yeah. Thank you. So you said that Unix primitives might be obsolete in modern isolate clouds. Can you elaborate on that, please? Yeah. So I talked about this idea of isolate clouds. I really think there's a lot more to say about this. Maybe I should make that a focus of a talk. But the Unix primitives, such as the file system of processes and sockets, they've lived with us for a long time. But I mentioned, for example, this feature that cloudflare has, like zero cost inter-service communication. In a classical setup, you would need to do service discovery via DNS or some kind of console service. And then you'd have to find out, OK, what IP is this other service running on to, and then open up a socket. I think these isolate clouds, because they're much more involved in some sense with the isolates that are running, they'll provide a lot of these primitives out of the box. And when you're building applications that run around the entire world, it doesn't make sense to program for an individual process when you're building something that runs worldwide. So I think the Unix primitives have been great. They've served us well. And they'll take a long time to disappear. But I think as we start building these modern javascript applications for the cloud, we'll see them kind of phase out and we'll see new primitives emerge. And that's maybe things like first class blob storage or KV storage. cloudflare shipped KV storage. We're looking to ship that too at Deepin Deploy. And I think today, a startup called Temporal.io raised $100 million Series B, which is quite substantial. And one of the things that they changed is they changed the whole queuing cron task mechanism. They kind of reinvent those primitives in part because they're moving beyond the Unix restrictions. So it will be a big shift because developers care a lot about Unix. But I think we need to shift beyond to build programs in a more modern fashion. Very, very interesting. Agentile1990 asked, compute keeps moving closer and closer to the client. Do you feel that someday we will move to a stateful connection in the far future of the web? A stateful connection? I'm not exactly sure what they mean by that. A stateful connection between the cloud and the clients? That could be interesting. But I need to kind of understand a little more specifics of what they mean by a stateful connection. Oh, yeah. Well, maybe we can talk about that in this core with Agentile1990. Yeah, in a special chat. Yeah, in a special chat we can talk about that. So thank you. Thank you, Aaron, very much. This was great talk and great questions as well. So yeah. Well, thank you, everyone, for attending. I appreciate your time. See you all in the special chat. Yep. Thank you. Bye-bye.