perf: latest tsickle to tree shake: abstract class methods & interfaces (#18236)

In previous version of tsickle abstract class methods were materialized.
The change resulted in 6Kb savings in angular.io bundle.

This change also required the removal of `@private` and `@return` type
annotation as it is explicitly dissalowed by tsickle.

NOTE: removed casts in front of `makeDecorator` due to:
https://github.com/angular/devkit/issues/45

```
 14938 Jul 19 13:16 0.b19e913fbdd6507d346b.chunk.js
  1535 Jul 19 13:16 inline.d8e019ea3cfdd86c2bd0.bundle.js
589178 Jul 19 13:16 main.54c97bcb6f254776b678.bundle.js
 34333 Jul 19 13:16 polyfills.4a3c9ca9481d53803157.bundle.js

 14938 Jul 18 16:55 0.b19e913fbdd6507d346b.chunk.js
  1535 Jul 18 16:55 inline.0c83abb44fad9a2768a7.bundle.js
582786 Jul 18 16:55 main.ea290db71b051813e156.bundle.js
 34333 Jul 18 16:55 polyfills.4a3c9ca9481d53803157.bundle.js

main savings: 589178 - 582786 = 6,392
```

PR Close #18236
This commit is contained in:
Miško Hevery 2017-07-19 14:01:28 -07:00 committed by Miško Hevery
parent 7ae7573bc8
commit b7a6f52d59
21 changed files with 40 additions and 55 deletions

View File

@ -42,7 +42,7 @@ jobs:
key: angular-{{ .Branch }}-{{ checksum "npm-shrinkwrap.json" }} key: angular-{{ .Branch }}-{{ checksum "npm-shrinkwrap.json" }}
- run: bazel run @io_bazel_rules_typescript_node//:bin/npm install - run: bazel run @io_bazel_rules_typescript_node//:bin/npm install
- run: bazel build ... - run: bazel build packages/...
- save_cache: - save_cache:
key: angular-{{ .Branch }}-{{ checksum "npm-shrinkwrap.json" }} key: angular-{{ .Branch }}-{{ checksum "npm-shrinkwrap.json" }}
paths: paths:

View File

@ -1,6 +1,6 @@
{ {
"name": "angular-srcs", "name": "angular-srcs",
"version": "4.3.0-beta.1", "version": "4.3.0",
"dependencies": { "dependencies": {
"@types/angularjs": { "@types/angularjs": {
"version": "1.5.13-alpha" "version": "1.5.13-alpha"
@ -4818,7 +4818,7 @@
} }
}, },
"tsickle": { "tsickle": {
"version": "0.21.6" "version": "0.23.4"
}, },
"tslib": { "tslib": {
"version": "1.7.1" "version": "1.7.1"
@ -4878,7 +4878,7 @@
"version": "0.0.6" "version": "0.0.6"
}, },
"typescript": { "typescript": {
"version": "2.3.2" "version": "2.3.4"
}, },
"ua-parser-js": { "ua-parser-js": {
"version": "0.7.10" "version": "0.7.10"

8
npm-shrinkwrap.json generated
View File

@ -1,6 +1,6 @@
{ {
"name": "angular-srcs", "name": "angular-srcs",
"version": "4.3.0-beta.1", "version": "4.3.0",
"dependencies": { "dependencies": {
"@types/angularjs": { "@types/angularjs": {
"version": "1.5.13-alpha", "version": "1.5.13-alpha",
@ -7696,9 +7696,9 @@
} }
}, },
"tsickle": { "tsickle": {
"version": "0.21.6", "version": "0.23.4",
"from": "tsickle@0.21.6", "from": "tsickle@0.23.4",
"resolved": "https://registry.npmjs.org/tsickle/-/tsickle-0.21.6.tgz" "resolved": "https://registry.npmjs.org/tsickle/-/tsickle-0.23.4.tgz"
}, },
"tslib": { "tslib": {
"version": "1.7.1", "version": "1.7.1",

View File

@ -92,10 +92,10 @@
"source-map-support": "^0.4.2", "source-map-support": "^0.4.2",
"systemjs": "0.18.10", "systemjs": "0.18.10",
"ts-api-guardian": "^0.2.2", "ts-api-guardian": "^0.2.2",
"tsickle": "^0.21.1", "tsickle": "^0.23.4",
"tslint": "^4.1.1", "tslint": "^4.1.1",
"tslint-eslint-rules": "^3.1.0", "tslint-eslint-rules": "^3.1.0",
"typescript": "^2.3.2", "typescript": "^2.3.4",
"universal-analytics": "^0.3.9", "universal-analytics": "^0.3.9",
"vrsource-tslint-rules": "^4.0.0", "vrsource-tslint-rules": "^4.0.0",
"webpack": "^1.12.6", "webpack": "^1.12.6",

View File

@ -81,12 +81,10 @@ class CustomLoaderModuleResolutionHostAdapter extends ModuleResolutionHostAdapte
/** /**
* @internal * @internal
* @private
*/ */
export class NgTools_InternalApi_NG_2 { export class NgTools_InternalApi_NG_2 {
/** /**
* @internal * @internal
* @private
*/ */
static codeGen(options: NgTools_InternalApi_NG2_CodeGen_Options): Promise<any> { static codeGen(options: NgTools_InternalApi_NG2_CodeGen_Options): Promise<any> {
const hostContext: CompilerHostContext = const hostContext: CompilerHostContext =
@ -114,7 +112,6 @@ export class NgTools_InternalApi_NG_2 {
/** /**
* @internal * @internal
* @private
*/ */
static listLazyRoutes(options: NgTools_InternalApi_NG2_ListLazyRoutes_Options): static listLazyRoutes(options: NgTools_InternalApi_NG2_ListLazyRoutes_Options):
NgTools_InternalApi_NG_2_LazyRouteMap { NgTools_InternalApi_NG_2_LazyRouteMap {
@ -144,7 +141,6 @@ export class NgTools_InternalApi_NG_2 {
/** /**
* @internal * @internal
* @private
*/ */
static extractI18n(options: NgTools_InternalApi_NG2_ExtractI18n_Options): Promise<any> { static extractI18n(options: NgTools_InternalApi_NG2_ExtractI18n_Options): Promise<any> {
const hostContext: CompilerHostContext = const hostContext: CompilerHostContext =

View File

@ -49,11 +49,6 @@ export class RouteDef {
} }
/**
*
* @returns {LazyRouteMap}
* @private
*/
export function listLazyRoutesOfModule( export function listLazyRoutesOfModule(
entryModule: string, host: AotCompilerHost, reflector: StaticReflector): LazyRouteMap { entryModule: string, host: AotCompilerHost, reflector: StaticReflector): LazyRouteMap {
const entryRouteDef = RouteDef.fromString(entryModule); const entryRouteDef = RouteDef.fromString(entryModule);
@ -111,7 +106,6 @@ function _resolveModule(modulePath: string, containingFile: string, host: AotCom
/** /**
* Throw an exception if a route is in a route map, but does not point to the same module. * Throw an exception if a route is in a route map, but does not point to the same module.
* @private
*/ */
function _assertRoute(map: LazyRouteMap, route: LazyRoute) { function _assertRoute(map: LazyRouteMap, route: LazyRoute) {
const r = route.routeDef.toString(); const r = route.routeDef.toString();
@ -173,7 +167,6 @@ function _extractLazyRoutesFromStaticModule(
/** /**
* Get the NgModule Metadata of a symbol. * Get the NgModule Metadata of a symbol.
* @private
*/ */
function _getNgModuleMetadata(staticSymbol: StaticSymbol, reflector: StaticReflector): NgModule { function _getNgModuleMetadata(staticSymbol: StaticSymbol, reflector: StaticReflector): NgModule {
const ngModules = reflector.annotations(staticSymbol).filter((s: any) => s instanceof NgModule); const ngModules = reflector.annotations(staticSymbol).filter((s: any) => s instanceof NgModule);
@ -204,7 +197,6 @@ function _collectRoutes(
/** /**
* Return the loadChildren values of a list of Route. * Return the loadChildren values of a list of Route.
* @private
*/ */
function _collectLoadChildren(routes: Route[]): string[] { function _collectLoadChildren(routes: Route[]): string[] {
return routes.reduce((m, r) => { return routes.reduce((m, r) => {

View File

@ -231,7 +231,6 @@ class _Scanner {
* @param two second symbol (part of the operator when the second code point matches) * @param two second symbol (part of the operator when the second code point matches)
* @param threeCode code point for the third symbol * @param threeCode code point for the third symbol
* @param three third symbol (part of the operator when provided and matches source expression) * @param three third symbol (part of the operator when provided and matches source expression)
* @returns {Token}
*/ */
scanComplexOperator( scanComplexOperator(
start: number, one: string, twoCode: number, two: string, threeCode?: number, start: number, one: string, twoCode: number, two: string, threeCode?: number,

View File

@ -150,7 +150,7 @@ class _Tokenizer {
} }
/** /**
* @returns {boolean} whether an ICU token has been created * @returns whether an ICU token has been created
* @internal * @internal
*/ */
private _tokenizeExpansionForm(): boolean { private _tokenizeExpansionForm(): boolean {

View File

@ -401,7 +401,6 @@ export class BindingParser {
* @param propName the name of the property / attribute * @param propName the name of the property / attribute
* @param sourceSpan * @param sourceSpan
* @param isAttr true when binding to an attribute * @param isAttr true when binding to an attribute
* @private
*/ */
private _validatePropertyOrAttributeName( private _validatePropertyOrAttributeName(
propName: string, sourceSpan: ParseSourceSpan, isAttr: boolean): void { propName: string, sourceSpan: ParseSourceSpan, isAttr: boolean): void {

View File

@ -202,7 +202,6 @@ function _buildFromEncodedParts(
* $6 = <undefined> query without ? * $6 = <undefined> query without ?
* $7 = Related fragment without # * $7 = Related fragment without #
* </pre> * </pre>
* @type {!RegExp}
* @internal * @internal
*/ */
const _splitRe = new RegExp( const _splitRe = new RegExp(

View File

@ -151,7 +151,7 @@ export interface Injectable {}
* @stable * @stable
* @Annotation * @Annotation
*/ */
export const Injectable: InjectableDecorator = <InjectableDecorator>makeDecorator('Injectable'); export const Injectable: InjectableDecorator = makeDecorator('Injectable');
/** /**
* Type of the Self decorator / constructor function. * Type of the Self decorator / constructor function.

View File

@ -201,8 +201,7 @@ export type ContentChildren = Query;
* @stable * @stable
* @Annotation * @Annotation
*/ */
export const ContentChildren: ContentChildrenDecorator = export const ContentChildren: ContentChildrenDecorator = makePropDecorator(
<ContentChildrenDecorator>makePropDecorator(
'ContentChildren', 'ContentChildren',
(selector?: any, data: any = {}) => (selector?: any, data: any = {}) =>
({selector, first: false, isViewQuery: false, descendants: false, ...data}), ({selector, first: false, isViewQuery: false, descendants: false, ...data}),

View File

@ -400,7 +400,7 @@ export interface Directive {
* @Annotation * @Annotation
*/ */
export const Directive: DirectiveDecorator = export const Directive: DirectiveDecorator =
<DirectiveDecorator>makeDecorator('Directive', (dir: Directive = {}) => dir); makeDecorator('Directive', (dir: Directive = {}) => dir);
/** /**
* Type of the Component decorator / constructor function. * Type of the Component decorator / constructor function.
@ -683,7 +683,7 @@ export interface Component extends Directive {
* @stable * @stable
* @Annotation * @Annotation
*/ */
export const Component: ComponentDecorator = <ComponentDecorator>makeDecorator( export const Component: ComponentDecorator = makeDecorator(
'Component', (c: Component = {}) => ({changeDetection: ChangeDetectionStrategy.Default, ...c}), 'Component', (c: Component = {}) => ({changeDetection: ChangeDetectionStrategy.Default, ...c}),
Directive); Directive);
@ -724,8 +724,7 @@ export interface Pipe {
* @stable * @stable
* @Annotation * @Annotation
*/ */
export const Pipe: PipeDecorator = export const Pipe: PipeDecorator = makeDecorator('Pipe', (p: Pipe) => ({pure: true, ...p}));
<PipeDecorator>makeDecorator('Pipe', (p: Pipe) => ({pure: true, ...p}));
/** /**

View File

@ -191,4 +191,4 @@ export interface NgModule {
* @Annotation * @Annotation
*/ */
export const NgModule: NgModuleDecorator = export const NgModule: NgModuleDecorator =
<NgModuleDecorator>makeDecorator('NgModule', (ngModule: NgModule) => ngModule); makeDecorator('NgModule', (ngModule: NgModule) => ngModule);

View File

@ -263,7 +263,8 @@ export function Class(clsDef: ClassDefinition): Type<any> {
*/ */
export function makeDecorator( export function makeDecorator(
name: string, props?: (...args: any[]) => any, parentClass?: any, name: string, props?: (...args: any[]) => any, parentClass?: any,
chainFn?: (fn: Function) => void): (...args: any[]) => (cls: any) => any { chainFn?: (fn: Function) => void):
{new (...args: any[]): any; (...args: any[]): any; (...args: any[]): (cls: any) => any;} {
const metaCtor = makeMetadataCtor(props); const metaCtor = makeMetadataCtor(props);
function DecoratorFactory(objOrType: any): (cls: any) => any { function DecoratorFactory(objOrType: any): (cls: any) => any {
@ -298,7 +299,7 @@ export function makeDecorator(
DecoratorFactory.prototype.toString = () => `@${name}`; DecoratorFactory.prototype.toString = () => `@${name}`;
(<any>DecoratorFactory).annotationCls = DecoratorFactory; (<any>DecoratorFactory).annotationCls = DecoratorFactory;
return DecoratorFactory; return DecoratorFactory as any;
} }
function makeMetadataCtor(props?: (...args: any[]) => any): any { function makeMetadataCtor(props?: (...args: any[]) => any): any {

View File

@ -47,6 +47,14 @@ export function main() {
class SomeService extends Base {} class SomeService extends Base {}
// Move back into the it which needs it after https://github.com/angular/tsickle/issues/547 is
// fixed.
@Component({template: '<div someDir>{{1 | somePipe}}</div>'})
class TestComp3 {
constructor(service: SomeService) {}
}
function resetTestEnvironmentWithSummaries(summaries?: () => any[]) { function resetTestEnvironmentWithSummaries(summaries?: () => any[]) {
const {platform, ngModule} = getTestBed(); const {platform, ngModule} = getTestBed();
TestBed.resetTestEnvironment(); TestBed.resetTestEnvironment();
@ -150,15 +158,10 @@ export function main() {
}); });
it('should use NgModule metadata from summaries', () => { it('should use NgModule metadata from summaries', () => {
@Component({template: '<div someDir>{{1 | somePipe}}</div>'})
class TestComp {
constructor(service: SomeService) {}
}
TestBed TestBed
.configureTestingModule( .configureTestingModule(
{providers: [SomeDep], declarations: [TestComp], imports: [SomeModule]}) {providers: [SomeDep], declarations: [TestComp3], imports: [SomeModule]})
.createComponent(TestComp); .createComponent(TestComp3);
expectInstanceCreated(SomeModule); expectInstanceCreated(SomeModule);
expectInstanceCreated(SomeDirective); expectInstanceCreated(SomeDirective);

View File

@ -43,7 +43,7 @@ let _inFakeAsyncCall = false;
* {@example testing/ts/fake_async.ts region='basic'} * {@example testing/ts/fake_async.ts region='basic'}
* *
* @param fn * @param fn
* @returns {Function} The function wrapped to be executed in the fakeAsync zone * @returns The function wrapped to be executed in the fakeAsync zone
* *
* @experimental * @experimental
*/ */
@ -121,7 +121,7 @@ export function tick(millis: number = 0): void {
* of time that would have been elapsed. * of time that would have been elapsed.
* *
* @param maxTurns * @param maxTurns
* @returns {number} The simulated time elapsed, in millis. * @returns The simulated time elapsed, in millis.
* *
* @experimental * @experimental
*/ */

View File

@ -27,7 +27,6 @@ export class Title {
constructor(@Inject(DOCUMENT) private _doc: any) {} constructor(@Inject(DOCUMENT) private _doc: any) {}
/** /**
* Get the title of the current HTML document. * Get the title of the current HTML document.
* @returns {string}
*/ */
getTitle(): string { return getDOM().getTitle(this._doc); } getTitle(): string { return getDOM().getTitle(this._doc); }

View File

@ -215,7 +215,6 @@ const NON_ALPHANUMERIC_REGEXP = /([^\#-~ |!])/g;
* resulting string can be safely inserted into attribute or * resulting string can be safely inserted into attribute or
* element text. * element text.
* @param value * @param value
* @returns {string} escaped text
*/ */
function encodeEntities(value: string) { function encodeEntities(value: string) {
return value.replace(/&/g, '&amp;') return value.replace(/&/g, '&amp;')

View File

@ -327,7 +327,7 @@ describe('tsc-wrapped', () => {
main(basePath, {basePath}) main(basePath, {basePath})
.then(() => { .then(() => {
const out = readOut('js.map'); const out = readOut('js.map');
expect(out).toContain('"sources":["other_test.ts"]'); expect(out).toContain('"sources":["other_test.ts","../test.ts"]');
done(); done();
}) })
.catch(e => done.fail(e)); .catch(e => done.fail(e));
@ -361,7 +361,7 @@ describe('tsc-wrapped', () => {
main(basePath, {basePath}) main(basePath, {basePath})
.then(() => { .then(() => {
const out = readOut('js.map'); const out = readOut('js.map');
expect(out).toContain('"sources":["other_test.ts"]'); expect(out).toContain('"sources":["other_test.ts","../test.ts"]');
done(); done();
}) })
.catch(e => done.fail(e)); .catch(e => done.fail(e));

View File

@ -2,4 +2,4 @@
set -u -e -o pipefail set -u -e -o pipefail
bazel build ... bazel build packages/...