48
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 to raw-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
> esbuild-ng-cli@0.0.0 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
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
let me know in the comments if those or any other extension are interesting for you.
48