https://a.storyblok.com/f/270183/1368x665/7d4c8cfca5/25may_dev-blog_js-adventure.png

Choose Your Own JavaScript Adventure

Published on May 28, 2025

There’s something quite remarkable about the fact that JavaScript (JS) has become the de facto second programming language for every web application developer out there. That’s pretty impressive, considering the name itself was chosen to align itself to the Java programming language despite being fundamentally completely different. I wrote last year that PHP’s success was down to its evolution, and you could certainly make the case that the only other language that has seen the same level if not more of this evolution is JS. But, how do you approach this vast stack of options? I drew inspiration from this now legendary article, which I remember reading at the time and reveling in how complex things had become. In this article, we’ll go through the origins, advantages, and disadvantages of what has made this complex ecosystem.

Origins

Graphic of the Netscape Navigator BrandingBack To The BeginningThe limitations of Vanilla JS were covered by the first big library release: jQuery. These days, jQuery tends to be the target of jokes due to the problems it solved being natively shipped into the language, but it’s probably worth noting that jQuery still has a market share of 90% on websites in 2025. The complexity of modern front-end frameworks such as Vue and React is totally offset by the simplicity of jQuery for more straightforward applications.

Node Flips The Script

Ryan Dahl really changed everything in 2009. At this point, Google’s V8 engine in the Chrome Browser, JScript in Internet Explorer, and SpiderMonkey in Firefox were the biggest runtime engines in use for their respective browsers. In a true moment of innovation, Ryan asked the question: “What if you pulled out the V8 engine and ran it on a server instead?”. And so, Node was born, not realising that every future developer would subsequently be confused with exactly how you describe what it actually is to people. Is it a framework? No. Is it JavaScript? No. “A runtime and peripheral toolchains” is the mouthful of a correct answer.

Package Management

Picture of many, boxes, chaotically stackedWatch that node_modules directory grow!Once you have a server-side language, the next logical step is to have a package management system. The Node Package Manager (npm) was the default tool for years, but as we’ve already seen, the JavaScript ecosystem rarely stands still for long. Not content with the performance that was offered with dependency resolution, Facebook created Yarn in 2016. Yarn saw the introduction of a new lock file and, importantly, offline caching. The improved performance could be seen as akin to the development of PHP7 in response to HHVM; npm consequently considerably improved its performance speeds and addressed the issues that led to the development of Yarn in the first place. Therefore, the age-old “it depends on your preference” is the realistic answer to “Which should I use?”

I ES6ed All Your Common Modules

JavaScript didn’t originally have a modular system that enabled the exporting of files and properties/functions. The rise of Node and the considerable scaling of web applications to rival native operating system applications in both the front and back end meant that this had to be addressed. This came in the form of CommonJS, a standard that allowed imports using the require() helper function.

As we’ve seen elsewhere, JavaScript is full of developers trying to solve existing problems, and one of these was Node enabling exports with CommonJS. Therefore, the permanent solution would be: how do we get native importing/exporting in JavaScript? In 2015, ECMAScript did just this with the addition of ESM (ECMAScript Modules).

In a pattern you’re probably starting to notice, you therefore have two different methods for scaling out applications. “What should I use?”, you ask. Again, the answer technically is “which one works for you”, but that’s not entirely accurate. For new projects, it’s recommended to use ESM due to it being native, and support for tree-shaking and static analysis included. 

TypeScript To The Rescue

Image of the Typescript LogoA Saviour Is BornThe thing about either JavaScript in the browser engine or Node is that it’s a weakly typed language that will attempt to pretty much run anything you attempt to do. Those from the worlds of Java, C#, and other compiled languages would probably reel in horror at the ability of JS developers to write mountains of crazy nonsensical code (and they did: I distinctly remember a frontend tool where all the arguments to the main helper function were just variables as single letters that spelled out the product, which shall remain nameless). JS always has someone to come along to address its limitations, and for this particular instance, it was Microsoft.

Microsoft developed a superset of JavaScript that brought a strong typing system in the form of both a compiler and a runtime (that can be called with npx). The adoption of TypeScript has been pretty phenomenal, especially when application requirements are likely to scale quickly. Here at Vonage, our own Node SDK saw a total rewrite by Chuck Reeves for version 3, which ported it to TypeScript.

Compiling Confusion

The introduction of npm as a package manager created a unique issue for frontend developers: a new folder named node_modules existed in projects, but how would you ship these dependencies into frontend code? Before npm, Bower handled frontend dependencies. However, npm pretty much made it redundant. Used in conjunction with npm, Grunt and Gulp would be used as task-runners, most commonly used with tooling like Babel to transpile to lower-level JavaScript.

The unified compiling solution came in the form of Webpack, which would compile an entire front end into a unified JS file based on an asset system. All CSS files, JS source files or ones from package management, image files, you name it. Throw in the Typescript compiler if you need it and you’ve got a powerful builder. There’s always a “but” though…

I worked with Webpack a lot in agency jobs and commercial enterprises, and I can tell you that with great power comes great complexity. Running it on every build is time-consuming, and the amount of times it fell over because of configuration problems made me want to routinely burst into tears. So, in the spirit of the article: guess what happened next? That’s right, someone came along and built something else. The VueJS library author (personally, Vue is the only front-end JS framework I’ve ever enjoyed working with but that’s a topic for another day) Evan You created Vite, a compiler and server written from scratch with super-high benchmarks. It was adopted quickly by Remix, Laravel, Nuxt, and Astro, which is a pretty high-profile portfolio.

Runtime Evolution: Deno and Bun.sh

Photograph of an art exhibition in a street showing the evolution of humansThe Journey Never EndsThis is the part where I really enjoyed JS’s evolution. Where Node turned the web application stack on its head, time had plans to create new problems. In 2009, Serverless and Cloud Native computation were in their infancy. By 2016, DevOps engineers had high-performance expectations when sending entire function closures in Node through cloud platforms’ compute runtimes. We had two problems by this stage: performance at the millions of events in the event loop for high-availability applications and the Node package system (which by now was also responsible for everything in the front-end as well) entering into a dependency hell of meme-like proportions.

The first problem was addressed by Node’s original creator. In 2018, Ryan announced Deno, and two years later, saw the production release of Deno. Deno couldn’t obviously “just solve” the dependency hell that had emerged out of npm overnight, but it did put various mechanisms into place that would standardise any adopters of the runtime:

  • Typescript support out of the box, thus a push towards more robust code.

  • Only using ESM modules by default, so no mix-and-match between ESM and CommonJS.

  • Removal of a default package manager. With package discovery through URLs alone, it standardised the runtime to avoid it being tightly coupled to one management tool (i.e., npm).

  • A more streamlined API. A major Node problem was that small chunks of code “became effectively core”. Absorbing the most vital libraries as a standard library and cutting the excess was a smart move, and one that possibly could stop things like a couple of lines of code breaking the internet.

So, wouldn’t the conclusion be just for everyone to move to Deno? Well, no. Because then:

Bun.sh was launched in 2021. I’ll admit that I was surprised that another server-side runtime was being released. What happened here?

Well, Deno was a reimagining of Node by its creator, with some architecture decisions to directly stop the tooling and ecosystem issues that came after Node. Bun, however, really went to town: it launched to remove the optional 3rd-party tooling essential to running server-side JS. That meant:

  • TypeScript support out of the box, the same as Deno

  • A built-in test runner

  • A built-in package manager

  • A built-in transpiler

  • A built-in bundler (think Vite or Ruby’s bundler)

All of these were built in Zig, which is comparable to new low-level programming languages that have replaced the likes of C or C++, such as Rust. “Which one should I choose, though?” I once again hear you ask. The truth is, there is no correct answer. Anyone who advocates for one will be wrong in another aspect of what they’re trying to do, and that’s just full-stack JS for you.

Conclusion

I hope you enjoyed the vast, sprawling adventure that is the evolution of JS. The thing is, there’s no right or wrong answer when it comes to choosing stacks and tools. I didn’t even get on to Astro, or Svelte, or Remix, or Nuxt, or Next. I am just a humble developer, attempting to ship software. With the grocery store of runtimes and tools available, what I can do is take suggestions on what tooling to work with on articles that use Vonage APIs? Join our thriving Developer Community on Slack, follow us on X (formerly Twitter), or subscribe to our Developer Newsletter. Stay connected, share your progress, and keep up with the latest developer news, tips, and events!

Share:

https://a.storyblok.com/f/270183/400x385/12b3020c69/james-seconde.png
James SecondeSenior PHP Developer Advocate

A trained actor with a dissertation on standup comedy, I came into PHP development via. the meetup scene. You can find me speaking and writing on tech, or playing/buying odd records from my vinyl collection.