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

Tree-shaking for production build is not working properly #4137

Closed
thomasgazzoni opened this issue Apr 18, 2017 · 51 comments · Fixed by #6998
Closed

Tree-shaking for production build is not working properly #4137

thomasgazzoni opened this issue Apr 18, 2017 · 51 comments · Fixed by #6998
Labels
P2 The issue is important to a large percentage of users, with a workaround

Comments

@thomasgazzoni
Copy link

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:

import { NgModule } from '@angular/core';
import {
    MdCardModule,
    MdChipsModule,
    MdToolbarModule,
    MdButtonModule,
    MdSidenavModule,
    MdRippleModule,
    MdIconModule,
    MdListModule,
    MdProgressSpinnerModule,
} from '@angular/material';

@NgModule({
    imports: [
        MdCardModule,
        MdChipsModule,
        MdToolbarModule,
        MdButtonModule,
        MdSidenavModule,
        MdRippleModule,
        MdIconModule,
        MdListModule,
        MdProgressSpinnerModule,
    ],
    declarations: [

    ],
    providers: [

    ],
    exports: [
        MdCardModule,
        MdChipsModule,
        MdToolbarModule,
        MdButtonModule,
        MdSidenavModule,
        MdRippleModule,
        MdIconModule,
        MdListModule,
        MdProgressSpinnerModule,
    ]
})
export class CustomMaterialModule { }

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
image

@devversion
Copy link
Member

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.

@jelbourn
Copy link
Member

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.

@jelbourn jelbourn self-assigned this Apr 18, 2017
@jelbourn jelbourn added the P2 The issue is important to a large percentage of users, with a workaround label Apr 18, 2017
@dahaupt
Copy link

dahaupt commented Apr 18, 2017

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 {
}

@kuncevic
Copy link
Contributor

kuncevic commented May 3, 2017

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

image

Looking forward to bata.4 handling that case.

@fknop
Copy link

fknop commented May 13, 2017

Has this issue been fixed with beta.4 ?

@karolmie1
Copy link

@fknop I've noticed some decrease in size, but not enough.

@kuncevic
Copy link
Contributor

@fknop @karolmie1 for me it is just got increased:

image
was:
741.2k kb
60.03 gziped
now
850.19 kb
69.11 kb gziped
And I am just importing my custom module #4137 (comment)

@paulogr
Copy link

paulogr commented May 15, 2017

Love to see that working!

@jelbourn
Copy link
Member

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.

@fetters5
Copy link

fetters5 commented Jun 2, 2017

Any updates on a timeline for this by chance?

@jelbourn
Copy link
Member

jelbourn commented Jun 2, 2017

@IgorMinar and @kara are actively working on it.

@jelbourn jelbourn assigned kara and unassigned jelbourn Jun 6, 2017
@ghost
Copy link

ghost commented Jun 9, 2017

While it is currently being worked on, is there an other possible workaround to this problem right now?

@aitboudad
Copy link
Contributor

Check this one https://github.com/IgorMinar/purify it might help you

@jelbourn
Copy link
Member

jelbourn commented Jun 9, 2017

Yep, that's what they're working on

@karolmie1
Copy link

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.

@deepakzoto
Copy link

@jelbourn Any Update on tree-shaking?

@filipesilva
Copy link
Contributor

@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 angular/angular-cli#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.

@alexzuza
Copy link
Contributor

@filipesilva Very nice news. We will try it

@HaareeKrishna
Copy link

Webpack will not load unused modules and cannot remove it from bundle. We need to use uglifyJs to remove the dead code from bundle.

@IAMtheIAM
Copy link

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.

@willshowell
Copy link
Contributor

@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 angular/angular-cli@9ec5b4e

@IAMtheIAM
Copy link

IAMtheIAM commented Sep 19, 2017

@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.

@trotyl
Copy link
Contributor

trotyl commented Sep 20, 2017

@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)

@CardzMania
Copy link

We still see material.es5.js + 19 modules in our project
screen shot 2017-10-13 at 4 28 40 pm

"@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?

@aitboudad
Copy link
Contributor

@CardzMania just avoid importing modules from @angular/material:

Before:

import {MatButtonModule} from '@angular/material';

After:

import {MatButtonModule} from '@angular/material/button';

@CardzMania
Copy link

Ohhh, thanks for the quick reply, let me try that. Must have missed it in the comments :(

@CardzMania
Copy link

CardzMania commented Oct 13, 2017

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!

@daniele-pecora
Copy link

Can confirm this
Viewings from the webpack-bundle-analyzer
Before
before

After
after

@Lakston
Copy link

Lakston commented Dec 12, 2017

Has this been fixed ? Because I am importing from @angular/material and the tree shaking is working properly :

screen shot 2017-12-12 at 08 57 42

@oliveti
Copy link

oliveti commented Dec 12, 2017

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';

main f99a665aedb758fe3621 bundle js - source map explorer 2017-12-12 12-34-18

Isn't anyway to make it work with importing @angular/material?

@GeorgeKnap
Copy link

GeorgeKnap commented Dec 12, 2017

@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.
ecall-stats
gis_stats

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

@shifatul-i
Copy link

Any update on this?

Looks bad
image

@tom94zoe
Copy link

tom94zoe commented Nov 8, 2018

@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.
ecall-stats
gis_stats

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.

image

@danielsuter
Copy link

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",

@devversion
Copy link
Member

This is issue has been closed last year because we switched to the Angular package format that should have fixed this. If you are still seeing an issue in regards to tree-shaking, please open a new issue and maybe also use source-map-explorer, so that we can see what's going on in your application.

@angular angular locked as resolved and limited conversation to collaborators Nov 26, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
P2 The issue is important to a large percentage of users, with a workaround
Projects
None yet
Development

Successfully merging a pull request may close this issue.