1 | # Angular Build Optimizer
|
2 |
|
3 | Angular Build Optimizer contains Angular optimizations applicable to JavaScript code as a TypeScript transform pipeline.
|
4 |
|
5 |
|
6 | ## Available optimizations
|
7 |
|
8 | Transformations applied depend on file content:
|
9 |
|
10 | - [Class fold](#class-fold), [Scrub file](#scrub-file) and [Prefix functions](#prefix-functions): applied to Angular apps and libraries.
|
11 | - [Import tslib](#import-tslib): applied when TypeScript helpers are found.
|
12 |
|
13 | Some of these optimizations add `/*@__PURE__*/` comments.
|
14 | These are used by JS optimization tools to identify pure functions that can potentially be dropped.
|
15 |
|
16 |
|
17 | ### Class fold
|
18 |
|
19 | Static properties are folded into ES5 classes:
|
20 |
|
21 | ```typescript
|
22 | // input
|
23 | var Clazz = (function () { function Clazz() { } return Clazz; }());
|
24 | Clazz.prop = 1;
|
25 |
|
26 | // output
|
27 | var Clazz = (function () { function Clazz() { } Clazz.prop = 1; return Clazz; }());
|
28 | ```
|
29 |
|
30 |
|
31 | ### Scrub file
|
32 |
|
33 | Angular decorators, property decorators and constructor parameters are removed, while leaving non-Angular ones intact.
|
34 |
|
35 | ```typescript
|
36 | // input
|
37 | import { Injectable, Input, Component } from '@angular/core';
|
38 | import { NotInjectable, NotComponent, NotInput } from 'another-lib';
|
39 | var Clazz = (function () { function Clazz() { } return Clazz; }());
|
40 | Clazz.decorators = [{ type: Injectable }, { type: NotInjectable }];
|
41 | Clazz.propDecorators = { 'ngIf': [{ type: Input }] };
|
42 | Clazz.ctorParameters = function () { return [{type: Injector}]; };
|
43 | var ComponentClazz = (function () {
|
44 | function ComponentClazz() { }
|
45 | __decorate([
|
46 | Input(),
|
47 | __metadata("design:type", Object)
|
48 | ], Clazz.prototype, "selected", void 0);
|
49 | __decorate([
|
50 | NotInput(),
|
51 | __metadata("design:type", Object)
|
52 | ], Clazz.prototype, "notSelected", void 0);
|
53 | ComponentClazz = __decorate([
|
54 | NotComponent(),
|
55 | Component({
|
56 | selector: 'app-root',
|
57 | templateUrl: './app.component.html',
|
58 | styleUrls: ['./app.component.css']
|
59 | })
|
60 | ], ComponentClazz);
|
61 | return ComponentClazz;
|
62 | }());
|
63 |
|
64 | // output
|
65 | import { Injectable, Input, Component } from '@angular/core';
|
66 | import { NotInjectable, NotComponent } from 'another-lib';
|
67 | var Clazz = (function () { function Clazz() { } return Clazz; }());
|
68 | Clazz.decorators = [{ type: NotInjectable }];
|
69 | var ComponentClazz = (function () {
|
70 | function ComponentClazz() { }
|
71 | __decorate([
|
72 | NotInput(),
|
73 | __metadata("design:type", Object)
|
74 | ], Clazz.prototype, "notSelected", void 0);
|
75 | ComponentClazz = __decorate([
|
76 | NotComponent()
|
77 | ], ComponentClazz);
|
78 | return ComponentClazz;
|
79 | }());
|
80 | ```
|
81 |
|
82 |
|
83 | ### Prefix functions
|
84 |
|
85 | Adds `/*@__PURE__*/` comments to top level downleveled class declarations and instantiation.
|
86 |
|
87 | Warning: this transform assumes the file is a pure module. It should not be used with unpure modules.
|
88 |
|
89 | ```typescript
|
90 | // input
|
91 | var Clazz = (function () { function Clazz() { } return Clazz; }());
|
92 | var newClazz = new Clazz();
|
93 | var newClazzTwo = Clazz();
|
94 |
|
95 | // output
|
96 | var Clazz = /*@__PURE__*/ (function () { function Clazz() { } return Clazz; }());
|
97 | var newClazz = /*@__PURE__*/ new Clazz();
|
98 | var newClazzTwo = /*@__PURE__*/ Clazz();
|
99 | ```
|
100 |
|
101 |
|
102 | ### Prefix Classes
|
103 |
|
104 | Adds `/*@__PURE__*/` to downleveled TypeScript classes.
|
105 |
|
106 | ```typescript
|
107 | // input
|
108 | var ReplayEvent = (function () {
|
109 | function ReplayEvent(time, value) {
|
110 | this.time = time;
|
111 | this.value = value;
|
112 | }
|
113 | return ReplayEvent;
|
114 | }());
|
115 |
|
116 | // output
|
117 | var ReplayEvent = /*@__PURE__*/ (function () {
|
118 | function ReplayEvent(time, value) {
|
119 | this.time = time;
|
120 | this.value = value;
|
121 | }
|
122 | return ReplayEvent;
|
123 | }());
|
124 | ```
|
125 |
|
126 |
|
127 | ### Import tslib
|
128 |
|
129 | TypeScript helpers (`__extends/__decorate/__metadata/__param`) are replaced with `tslib` imports whenever found.
|
130 |
|
131 | ```typescript
|
132 | // input
|
133 | var __extends = (this && this.__extends) || function (d, b) {
|
134 | for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
|
135 | function __() { this.constructor = d; }
|
136 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
137 | };
|
138 |
|
139 | // output
|
140 | import { __extends } from "tslib";
|
141 | ```
|
142 |
|
143 | ### Wrap enums
|
144 |
|
145 | Wrap downleveled TypeScript enums in a function, and adds `/*@__PURE__*/` comment.
|
146 |
|
147 | ```typescript
|
148 | // input
|
149 | var ChangeDetectionStrategy;
|
150 | (function (ChangeDetectionStrategy) {
|
151 | ChangeDetectionStrategy[ChangeDetectionStrategy["OnPush"] = 0] = "OnPush";
|
152 | ChangeDetectionStrategy[ChangeDetectionStrategy["Default"] = 1] = "Default";
|
153 | })(ChangeDetectionStrategy || (ChangeDetectionStrategy = {}));
|
154 |
|
155 | // output
|
156 | var ChangeDetectionStrategy = /*@__PURE__*/ (function () {
|
157 | var ChangeDetectionStrategy = {};
|
158 | ChangeDetectionStrategy[ChangeDetectionStrategy["OnPush"] = 0] = "OnPush";
|
159 | ChangeDetectionStrategy[ChangeDetectionStrategy["Default"] = 1] = "Default";
|
160 | return ChangeDetectionStrategy;
|
161 | })();
|
162 | ```
|
163 |
|
164 |
|
165 | ## Library Usage
|
166 |
|
167 | ```typescript
|
168 | import { buildOptimizer } from '@angular-devkit/build-optimizer';
|
169 |
|
170 | const transpiledContent = buildOptimizer({ content: input }).content;
|
171 | ```
|
172 |
|
173 | Available options:
|
174 | ```typescript
|
175 | export interface BuildOptimizerOptions {
|
176 | content?: string;
|
177 | inputFilePath?: string;
|
178 | outputFilePath?: string;
|
179 | emitSourceMap?: boolean;
|
180 | strict?: boolean;
|
181 | isSideEffectFree?: boolean;
|
182 | }
|
183 | ```
|
184 |
|
185 |
|
186 | ## Webpack loader usage:
|
187 |
|
188 | ```typescript
|
189 | import { BuildOptimizerWebpackPlugin } from '@angular-devkit/build-optimizer';
|
190 |
|
191 | module.exports = {
|
192 | plugins: [
|
193 | new BuildOptimizerWebpackPlugin(),
|
194 | ]
|
195 | module: {
|
196 | rules: [
|
197 | {
|
198 | test: /\.js$/,
|
199 | loader: '@angular-devkit/build-optimizer/webpack-loader',
|
200 | options: {
|
201 | sourceMap: false
|
202 | }
|
203 | }
|
204 | ]
|
205 | }
|
206 | }
|
207 | ```
|
208 |
|
209 |
|
210 | ## CLI usage
|
211 |
|
212 | ```bash
|
213 | build-optimizer input.js
|
214 | build-optimizer input.js output.js
|
215 | ```
|