Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(@angular/cli): add build-optimizer support #6520

Merged
merged 1 commit into from
Jul 19, 2017

Conversation

filipesilva
Copy link
Contributor

@filipesilva filipesilva commented May 31, 2017

Adds the new flag --build-optimizer (--bo), usable only with --aot (or --prod since it auto enables --aot).

This feature is experimental, and may not work correctly on your project. Should it work, total bundle size should go down. Savings are heavily dependent on the project.

See https://github.com/angular/devkit/tree/master/packages/angular_devkit/build_optimizer for details about all the optimizations applied.

Usage: ng build --prod --build-optimizer. Disabling the vendor chunk has been shown to improve total savings, and is done automatically when --bo is specified unless --vendor-chunk has a value.

Please let us know if using --build-optimizer breaks your project so we can improve it further. Repos are very welcome.

Note: the UglifyJS pure_getters option is also turned on when using --build-optimizer. If your code has side effects in property access, they will likely not work properly.

pure_getters -- the default is false. If you pass true for this, UglifyJS will assume that object property access (e.g. foo.bar or foo["bar"]) doesn't have any side effects. Specify "strict" to treat foo.bar as side-effect-free only when foo is certain to not throw, i.e. not null or undefined.

@deebloo
Copy link
Contributor

deebloo commented Jul 5, 2017

:)

} else {
commandOptions.vendorChunk = true;
}
}
Copy link
Contributor

@deebloo deebloo Jul 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

commandOptions.vendorChunk = !commandOptions.ngo ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that would be more concise 👍

@filipesilva filipesilva changed the title feat(@angular/cli): add ngo support feat(@angular/cli): add build-optimizer support Jul 11, 2017
@Koslun
Copy link

Koslun commented Jul 13, 2017

Readme link got broken, here is the new url: https://github.com/angular/devkit/tree/master/packages/angular_devkit/build_optimizer

@filipesilva
Copy link
Contributor Author

@Koslun good catch, updated 👍

Brocco
Brocco previously approved these changes Jul 14, 2017
@filipesilva
Copy link
Contributor Author

PR changed to automatically default --vendor-chunk to false when --build-optimizer is specified.

Adds the new flag `--build-optimizer` (`--bo`), usable only with `--aot` (or `--prod` since it auto enables `--aot`).

This feature is experimental, and may not work correctly on your project. Should it work, total bundle size should go down. Savings are heavily dependent on the project.

See https://github.com/angular/devkit/tree/master/packages/angular_devkit/build_optimizer for details about all the optimizations applied.

Usage: `ng build --prod --build-optimizer`. Disabling the vendor chunk has been shown to improve total savings, and is done automatically when `--bo` is specified unless `--vendor-chunk` has a value.

Please let us know if using `--build-optimizer` breaks your project so we can improve it further. Repos are very welcome.
@chriszrc
Copy link

ng serve is still working fine, but build with --prod or with --prod and --build-optimizer fails with the following cryptic error:

ERROR in ./src/main.ts Module not found: Error: Can't resolve './$$_gendir/app/app.module.ngfactory' in '/Users/anonymous/github/project/src' resolve './$$_gendir/app/app.module.ngfactory' in '/Users/anonymous/github/project/src' using description file: /Users/anonymous/github/project/package.json (relative path: ./src) Field 'browser' doesn't contain a valid alias configuration after using description file: /Users/anonymous/github/project/package.json (relative path: ./src) using description file: /Users/anonymous/github/project/package.json (relative path: ./src/$$_gendir/app/app.module.ngfactory) no extension Field 'browser' doesn't contain a valid alias configuration /Users/anonymous/github/project/src/$$_gendir/app/app.module.ngfactory doesn't exist .ts Field 'browser' doesn't contain a valid alias configuration /Users/anonymous/github/project/src/$$_gendir/app/app.module.ngfactory.ts doesn't exist .js Field 'browser' doesn't contain a valid alias configuration /Users/anonymous/github/project/src/$$_gendir/app/app.module.ngfactory.js doesn't exist as directory /Users/anonymous/github/project/src/$$_gendir/app/app.module.ngfactory doesn't exist [/Users/anonymous/github/project/src/$$_gendir/app/app.module.ngfactory] [/Users/anonymous/github/project/src/$$_gendir/app/app.module.ngfactory.ts] [/Users/anonymous/github/project/src/$$_gendir/app/app.module.ngfactory.js] [/Users/anonymous/github/project/src/$$_gendir/app/app.module.ngfactory] @ ./src/main.ts 3:0-74 @ multi ./src/main.ts

@filipesilva
Copy link
Contributor Author

@chriszrc I think you're getting #7113. The solution is to update #7113 (comment).

@chriszrc
Copy link

chriszrc commented Jul 24, 2017

Ok, I updated to 1.3.0-rc.1 and ng build --prod is back to working (nice!). However with --build-optimizer, now I've got a different error:

ERROR in ./node_modules/rxjs/observable/BoundCallbackObservable.js Module build failed: TypeError: Cannot read property 'type' of undefined at Object.getEffectiveTypeAnnotationNode (/Users/anonymous/github/project/node_modules/@angular-devkit/build-optimizer/node_modules/typescript/lib/typescript.js:9341:17) at assignContextualParameterTypes (/Users/anonymous/github/project/node_modules/@angular-devkit/build-optimizer/node_modules/typescript/lib/typescript.js:41652:25) at checkFunctionExpressionOrObjectLiteralMethod (/Users/anonymous/github/project/node_modules/@angular-devkit/build-optimizer/node_modules/typescript/lib/typescript.js:41948:29) at checkExpressionWorker (/Users/anonymous/github/project/node_modules/@angular-devkit/build-optimizer/node_modules/typescript/lib/typescript.js:42959:28) at checkExpression (/Users/anonymous/github/project/node_modules/@angular-devkit/build-optimizer/node_modules/typescript/lib/typescript.js:42898:42) at checkExpressionCached (/Users/anonymous/github/project/node_modules/@angular-devkit/build-optimizer/node_modules/typescript/lib/typescript.js:42779:38) at checkReturnStatement (/Users/anonymous/github/project/node_modules/@angular-devkit/build-optimizer/node_modules/typescript/lib/typescript.js:45418:54) at checkSourceElement (/Users/anonymous/github/project/node_modules/@angular-devkit/build-optimizer/node_modules/typescript/lib/typescript.js:46763:28) at Object.forEach (/Users/anonymous/github/project/node_modules/@angular-devkit/build-optimizer/node_modules/typescript/lib/typescript.js:1506:30) at checkBlock (/Users/anonymous/github/project/node_modules/@angular-devkit/build-optimizer/node_modules/typescript/lib/typescript.js:44563:16) at checkSourceElement (/Users/anonymous/github/project/node_modules/@angular-devkit/build-optimizer/node_modules/typescript/lib/typescript.js:46742:28) at checkFunctionExpressionOrObjectLiteralMethodDeferred (/Users/anonymous/github/project/node_modules/@angular-devkit/build-optimizer/node_modules/typescript/lib/typescript.js:41990:21) at checkDeferredNodes (/Users/anonymous/github/project/node_modules/@angular-devkit/build-optimizer/node_modules/typescript/lib/typescript.js:46828:25) at checkSourceFileWorker (/Users/anonymous/github/project/node_modules/@angular-devkit/build-optimizer/node_modules/typescript/lib/typescript.js:46863:17) at checkSourceFile (/Users/anonymous/github/project/node_modules/@angular-devkit/build-optimizer/node_modules/typescript/lib/typescript.js:46842:13) at Object.forEach (/Users/anonymous/github/project/node_modules/@angular-devkit/build-optimizer/node_modules/typescript/lib/typescript.js:1506:30) @ ./node_modules/rxjs/observable/bindCallback.js 2:32-68 @ ./node_modules/rxjs/add/observable/bindCallback.js @ ./node_modules/rxjs/Rx.js @ ./src/app/my-component/my.component.ts @ ./src/$$_gendir/app/app.module.ngfactory.ts @ ./src/main.ts @ multi ./src/main.ts ERROR in ./node_modules/rxjs/observable/BoundNodeCallbackObservable.js Module build failed: TypeError: Cannot read property 'type' of undefined at Object.getEffectiveTypeAnnotationNode (/Users/anonymous/github/project/node_modules/@angular-devkit/build-optimizer/node_modules/typescript/lib/typescript.js:9341:17) at assignContextualParameterTypes (/Users/anonymous/github/project/node_modules/@angular-devkit/build-optimizer/node_modules/typescript/lib/typescript.js:41652:25) at checkFunctionExpressionOrObjectLiteralMethod (/Users/anonymous/github/project/node_modules/@angular-devkit/build-optimizer/node_modules/typescript/lib/typescript.js:41948:29) at checkExpressionWorker (/Users/anonymous/github/project/node_modules/@angular-devkit/build-optimizer/node_modules/typescript/lib/typescript.js:42959:28) at checkExpression (/Users/anonymous/github/project/node_modules/@angular-devkit/build-optimizer/node_modules/typescript/lib/typescript.js:42898:42) at checkExpressionCached (/Users/anonymous/github/project/node_modules/@angular-devkit/build-optimizer/node_modules/typescript/lib/typescript.js:42779:38) at checkReturnStatement (/Users/anonymous/github/project/node_modules/@angular-devkit/build-optimizer/node_modules/typescript/lib/typescript.js:45418:54) at checkSourceElement (/Users/anonymous/github/project/node_modules/@angular-devkit/build-optimizer/node_modules/typescript/lib/typescript.js:46763:28) at Object.forEach (/Users/anonymous/github/project/node_modules/@angular-devkit/build-optimizer/node_modules/typescript/lib/typescript.js:1506:30) at checkBlock (/Users/anonymous/github/project/node_modules/@angular-devkit/build-optimizer/node_modules/typescript/lib/typescript.js:44563:16) at checkSourceElement (/Users/anonymous/github/project/node_modules/@angular-devkit/build-optimizer/node_modules/typescript/lib/typescript.js:46742:28) at checkFunctionExpressionOrObjectLiteralMethodDeferred (/Users/anonymous/github/project/node_modules/@angular-devkit/build-optimizer/node_modules/typescript/lib/typescript.js:41990:21) at checkDeferredNodes (/Users/anonymous/github/project/node_modules/@angular-devkit/build-optimizer/node_modules/typescript/lib/typescript.js:46828:25) at checkSourceFileWorker (/Users/anonymous/github/project/node_modules/@angular-devkit/build-optimizer/node_modules/typescript/lib/typescript.js:46863:17) at checkSourceFile (/Users/anonymous/github/project/node_modules/@angular-devkit/build-optimizer/node_modules/typescript/lib/typescript.js:46842:13) at Object.forEach (/Users/anonymous/github/project/node_modules/@angular-devkit/build-optimizer/node_modules/typescript/lib/typescript.js:1506:30) @ ./node_modules/rxjs/observable/bindNodeCallback.js 2:36-76 @ ./node_modules/rxjs/add/observable/bindNodeCallback.js @ ./node_modules/rxjs/Rx.js @ ./src/app/my-component/my.component.ts @ ./src/$$_gendir/app/app.module.ngfactory.ts @ ./src/main.ts @ multi ./src/main.ts

@cyrilletuzi
Copy link
Contributor

Are we sure we want to disable --vendor-chunk with --build-optimizer ? It's really bad for cache (every update of the app need a full reload instead of just the main script).

In my app, which is a really classic one, total size with --build-optimizer and with or without --vendor-chunk is exactly the same.

@filipesilva
Copy link
Contributor Author

@chrisfitz now that one I have no idea what it is. I know we have some problems with RxJS operators in the build optimizer (angular/devkit#51) but unsure if that's exactly it. Is this a project I can check out?

@cyrilletuzi our tests showed a marked improvement in total size by disabling vendor chunk in some projects. I haven't see any reverse case though. So it does seem more sensible to default to it for now, although that might change for a final release of it (it's still experimental).

@chriszrc
Copy link

chriszrc commented Jul 31, 2017

Hi, thanks for the link, my issue was the same as this other issue that was linked to it:

#7110

Changing my rxjs imports from:

import { Observable } from 'rxjs/Rx';

to

import { Observable } from 'rxjs/Observable';

and then adding back all the individual operators:

import 'rxjs/add/observable/merge'; ...etc

worked!

Not sure if this is the same issue as here (#7057) , but using the new --build-optimizer and trying to look at the sourcemaps to see how things are looking, you get this:

screen shot 2017-07-31 at 11 05 54 am

I can still see the local project dependencies, but all the information about vendor libraries is gone. Same with --vendor-chunk true and just looking at the vendor.bundle.

Really nice work! My js dropped ~.7 mb with the new optimizations!

@Koslun
Copy link

Koslun commented Jul 31, 2017

@chriszrc do you include changing your RxJS imports in those ~700 KB savings? Given that for most users this would save quite a lot by itself.

@chriszrc
Copy link

Hi, @chriszrc here (typo?), yes, that included rxjs import changes, I suspect the savings are mainly from that and material-

@Koslun
Copy link

Koslun commented Jul 31, 2017

@chriszrc yes, sorry, typo. And ok, makes sense. Know that tree-shaking classes should have a large effect on both RxJS and angular libraries as they both contain a lot of classes. While both RxJS and Material are quite large libraries they both allow a great deal of cherry picking.

So curious how large the effect really is on projects who already cherry pick their imports. Will investigate a bit on my own when time allows but strongly recommend https://github.com/th0r/webpack-bundle-analyzer for investigating bundle sizes. As it's both quite easy to use and largely accurate numbers unlike for example https://chrisbateman.github.io/webpack-visualizer/.

Would be quite awesome if there was just a negligible difference between cherry picking and just importing entire libraries. Though mostly for developer ergonomics it would likely overall reduce the output of quite a lot of angular applications in the wild which does not do this cherry picking.

@cyrilletuzi
Copy link
Contributor

@filipesilva following my previous comment, as the build optimizer will be on by default in CLI 1.5 and Angular 5, will it stay with --vendor-chunk false by default ?

Total size is not the only criteria, having one big bundle means when the app is updated, all the big bundle will have to be downloaded again instead of just the main bundle (which is light, unlike to the vendor one). This is why the CLI separated them, I think it's quite strange to revert that.

@filipesilva
Copy link
Contributor Author

@cyrilletuzi yes it should stay --vendor-chunk false by default. I agree total size is not the only criteria, but it's a very, very important one. I think the default caters to the general scenario well. There's is also no guarantee that vendor won't change, mind you.. so while true that there are cache gains there, they exist only on some scenarios.

@Alekcei
Copy link

Alekcei commented Dec 27, 2017

--no-build-optimizer not working in @angular/cli:1.6.2. But if use @angular/cli:1.5.0 then all Ok

@Alekcei
Copy link

Alekcei commented Dec 27, 2017

possibly connected #8900

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 12, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants