Closed thomasgazzoni closed 7 years ago
Yeah I experienced the same issue when testing Material with Webpack 2.
I've been talking to some people about this and it looks like this happens due to missing @__PURE__
annotations in the FESM bundles on IIFEs.
Yep, just spent a while talking about this with the rest of the Angular core team. The gist is that the new packing structure doesn't work out of the box with how webpack tries to eliminate dead code. We're working on a solution and will publish a beta.4 as soon as we have a good approach.
Do we even have to import the single Modules into our CustomMaterialModule? I just exported them and everything seems to work fine.
My CustomMaterialModule:
@NgModule({
exports: [
MdButtonModule, MdInputModule, MdSelectModule, MdTabsModule, MdMenuModule, MdIconModule, MdTooltipModule, MdCardModule,
MdCheckboxModule, MdSidenavModule, MdDialogModule, MdToolbarModule, MdSnackBarModule, MdProgressSpinnerModule, MdListModule
]
})
export class CustomMaterialModule {
}
Just created a custom material module thinking to reduce the bundle size
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import {
MdDialogModule,
MdToolbarModule,
MdInputModule,
MdMenuModule,
MdIconModule,
MdSlideToggleModule,
MdSliderModule,
MdSelectModule,
MdRadioModule,
MdCheckboxModule,
MdButtonModule,
MdButtonToggleModule,
MdSidenavModule,
MdListModule,
MdTooltipModule
} from '@angular/material';
@NgModule({
imports: [
CommonModule,
MdDialogModule,
MdToolbarModule,
MdInputModule,
MdMenuModule,
MdIconModule,
MdSlideToggleModule,
MdSliderModule,
MdSelectModule,
MdRadioModule,
MdCheckboxModule,
MdButtonModule,
MdButtonToggleModule,
MdSidenavModule,
MdListModule,
MdTooltipModule
],
exports: [
CommonModule,
MdDialogModule,
MdToolbarModule,
MdInputModule,
MdMenuModule,
MdIconModule,
MdSlideToggleModule,
MdSliderModule,
MdSelectModule,
MdRadioModule,
MdCheckboxModule,
MdButtonModule,
MdButtonToggleModule,
MdSidenavModule,
MdListModule,
MdTooltipModule
]
})
export class CustomMaterialModule { }
Didn't work still getting same material size 741.28 kb
. So currently no difference if I am importing my custom module or MaterialModule
Looking forward to bata.4
handling that case.
Has this issue been fixed with beta.4 ?
@fknop I've noticed some decrease in size, but not enough.
@fknop @karolmie1 for me it is just got increased:
was:
741.2k
kb
60.03
gziped
now
850.19
kb
69.11
kb gziped
And I am just importing my custom module https://github.com/angular/material2/issues/4137#issuecomment-298827979
Love to see that working!
We're working on it (experiment 1, experiment 2), but getting it to "just work" with existing tooling is somewhat tricky and we're still working out the approach.
Any updates on a timeline for this by chance?
@IgorMinar and @kara are actively working on it.
While it is currently being worked on, is there an other possible workaround to this problem right now?
Check this one https://github.com/IgorMinar/purify it might help you
Yep, that's what they're working on
Would it be possible to provide separate modules: MdCardModule, MdChipsModule, instead of one blob? Then we could import directly, and circumvent the tree-shaking conondrum.
Plus material module as of now for lazy people.
Same way a angular does it -> there is no one big angular.es5 file, they are split into router module, animations module itp.
@jelbourn Any Update on tree-shaking?
@angular-devkit/build-optimizer
(formerly ngo
+purify
) support was added to @angular/cli@1.3.0-rc.0
. You can read more about it in https://github.com/angular/angular-cli/pull/6520.
This should allow a lot of unused material classes to be dropped. Please let me know how it worked out for you - this is still experimental and it's very important to work out the kinks before 1.3.0
final.
@filipesilva Very nice news. We will try it
@filipesilva that cool, but there is something wrong going on with CLI producing wrong bundler stats file or due to incompatibility with scope hoisting https://github.com/angular/angular-cli/issues/7057 Tested with 1.3.0-beta.0 and 1.3.0 rc.0.
Why not just split into separate submodules files? Instead
import {
MdAutocompleteModule
MdButtonModule,
} from } from '@angular/material';
We could have:
import { MdAutocompleteModule } from '@angular/material/MdAutocompleteModule';
import { MdButtonModule } from '@angular/material/MdButtonModule'
And user will automatically import only what is needed. You can still re-export everything under @angular/material.
Now I have a situation that my prod bundle is 1.5mb and large part is because of Material. I will try with aot, but the app is already barely usable in IE11. We go live on Monday and It looks like I will need to rewrite this to Bootstrap.
@filipesilva, tried the RC.5 and the problem remains (in fact the vendor bundle increased from 895KB in 1.2.1 to 897KB in 1.3.0-rc.5). Basically I have imported two modules from material (MdInputModule and MdCardModule) to a fresh new cli project.
My setup:
@angular/cli: 1.3.0-rc.5
node: 6.10.3
os: win32 x64
@angular/animations: 4.3.3
@angular/cdk: 2.0.0-beta.8
@angular/common: 4.3.3
@angular/compiler: 4.3.3
@angular/core: 4.3.3
@angular/forms: 4.3.3
@angular/http: 4.3.3
@angular/material: 2.0.0-beta.8
@angular/platform-browser: 4.3.3
@angular/platform-browser-dynamic: 4.3.3
@angular/router: 4.3.3
@angular/cli: 1.3.0-rc.5
@angular/compiler-cli: 4.3.3
@angular/language-service: 4.3.3
@julianobrasil to use the build optimizer you need to add the --build-optimizer
flag (e.g. ng build --prod --build-optimizer
).
Wow! Nice!!! Apparently I found nothing but the two modules I've imported.
905KB to 273KB is indeed a very big reduction :D
Let me know if there's any runtime problems with the app, we're still ironing out bugs.
I'll try it in a real project I'm working on. At the end of the day I'll comment about the tests over here.
@filipesilva, I've just tried to compile the other project (I have some extra stuff like lazy loading routing and some third-party libraries - see bellow). If you need more details, let me know.
ERROR in ./node_modules/rxjs/observable/BoundCallbackObservable.js Module build failed: TypeError: Cannot read property 'type' of undefined at Object.getEffectiveTypeAnnotationNode (E:\Users\Juliano\Documents\Projetos\SGI-ALFA\github\SGI-Frontend\node_modules\@angular-devkit\build-optimizer\node_modules\typescript\lib\typescript.js:9341:17) at assignContextualParameterTypes (E:\Users\Juliano\Documents\Projetos\SGI-ALFA\github\SGI-Frontend\node_modules\@angular-devkit\build-optimizer\node_modules\typescript\lib\typescript.js:41652:25) at checkFunctionExpressionOrObjectLiteralMethod (E:\Users\Juliano\Documents\Projetos\SGI-ALFA\github\SGI-Frontend\node_modules\@angular-devkit\build-optimizer\node_modules\typescript\lib\typescript.js:41948:29) at checkExpressionWorker (E:\Users\Juliano\Documents\Projetos\SGI-ALFA\github\SGI-Frontend\node_modules\@angular-devkit\build-optimizer\node_modules\typescript\lib\typescript.js:42959:28) at checkExpression (E:\Users\Juliano\Documents\Projetos\SGI-ALFA\github\SGI-Frontend\node_modules\@angular-devkit\build-optimizer\node_modules\typescript\lib\typescript.js:42898:42) at checkExpressionCached (E:\Users\Juliano\Documents\Projetos\SGI-ALFA\github\SGI-Frontend\node_modules\@angular-devkit\build-optimizer\node_modules\typescript\lib\typescript.js:42779:38) at checkReturnStatement (E:\Users\Juliano\Documents\Projetos\SGI-ALFA\github\SGI-Frontend\node_modules\@angular-devkit\build-optimizer\node_modules\typescript\lib\typescript.js:45418:54) at checkSourceElement (E:\Users\Juliano\Documents\Projetos\SGI-ALFA\github\SGI-Frontend\node_modules\@angular-devkit\build-optimizer\node_modules\typescript\lib\typescript.js:46763:28) at Object.forEach (E:\Users\Juliano\Documents\Projetos\SGI-ALFA\github\SGI-Frontend\node_modules\@angular-devkit\build-optimizer\node_modules\typescript\lib\typescript.js:1506:30) at checkBlock (E:\Users\Juliano\Documents\Projetos\SGI-ALFA\github\SGI-Frontend\node_modules\@angular-devkit\build-optimizer\node_modules\typescript\lib\typescript.js:44563:16) at checkSourceElement (E:\Users\Juliano\Documents\Projetos\SGI-ALFA\github\SGI-Frontend\node_modules\@angular-devkit\build-optimizer\node_modules\typescript\lib\typescript.js:46742:28) at checkFunctionExpressionOrObjectLiteralMethodDeferred (E:\Users\Juliano\Documents\Projetos\SGI-ALFA\github\SGI-Frontend\node_modules\@angular-devkit\build-optimizer\node_modules\typescript\lib\typescript.js:41990:21) at checkDeferredNodes (E:\Users\Juliano\Documents\Projetos\SGI-ALFA\github\SGI-Frontend\node_modules\@angular-devkit\build-optimizer\node_modules\typescript\lib\typescript.js:46828:25) at checkSourceFileWorker (E:\Users\Juliano\Documents\Projetos\SGI-ALFA\github\SGI-Frontend\node_modules\@angular-devkit\build-optimizer\node_modules\typescript\lib\typescript.js:46863:17) at checkSourceFile (E:\Users\Juliano\Documents\Projetos\SGI-ALFA\github\SGI-Frontend\node_modules\@angular-devkit\build-optimizer\node_modules\typescript\lib\typescript.js:46842:13) at Object.forEach (E:\Users\Juliano\Documents\Projetos\SGI-ALFA\github\SGI-Frontend\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/model/service/dao/usuario.service.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 (E:\Users\Juliano\Documents\Projetos\SGI-ALFA\github\SGI-Frontend\node_modules\@angular-devkit\build-optimizer\node_modules\typescript\lib\typescript.js:9341:17) at assignContextualParameterTypes (E:\Users\Juliano\Documents\Projetos\SGI-ALFA\github\SGI-Frontend\node_modules\@angular-devkit\build-optimizer\node_modules\typescript\lib\typescript.js:41652:25) at checkFunctionExpressionOrObjectLiteralMethod (E:\Users\Juliano\Documents\Projetos\SGI-ALFA\github\SGI-Frontend\node_modules\@angular-devkit\build-optimizer\node_modules\typescript\lib\typescript.js:41948:29) at checkExpressionWorker (E:\Users\Juliano\Documents\Projetos\SGI-ALFA\github\SGI-Frontend\node_modules\@angular-devkit\build-optimizer\node_modules\typescript\lib\typescript.js:42959:28) at checkExpression (E:\Users\Juliano\Documents\Projetos\SGI-ALFA\github\SGI-Frontend\node_modules\@angular-devkit\build-optimizer\node_modules\typescript\lib\typescript.js:42898:42) at checkExpressionCached (E:\Users\Juliano\Documents\Projetos\SGI-ALFA\github\SGI-Frontend\node_modules\@angular-devkit\build-optimizer\node_modules\typescript\lib\typescript.js:42779:38) at checkReturnStatement (E:\Users\Juliano\Documents\Projetos\SGI-ALFA\github\SGI-Frontend\node_modules\@angular-devkit\build-optimizer\node_modules\typescript\lib\typescript.js:45418:54) at checkSourceElement (E:\Users\Juliano\Documents\Projetos\SGI-ALFA\github\SGI-Frontend\node_modules\@angular-devkit\build-optimizer\node_modules\typescript\lib\typescript.js:46763:28) at Object.forEach (E:\Users\Juliano\Documents\Projetos\SGI-ALFA\github\SGI-Frontend\node_modules\@angular-devkit\build-optimizer\node_modules\typescript\lib\typescript.js:1506:30) at checkBlock (E:\Users\Juliano\Documents\Projetos\SGI-ALFA\github\SGI-Frontend\node_modules\@angular-devkit\build-optimizer\node_modules\typescript\lib\typescript.js:44563:16) at checkSourceElement (E:\Users\Juliano\Documents\Projetos\SGI-ALFA\github\SGI-Frontend\node_modules\@angular-devkit\build-optimizer\node_modules\typescript\lib\typescript.js:46742:28) at checkFunctionExpressionOrObjectLiteralMethodDeferred (E:\Users\Juliano\Documents\Projetos\SGI-ALFA\github\SGI-Frontend\node_modules\@angular-devkit\build-optimizer\node_modules\typescript\lib\typescript.js:41990:21) at checkDeferredNodes (E:\Users\Juliano\Documents\Projetos\SGI-ALFA\github\SGI-Frontend\node_modules\@angular-devkit\build-optimizer\node_modules\typescript\lib\typescript.js:46828:25) at checkSourceFileWorker (E:\Users\Juliano\Documents\Projetos\SGI-ALFA\github\SGI-Frontend\node_modules\@angular-devkit\build-optimizer\node_modules\typescript\lib\typescript.js:46863:17) at checkSourceFile (E:\Users\Juliano\Documents\Projetos\SGI-ALFA\github\SGI-Frontend\node_modules\@angular-devkit\build-optimizer\node_modules\typescript\lib\typescript.js:46842:13) at Object.forEach (E:\Users\Juliano\Documents\Projetos\SGI-ALFA\github\SGI-Frontend\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/model/service/dao/usuario.service.ts @ ./src/$$_gendir/app/app.module.ngfactory.ts @ ./src/main.ts @ multi ./src/main.ts
"dependencies": { "@angular/animations": "^4.3.3", "@angular/cdk": "^2.0.0-beta.8", "@angular/common": "^4.3.3", "@angular/compiler": "^4.3.3", "@angular/core": "^4.3.3", "@angular/flex-layout": "github:angular/flex-layout-builds", "@angular/forms": "^4.3.3", "@angular/http": "^4.3.3", "@angular/material": "^2.0.0-beta.8", "@angular/platform-browser": "^4.3.3", "@angular/platform-browser-dynamic": "^4.3.3", "@angular/platform-server": "^4.3.3", "@angular/router": "^4.3.3", "@types/crypto-js": "^3.1.32", "angular2-text-mask": "^8.0.1", "bootstrap": "^4.0.0-alpha.6", "chart.js": "^2.6.0", "core-js": "^2.4.1", "crypto-js": "^3.1.9-1", "express": "^4.14.0", "hammerjs": "^2.0.8", "jquery-ui": "^1.12.1", "jquery-ui-dist": "^1.12.1", "linqts": "^1.8.2", "ng2-dragula": "^1.5.0", "ngx-pagination": "^3.0.0", "rxjs": "^5.3.0", "ts-helpers": "^1.1.2", "zone.js": "^0.8.12" }, "devDependencies": { "@angular/cli": "^1.3.0-rc.5", "@angular/compiler-cli": "^4.3.3", "@angular/language-service": "^4.3.3", "@types/jasmine": "2.5.46", "@types/node": "~7.0.12", "codelyzer": "~3.0.1", "jasmine-core": "~2.6.2", "jasmine-spec-reporter": "~4.1.0", "karma": "~1.7.0", "karma-chrome-launcher": "~2.1.1", "karma-cli": "~1.0.1", "karma-coverage-istanbul-reporter": "^1.2.1", "karma-jasmine": "~1.1.0", "karma-jasmine-html-reporter": "^0.2.2", "protractor": "~5.1.2", "ts-node": "~3.0.4", "tslint": "~5.3.2", "typescript": "~2.3.4" }
@julianobrasil let's move this onto the CLI issue tracker now, this part isn't about Material any more.
Can you open a new issue there with these logs, and perhaps show me the contents of ./src/app/model/service/dao/usuario.service.ts
? If you can provide a repro it would be even better.
I've seen HUGE improvement using 1.3.0-rc.5
! Having all of the material components and angular itself I previously had a "base" bundle which could be up to 2MB. After using ng build --prod --aot --build-optimizer
the compiled code is around ~400kb
which is absolutely awesome! @filipesilva job well done! :1st_place_medal: :+1:
Hash: 03b835ca4ff8a748a075
Version: webpack 3.4.1
Time: 56462ms
Asset Size Chunks Chunk Names
js/polyfills.js 62.4 kB 0 [emitted] polyfills
js/main.js 337 kB 1 [emitted] [big] main
js/inline.js 1.36 kB 3 [emitted] inline
css/styles.03b835ca4ff8a748a075.css 33.4 kB 2 [emitted] styles
favicon.ico 5.43 kB [emitted]
./index.html 516 bytes [emitted]
../../manifest.json 204 bytes [emitted]
That's great to hear!
But there isn't a vendor.bundle.js
anymore. Why?
Is there any way to separate it out from the main.bundle.js
, thx.
@isEdison try --vendor-chunk true
@trotyl it works!
It's worth it to add the vendor-chunk? Which one is the explanation to remove it from the normal build?
We've seen much better results by not having the vendor bundle, so we default to it.
The combination of webpack 3 scope hoisting, build optimizer pure comments and UglifyJS allow a lot of code to be removed if it is in the same bundle. But when separating bundles, UglifyJS can no longer identify code to drop as well due to the indirection from the webpack loader.
So yes, you can re-add the vendor bundle by doing --vendor-chunk=true
. But I advise you to compare the total size with and without it to make sure you're not delivering unnecessary code.
Webpack will not load unused modules and cannot remove it from bundle. We need to use uglifyJs to remove the dead code from bundle.
How do we use build-optmizer
with webpack doing the build? I don't use ng
on command line at all for my setup. Currently in 2.0.0-beta.10
still no reduction in bundle size at all using webpack. It just plops the whole materialize.js into the bundle, even when only importing specific modules.
@IAMtheIAM this is not materialize. Also this looks like it might help:
https://github.com/angular/devkit/tree/master/packages/angular_devkit/build_optimizer
From https://github.com/angular/angular-cli/commit/9ec5b4ed66637f3605c74be1637464a2b0e8d44d
@willshowell Yes sorry, I meant the whole @angular/material js bundle.
So if I add that webpack plugin you pointed me to, Angular Build Optmizer, this should allow webpack/uglifyjs to tree shake the angular/material bundle ? I will check that out.
Lastly, should that loader only be used for development, or is it safe for production? I am unfamiliar with what it does.
@IAMtheIAM The build-optimizer can only work with AOT (and parts of the optimization needs uglifyJS), so likely you can only use that in production. (Few people use AOT in dev as I know)
We still see material.es5.js + 19 modules in our project
"@angular/material": "^2.0.0-beta.12",
Any ideas what we can do to get rid of this or how to debug whats going on?
@CardzMania just avoid importing modules from @angular/material
:
Before:
import {MatButtonModule} from '@angular/material';
After:
import {MatButtonModule} from '@angular/material/button';
Ohhh, thanks for the quick reply, let me try that. Must have missed it in the comments :(
Great, that worked! Had a hiccup along the way and noting here for others, just changing modules is not enough. Do remember to change all imports also:
Before:
import { MatDialogRef } from '@angular/material';
After
import { MatDialogRef } from '@angular/material/dialog';
Search for from '@angular/material'
and just get rid of it!
Can confirm this Viewings from the webpack-bundle-analyzer Before
After
Has this been fixed ? Because I am importing from @angular/material
and the tree shaking is working properly :
Hi,
@Lakston, you can see all the modules but tree shaking should strip out all unused modules.
If I want to make the tree shaking work as expected I have to import the sub-modules like this import { MatDialogModule } from '@angular/material/dialog';
Isn't anyway to make it work with importing @angular/material
?
@oliveti I agree with @Lakston
here are two of my projects. The first one uses imports from @angular/material
the second one uses imports only from specific submodules like @angular/material/dialog
.
Note the second one imports more modules -> it's bigger.
both contains only those modules imported in my custom material.module.ts
which means the tree-shaking must be working ok in both of them.
Correct me if I'm wrong.
versions:
@angular/material: 5.0.0
@angular: 5.1.0
@angular/cli: 1.6.0
Any update on this?
Looks bad
@oliveti I agree with @Lakston here are two of my projects. The first one uses imports from
@angular/material
the second one uses imports only from specific submodules like@angular/material/dialog
. Note the second one imports more modules -> it's bigger.both contains only those modules imported in my custom
material.module.ts
which means the tree-shaking must be working ok in both of them. Correct me if I'm wrong.versions:
@angular/material: 5.0.0 @angular: 5.1.0 @angular/cli: 1.6.0
I think that the treeshaked prod bundle should not contain typings. At least not such big files. My bundle size is 55kb gzipped, about 20kb of it are typings. Please correct me If I am wrong.
I am using the '@angular/material' - import. Because the intelisense of current Web Storm version suggest it.
Why is this issue closed? I still get a bundle size of 1.53mb unzipped. With the following dependencies:
"@angular/material": "^7.0.4", "@angular/core": "^7.0.4", "@angular-devkit/build-angular": "^0.10.6", "@angular/cli": "^7.0.6",
Bug, feature request, or proposal:
The production bundle size is not shrinking
What is the expected behavior?
Base on the new package structure the production bundle (ng build --prod) should not have included all the Material Components Module
What is the current behavior?
Base on the change log now we should create our own Custom MaterialModule, in my case I have this one:
that is imported in the AppModule.
Even if I remove all the module and import only, for example, MdButtonModule, the size of material library in the production vendor.js still 308Kb
Which versions of Angular, Material, OS, browsers are affected?
@angular/cli: 1.0.0 node: 7.9.0 os: linux x64 @angular/animations: 4.0.1 @angular/common: 4.0.1 @angular/compiler: 4.0.1 @angular/core: 4.0.1 @angular/forms: 4.0.1 @angular/http: 4.0.1 @angular/material: 2.0.0-beta.3 @angular/platform-browser: 4.0.1 @angular/platform-browser-dynamic: 4.0.1 @angular/router: 4.0.1 @angular/cli: 1.0.0 @angular/compiler-cli: 4.0.1
Is there anything else we should know?
This is the vendor sourcemap generated by source-map-explorer