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