On November 8th, 2023, Angular 17 was unveiled, marking what many in the community describe as the most exciting major release of the framework so far. A pinnacle of a movement that, as Minko Gechev describes in his blogpost, has "been picking up momentum with improvements such as signal-based reactivity, hydration, standalone components, directive composition, and dozens of other features."
The community calls this movement the Angular renaissance. Coined by Alyssa Nicoll this term gives captures the essence of the ongoing improvements of the framework: “That’s why I relate [this] to the Renaissance, because not only is there just a bunch of activity and freshness and creativity coming in, but also it’s geared towards the developer experience.” (DX)
Like the Renaissance, the recent Angular development emphasizes the humanist aspect of growth and potential, focusing on enhancing DX to make Angular more user-friendly for all.
Central to the developer experience is the speed of the development server. There's an incredible difference between fast startup times and seeing changes in the source code reflected (almost) instantly in the browser or a substantial initial startup time and subsequent waiting for tens or twenty seconds for the application to recompile. At least equally important, given its impact on both developers and end-users, is the production build process. It has to be fast even for large applications and needs to produce optimized bundles that ship the smallest amount of JavaScript possible to the user to satisfy both the developer and the end user.
From webpack to Vite & esbuild: ESM, Bundlers, and the evolution of the JavaScript ecosystem
Before ECMAScript modules (ESM) were available in browsers, developers had no native mechanism for authoring JavaScript in a modularized fashion. This is the reason we have tools like webpack that crawl the source code, then process and combine our modules into files that he browser can execute. Without a doubt, by enabling modularized development of frontend code, they significantly enhanced the developer experience when they were initially introduced.

webpack – turning modularized dependencies into static assets
But as our applications become more complex, the quantity of JavaScript we have to work with also grows significantly. It is common for large projects to contain thousands of modules. At that size, JavaScript-based bundlers like webpack, we are beginning to reach a performance ceiling. Because JavaScript is single threaded, it can take a very long time (often even minutes) to start up a development server and recompile our modifications.
This also applies to the build process. Although native ESMs are now widely supported, shipping unbundled ESMs in production is still inefficient due to the additional network round trips caused by nested imports. To get the optimal loading performance in production, we bundle our code with tree-shaking, lazy-loading and common chunk splitting (for better caching). No matter how big our application is, we still need this bundling to happen as quickly as possible.
How can we address these issues? We leverage the rise of JavaScript tools written in compile-to-native languages, and combine them with the availability of native ES modules in the browser for development. Specifically, the Angular team chose esbuild and Vite to power it's CLI's ng serve and ng build commands.
Let's take a closer look at these tools and how Angular uses them!
esbuild: Go-ing fast bundling JavaScript
The main goal of the esbuild project is to bring about a new era of build tool performance and, in the process, create an easy-to-use modern bundler. Many of the widely used build tools for the web, and consequently our own application builds, are tens to hundreds of times slower than they should be, if the comparison below is any indication:

How come esbuild is so much faster? It is developed with the Go programming language, which compiles to native code. Other bundlers are mostly written in JavaScript. This means they run on NodeJS, which has to spend extra time to parse the JavaScript code.
Additionally, printing, parsing, and source map creation can all be done simultaneously with esbuild. Whenever possible, its algorithms have been programmed to utilize all available CPU cores. Written in Go, which has parallelism at its heart, esbuild can use memory more wisely than any JavaScript tool. As you might know, by design JavaScript is limited to a single call stack for program execution. On the other hand, it should be mentioned that esbuild does lack some of the functionalities of tools like webpack. Its primary goal is speed.
If you want to learn more about esbuild I recommend this article.
Vite for Speed: Faster and leaner application development
Our second tool of choice is Vite. Vite is French for "quick", pronounced like "veet", and is a build tool that aims to provide a faster and leaner development experience for modern web projects.
It consists of two major parts:
- A dev server build around the idea of leveraging modern browsers and their native ES module capabilities.
- A build process that bundles your code with Rollup, pre-configured to output highly optimized static assets for production.
Fast & lean during development
Vite's development server serves source code over native ESM. It transfers some of the work normally performed by a bundler to the browser, requiring Vite to only modify and send source code when requested by the browser. Code behind conditional dynamic imports is only processed if actually needed on the current screen. Compare this to an approach that requires your entire application to be analyzed and bundled all before it can even display your initial page.
Did you notice that we highlighted source code? That is because Vite is smart enough to divide the modules in an application into source code and dependencies.
Because dependencies are typically provided in plain JavaScript and don't change all that much, especially while running the development server, Vite actually pre-bundles them using our new friend esbuild. This ensures CommonJS and UMD compatibility, as Vite must convert dependencies that are shipped as CommonJS or UMD into ESM first. It also improves performance for dependencies that ship their ES modules builds as many separate files importing one another: Nested imports set off a sequence of HTTP calls for their internal dependencies and the large amount of requests creates network congestion on the browser side, causing the page to load noticeably slower. Fast esbuild pre-bundling is therefore well worth the small initial overhead.
Smart & extensible during build
When it comes to the build process, Vite tries to give you an opinionated experience with sensible defaults out of the box.
CSS Code Splitting, Preload Directives Generation, and Async Chunk Loading Optimization are all automatically applied and there is no need for explicit configuration unless you want to disable them. It also offers an amazing Plugin API with full type support, which makes the process highly extensible. The build pipeline is built on top of RollUp, Vite's underlying JavaScript bundler. Yes, you read it right—Vite uses a bundler based on JavaScript for its build process and trades off speed for extensibility in this instance. That is at least for the time being, as the Vite team recently announced RollDown, a project that aims to develop a Rust (compile to native) based port of RollUp that runs as quickly as esbuild.
Angular & esbuild & Vite – Tools inside a closed process
Now that we are familiar with both esbuild and Vite, let's see how the Angular team uses these incredible tools to bring their development & build experience to a new level.
Starting with the team's CLI philosophy will help clarify later decisions about what to utilize and when. The team does not want you to be concerned with the internal workings of scaffolding, developing, upgrading, or translating applications. They view the CLI as a closed system. For the user, each one of those should only ever be one command. That way you can focus on building an application to your needs, while Angular takes care of fine tuning and performance optimizations of the development and build processes.
With this knowledge in mind, the team's decisions become very clear:
ng build with esbuild

When building for production, the Angular CLI uses esbuild for bundling your application and writing the resulting static files to disk. One thing I did not mention earlier is that while esbuild also supports plugins, they come with a lot more complexity as they cannot be simply chained together the same way RollUp/Vite plugins can. However, this is not an issue with the "closed" nature of the Angular CLI dev/build process. The CLI, written by a team of experts that have deep knowledge of the Angular internals, can orchestrate the use of plugins and take full advantage of esbuild's incredible speed.
For instance, in the new implementation, the entry points are passed to esbuild only after ngc & TypeScript are called directly to type-check the code and generate JavaScript for the client and server. Only after, the entry points are passed to esbuild, which produces final bundles with output optimized based on annotations from Angular's build optimizer. This enables smallest possible bundle sizes, while also being much faster than previous solutions.
ng serve with Vite

As you may have probably guessed, this means that Vite serves only as the development server for the Angular CLI. It still takes advantage of the fast cold starts and dependency pre-bundling that Vite provides out of the box. On top of that the CLI uses an internal plugin that makes sure that requests for Angular source code is rendered correctly and requests for static files are read from the disc and returned. However, with how Vite is currently used as part of the Angular CLI, you do not get access to Vite's incredible plugin system, which can be used to extend both development and build processes.
The team has to make this trade-off in order to make the experience as simple as possible for most consumers. Angular believes in abstractions with best defaults to make it easier for you. All you need to know is ng serve, ng build, and ng update.
The benefit of these high level abstractions? Last year, Angular's build optimizer was replaced by babel transform. All that was needed for developers to adopt and benefit from those changes was running ng update. It would likely take years for all of the millions of developers that use Angular to adapt these changes if they were to manually modify their build pipelines. Thanks to the closed nature of the Angular CLI, by updating to the new version of the CLI everyone saw their build improve automagically.
_The diagrams above are from an incredible talk given by Minko Gechev at ViteConf. Make sure to watch it here.*
Analog & Vite – Angular as Vite Plugin
But suppose we fully embraced Vite? What if we took full advantage of it and made the most out of the tool's mind blowing plugin ecosystem? What if we had access to the thousands of community built extensions that users can tap in to build their applications? What if Vite was more than an "implementation detail". What if instead Angular would become a Vite plugin?
Luckily thanks to the incredible work of Brandon Roberts we don't have to only imagine what this would look like. He has developed a community-built Vite plugin that enables us to both launch an Angular development server and use Vite to build Angular applications.
Brandon has turned Angular into a Vite plugin! Better yet, he went on to create the perfect use case of a Vite powered Angular experience: The AnalogJs metaframework.
AnalogJs leverages the power of Vite plugins to not only serve and build Angular applications, but connect them with UnJs' powerful Nitro server.
Together, AnalogJs, Nitro & Vite enable Server Side Rendering, Static Site Generation, file-based routing, markdown support, and straightforward deployments to a plethora of cloud based hosting providers! Transforming Angular from a primarily enterprise SPA option to a cutting edge solution similar to NextJs and Nuxt!
So how does Analog use Vite to give Angular these superpowers?
1. vite-plugin-angular – Angular as a Vite Plugin
It all starts with the vite-plugin-angular. Similar to the "official" internal plugin that the Angular team uses in its Vite-powered CLI dev server, it tells Vite (with the help of Angular Compiler) how to transpile Angular source files into JavaScript. The main difference is that it does this during not only during development, but also enables us to use Vite's production build pipeline giving us full access to the plugin ecosystem.
2. vite-plugin-nitro – Expanding Vite based Angular with its own server
Now that we have access to Vite plugins we leverage them in a powerful way: We augment our vanilla Angular application with the vite-plugin-nitro. This plugin adds a full-blown Nitro backend server to our app. Nitro is an open source TypeScript framework to build ultra-fast web servers, that are built to be deployed to NodeJs or edge based environments of (almost) every major cloud provider. Even better, our AnalogJs plugin takes care of all the internal configuration necessary to "teach" Nitro how to render Angular applications server side! This means that by combining vite-plugin-angular & vite-plugin-nitro we can already build full-stack Angular applications that can be deployed to Netlify, Vercel, Cloudflare, AWS, etc. in minutes.
3. File based routing – It just makes sense
However, AnalogJs doesn't stop there. Leveraging Vite's capability to read and transform source files, the framework creates an Angular compatible route configuration solely based on your folder structure and file names. Each file inside your pages directory will represent a route in your application. That makes visualizing and managing your app easier as the pages directory structure reflects all existing routes. No more manual wiring up of routes is necessary! This plays exceptionally well with Nitro, which uses a similar concept of file-based routing for API routes!
4. You can write markdown? You can create Analog pages!
AnalogJs takes file-based routing one step further! The framework comes with a content renderer that allows us to turn .md files into AnalogJs pages! Once more, leveraging Vite's capabilities to read and transform source files it even knows how to extract frontmatter meta-data that you associated with your page. This makes AnalogJs a fantastic tool for marketing pages or personal blogs! It really becomes as simple as adding another Markdown file to expand your AnalogJs applications!
6. analog – One plugin to rule them all
All this functionality is packaged in one simple Vite plugin. This means that to get all that functionality all you have to do is add this to your vite.config.ts:
/// <reference types="vitest" />
import { defineConfig } from 'vite';
import analog from '@analogjs/platform';
// https://vitejs.dev/config/
export default defineConfig(({ mode }) => ({
...
plugins: [analog()],
...
}));
Ready to check out AnalogJs, but not sure where to start? The AnalogJs' team has got that covered, too! Set up your application is as easy as running a single command:
npm create analog@latest
To Vite or not to Vite? That is the question.
As you can see, Vite is a really strong tool, and having access to the ecosystem lets us develop some amazing features that have the potential to not just enhance but even completely transform the Angular experience! Not only that, but AnalogJs' Vite integration makes it possible to use Angular in Qwick and Astro projects as well!
Nevertheless, it is also undeniable that there is a great deal of friction involved in developing and maintaining AnalogJs on top of Vite, while keeping it compatible with an Angular that might move in a completely different direction. Any of the internal improvements that the Angular team ships with it's own builder are not reflected in the Vite plugin and have to be ported over (to the best of the communities abilities) after the fact. For Analog users, the knowledge of the experts that working with Angular's internals every day are not automagically included when a new version of the framework is released.
Those are significant trade-offs, which the Analog team finds important enough to consider moving the Analog meta-framework onto the new, official, Vite, and esbuild powered tooling and maintaining a separate vite-plugin-angular to bring Angular to Astro, Qwick, and the rest of the Vite ecosystem.
Brandon did a great job of laying out both sides in more detail in this RFC and we invite you to please read through it and give us your feedback on what you believe is the best alternative for you!
To Vite or not to Vite? That is the question.
Thank you & more to come
Thank you to @brandontroberts for his incredible work with AnalogJs and his willingness to share his time and wisdom helping me create this article.
Thank you to Preston Lamb and Matthieu Riegler for their feedback and help!
As always, do you have any further questions or suggestions for blog posts? I hope this gives you a good overview of what's new in Angular tooling and how AnalogJs leverages Vite. Finally, I hope this inspires read the RFC and participate in the conversation! We are curious to hear your thoughts. Also, please don't hesitate to leave a comment or send me a message.
Finally, if you liked this article feel free to like and share it with others. If you enjoy my content follow me on Twitter or Github.