40
How to build angular cli application with esbuild
Are you curious if it's possible to build ng-cli generate application with esbuild - js bundling tool that is gaining popularity because of it very fast speed? It is, at least with a simplify proof-of-a-concept app; and with a bit of tweaking to the code.
My starting point is esbuild command shown & discussed in:
and code generated with ng-cli:
$ npx -p @angular/cli ng new esbuild-ng-cli
probably due to some recent package updates, I needed to tweak dependencies before the installation passed.
We need few more steps to build with esbuild. First, installing esbuild as dependency:
$ npm install esbuild --save-dev
added 1 package (...)
Then we need build script. As we are not yet doing complete migration to esbuild, I'll leave npm run build
as it was created - on webpack, and add dedicated esbuild
script:
"esbuild": "esbuild src/main.ts --bundle --outfile=dist/main.js --loader:.html=text --minify"
There are few things included in this command:
-
src/main.ts
- is the script entry point - from there esbuild start finding all dependecies -
--bundle
- tell esbuild to bundle all files into one bundle file -
--outfile=dist/main.js
- the target of our build -
--loader:.html=text
- makes HTML files interpreted as strings. It's similar toraw-loader
in webpack -
--minify
- minimize our code. It's not as effective as angular main configuration, but it's much better than leaving code unoptimized.
The necessary tweaks to the code, is to replace src/app/app.component.ts
with:
import { Component } from '@angular/core';
import template from './app.component.html';
@Component({
selector: 'app-root',
template,
// styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'esbuild-ng-cli';
}
templateUrl
is replace by explicit template load, and css import I dropped to simplify the proof-of-a-concept application.
For the TS complication to accept the HTML import, we need to add index.d.ts
with:
declare module "*.html" {
const content: string;
export default content;
}
With those changes in place, we can already see the build passing:
$ npm run esbuild
> [email protected] esbuild
> esbuild src/main.ts --bundle --outfile=dist/main.js --loader:.html=text --minify
dist/main.js 761.1kb
⚡ Done in 124ms
The speed is impressive - less than 1 second. Unfortunately the bundle size is much bigger than one produce by native setup - 170.87kB, but build time almost 13s.
Note that the esbuild specific changes brake the standard webpack build - we would need some tweaks to have those two coexists without troubles.
For quick testing the app, we will use quick & dirty html; inspired by the webpack output. The ./index.html
:
<!DOCTYPE html><html lang="en"><head>
<meta charset="utf-8">
<title>EsbuildNgCli</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<body>
<app-root></app-root>
<script src="dist/main.js"></script>
</body></html>
if we visit our page now, it will fail with:
Error: In this configuration Angular requires Zone.js
in the browser console. We can address it by adding one line to ./src/main.ts
:
import 'zone.js';
import { enableProdMode } from '@angular/core';
/** the rest of the file **/
this increases the bundle size to 798.2kb
- my course about esbuild
- You can see the working example at: https://marcin-wosinek.github.io/esbuild-ng-cli/
You can find the whole codebase in this repository:
marcin-wosinek / esbuild-ng-cli
Proof of a concept for esbuild script for ng cli generated project
This topic could be expanded in multiple ways
- more real work application
- adding css support
- setting up dev server with esbuild
- real esbuild & webpack coexistence - maybe it makes sense to have quick dev & heavily optimized production build
- schematics for generating esbuild-friendly code immediately with ng-cli
- some other code generators set up with esbuild
let me know in the comments if those or any other extension are interesting for you.
40