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

Increased main.js bundle size but less lazy chunks after updating to angular 9.0.0-rc.1 #16146

Closed
wambowams opened this issue Nov 11, 2019 · 58 comments
Assignees
Milestone

Comments

@wambowams
Copy link

🐞 Bug report

Command (mark with an x)

- [ ] new
- [x] build
- [ ] serve
- [ ] test
- [ ] e2e
- [ ] generate
- [ ] add
- [ ] update
- [ ] lint
- [ ] xi18n
- [ ] run
- [ ] config
- [ ] help
- [ ] version
- [ ] doc

Description

After updating from Angular 8.2.3 to 9.0.0-rc.1 the bundle size was increased for main module and some of the feature modules:
Before it was:
bundle_before9

After updating to Angular 9.0.0-rc.1 it is
image

🔬 Minimal Reproduction

running ng build --prod --namedChunks with following configuration:

            "production": {
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ],
              "optimization": true,
              "outputHashing": "all",
              "sourceMap": false,
              "extractCss": true,
              "namedChunks": false,
              "extractLicenses": true,
              "vendorChunk": false,
              "commonChunk": false,
              "buildOptimizer": true,
              "budgets": [
                {
                  "type": "initial",
                  "maximumWarning": "1mb",
                  "maximumError": "2mb"
                },
                {
                  "type": "anyComponentStyle",
                  "maximumWarning": "6kb"
                }
              ],
              "serviceWorker": true,
              "ngswConfigPath": "ngsw-config.json"
            }
          }

🌍 Your Environment


Angular CLI: 9.0.0-rc.1
Node: 10.15.3
OS: win32 x64
Angular: 9.0.0-rc.1
... animations, cli, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router, service-worker

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.900.0-rc.1
@angular-devkit/build-angular     0.900.0-rc.1
@angular-devkit/build-optimizer   0.900.0-rc.1
@angular-devkit/build-webpack     0.900.0-rc.1
@angular-devkit/core              9.0.0-rc.1
@angular-devkit/schematics        9.0.0-rc.1
@angular/cdk                      8.2.3
@angular/material                 8.2.3
@ngtools/webpack                  9.0.0-rc.1
@schematics/angular               9.0.0-rc.1
@schematics/update                0.900.0-rc.1
rxjs                              6.5.3
typescript                        3.6.4
webpack                           4.41.2
@alan-agius4
Copy link
Collaborator

Any chance of reproduction please?

@alan-agius4 alan-agius4 added the needs: repro steps We cannot reproduce the issue with the information given label Nov 11, 2019
@wambowams
Copy link
Author

I will try this afternoon, but its little bit hard as its a customer's project

@filipesilva
Copy link
Contributor

@wambowams just to be really sure, can you show the sizes on disk for the dist folder? Sometime in 8 we had a bug where the ng build reported sizes weren't correct.

@parys
Copy link

parys commented Nov 12, 2019

I hope this comment can help.
Faced with increasing main module size(in es2015) from 1.06 to 1.15 MB (and es5 size increased too), but all other modules decreased. Full application size decreased from 3.44 to 2.67 MB.
webpack-bundle-analyzer shows that it caused by angular/material. it increased from 127 to 200 kB and increase main module.
core and cli is 9 RC1,
material and cdk is 9 RC0

p.s. File sizes at disk are increased, checked this.

@filipesilva
Copy link
Contributor

@parys can you check if you have the same number of files? I wouldn't be surprised if only of the lazy modules had been merged with the main module.

@parys
Copy link

parys commented Nov 13, 2019

@filipesilva you are right.
86 files (es5 + es2015) in angular 9 rc1
90 files (es5 + es2015) angular 8.2.13
just angular files, skipped css and service-worker files (same count).
checked again, my files (src) decreased ~ 40kB
animations + platform-browser decreased ~10kB
common increased ~24kB.
forms increased ~15kB
router increased ~5kB
core increased ~7kB
-50(-40-10) and +52(24+15+5+7)
cdk increased ~13kB
material increased ~82kb
zone.js, hummerjs, rxjs same size
so as I see angular/material is guilty of increasing size by 90kB.
all angular packages + my main source is around same size.
as I see no one module merged to main. It combined between them at lazy load module level.

@wambowams
Copy link
Author

@parys Thank u for the tip, I have multiple material imports in different lazy loaded modules.
@filipesilva I will check the material problem and the disk filesize tomorrow at work

@elvirdolic
Copy link

I have a simmiliar experience

9.0.0-rc.1

chunk {2} polyfills-es2015.c7a30df4bc9d877b298c.js (polyfills) 35.9 kB [initial] [rendered]
chunk {8} 8-es2015.ada4e33bfaa3f31731ae.js () 10.1 kB  [rendered]
chunk {8} 8-es5.ada4e33bfaa3f31731ae.js () 10.7 kB  [rendered]
chunk {9} 9-es2015.709f406ec03c989f0f1f.js () 4.28 kB  [rendered]
chunk {9} 9-es5.709f406ec03c989f0f1f.js () 4.43 kB  [rendered]
chunk {11} 11-es2015.226745742bd2ed46cdb3.js () 1.08 kB  [rendered]
chunk {11} 11-es5.226745742bd2ed46cdb3.js () 1.21 kB  [rendered]
chunk {0} runtime-es2015.b97001bcf5aa06731258.js (runtime) 2.43 kB [entry] [rendered]      
chunk {0} runtime-es5.b97001bcf5aa06731258.js (runtime) 2.43 kB [entry] [rendered]
chunk {7} 7-es2015.6bd84e6ce375884a9572.js () 19.6 kB  [rendered]
chunk {7} 7-es5.6bd84e6ce375884a9572.js () 20.3 kB  [rendered]
chunk {13} 13-es2015.a42b4b1c7354dfe6f2ac.js () 2.41 kB  [rendered]
chunk {13} 13-es5.a42b4b1c7354dfe6f2ac.js () 2.91 kB  [rendered]   
chunk {12} 12-es2015.d5800d5600a902e895f5.js () 5.34 kB  [rendered]
chunk {12} 12-es5.d5800d5600a902e895f5.js () 5.85 kB  [rendered]   
chunk {6} 6-es2015.59e69d5e0f464084389e.js () 5.73 kB  [rendered]  
chunk {6} 6-es5.59e69d5e0f464084389e.js () 6.35 kB  [rendered]     
chunk {10} 10-es2015.e06cb514cf8a21185f7d.js () 55.7 kB  [rendered]
chunk {10} 10-es5.e06cb514cf8a21185f7d.js () 59.1 kB  [rendered]   
chunk {5} 5-es2015.a3e74ebf9abaa7a35ba5.js () 109 kB  [rendered]   
chunk {5} 5-es5.a3e74ebf9abaa7a35ba5.js () 111 kB  [rendered]
chunk {1} main-es2015.afec893c92139b333131.js (main) 1.83 MB [initial] [rendered]
chunk {1} main-es5.afec893c92139b333131.js (main) 2.03 MB [initial] [rendered]
chunk {4} styles.f7c48dea9a89feb2b99e.css (styles) 74.4 kB [initial] [rendered]
chunk {scripts} scripts.03e042f1f102bf0e2ed8.js (scripts) 19.9 kB [entry] [rendered]
Date: 2019-11-14T07:40:19.035Z - Hash: 4d5c0fbe7ba52a60a6cb - Time: 154070ms

exact numbers on disk

image

vs 8

chunk {0} common-es2015.f65f5aa566db4e06d105.js (common) 9.84 kB  [rendered]
chunk {1} runtime-es2015.dc5fd48940e2007b44fd.js (runtime) 4.49 kB [entry] [rendered]
chunk {2} 2-es2015.b66890fe6cb0d0ba93d2.js () 57.8 kB  [rendered]
chunk {3} 3-es2015.623227132f5ef6839c15.js () 20 kB  [rendered]
chunk {4} main-es2015.43343003de40fbc4ec5e.js (main) 2.21 MB [initial] [rendered]
chunk {5} polyfills-es2015.add85f0e35cf86eeff4a.js (polyfills) 63.4 kB [initial] [rendered]
chunk {6} polyfills-es5-es2015.5d4ed357ffea17c6a0dd.js (polyfills-es5) 225 kB [initial] [rendered]
chunk {7} styles.e5e1b71b2548c50cb6c5.css (styles) 72.3 kB [initial] [rendered]
chunk {8} 8-es2015.6bd7263fab8d903b0fb9.js () 254 kB  [rendered]
chunk {9} 9-es2015.478af0fa902e9a4f6539.js () 194 kB  [rendered]
chunk {10} 10-es2015.1be5d5f2474cd46c8288.js () 59.8 kB  [rendered]
chunk {11} 11-es2015.dffb2a20c94c68a0bf1c.js () 28 kB  [rendered]
chunk {12} 12-es2015.321a3b949196c255ca8e.js () 19.4 kB  [rendered]
chunk {13} 13-es2015.0a30a70a9c35bf08dddb.js () 156 kB  [rendered]
chunk {14} 14-es2015.9cf10db117bbba60ae53.js () 9.26 kB  [rendered]
chunk {15} 15-es2015.9482769a0e8d8a81eb5b.js () 27.7 kB  [rendered]
chunk {16} 16-es2015.4dcc1c7a5105ce379783.js () 12.8 kB  [rendered]
chunk {scripts} scripts.03e042f1f102bf0e2ed8.js (scripts) 19.8 kB [entry] [rendered]
Date: 2019-11-12T10:53:35.219Z - Hash: ede763d16e9e87e7cc2b - Time: 200420ms

in 8 the numbers reported are wrong ...

exact numbers disk v8

image

@filipesilva
Copy link
Contributor

@elvirdolic I think something similar happened in your case: version 8 has 13 application js bundles, while version 9 has only 10 application js bundles. The extra size seems to have come from code moving from some of the lazy bundles back into the main chunk.

@wambowams
Copy link
Author

@filipesilva I checked the file sizes. These are my results:
For Version 8.2.13:
bundle_before9
With size on the disk:

14.11.2019  14:33            60.658 0-es5.566bec7d8e9f9cda780a.js
14.11.2019  14:34            52.826 1-es2015.e9fd6dadef4caff07749.js
14.11.2019  14:33            19.960 5-es5.36e53960b8db97ac7f91.js
14.11.2019  14:34            19.751 6-es2015.4e348f6d41fafc26f200.js
14.11.2019  14:33             3.006 6-es5.c07b99f036dd7c321da9.js
14.11.2019  14:34             2.865 7-es2015.2bf07606f9c036fbb354.js
14.11.2019  14:33           120.951 7-es5.68d52a09dc28bd20e670.js
14.11.2019  14:34           112.920 8-es2015.3f0e8b4086b9f6ef70cc.js
14.11.2019  14:33            61.407 8-es5.82c8181b7341226961bb.js
14.11.2019  14:34            61.022 9-es2015.70ca7e368f9a76b59964.js
14.11.2019  14:34            21.375 common-es2015.54e83193ca37b87dd09a.js
14.11.2019  14:33            21.375 common-es5.0235b6e6e922441d2689.js
14.11.2019  14:34             1.542 index.html
14.11.2019  14:34           672.175 main-es2015.3ef131ef7dbb2e06e7da.js
14.11.2019  14:33           766.803 main-es5.916e65e01e2ceefdf20d.js
14.11.2019  14:34             1.133 manifest.webmanifest
14.11.2019  14:34           140.542 ngsw-worker.js
14.11.2019  14:34            41.830 ngsw.json
14.11.2019  14:34            37.304 polyfills-es2015.b9d61c8420fecac73ade.js
14.11.2019  14:33           113.605 polyfills-es5.22fcc391de73fbc61a39.js
14.11.2019  14:34             2.338 runtime-es2015.bd8a6f434a70643bf820.js
14.11.2019  14:33             2.335 runtime-es5.89f6f6bdf6a1c8dfa33b.js
14.11.2019  14:34               519 safety-worker.js
14.11.2019  14:34           180.853 styles.a78279866f8ed644cc62.css
14.11.2019  14:34               519 worker-basic.min.js
              25 Datei(en),      2.519.617 Bytes

And for Version 9.0.0-rc.1
bundle_after9
With files sizes:

14.11.2019  14:44           114.857 1-es2015.2eab0115fa339bfffb8d.js
14.11.2019  14:44           123.984 1-es5.2eab0115fa339bfffb8d.js
14.11.2019  14:44             8.158 6-es2015.061ae9b8b08999f9dc7d.js
14.11.2019  14:44             8.695 6-es5.061ae9b8b08999f9dc7d.js
14.11.2019  14:44             2.583 7-es2015.480bd5ab1960564ac076.js
14.11.2019  14:44             3.160 7-es5.480bd5ab1960564ac076.js
14.11.2019  14:45           100.520 8-es2015.b2e7b92e6a7ae57c60ad.js
14.11.2019  14:45           112.264 8-es5.b2e7b92e6a7ae57c60ad.js
14.11.2019  14:44            15.538 9-es2015.874764ed7c67c1148fb4.js
14.11.2019  14:44            16.387 9-es5.874764ed7c67c1148fb4.js
14.11.2019  14:45             1.560 index.html
14.11.2019  14:45           756.609 main-es2015.ba08a7a566bbc3160430.js
14.11.2019  14:45           890.459 main-es5.ba08a7a566bbc3160430.js
02.10.2019  10:25             1.133 manifest.webmanifest
14.11.2019  14:45           141.320 ngsw-worker.js
14.11.2019  14:45            41.662 ngsw.json
14.11.2019  14:44            36.808 polyfills-es2015.d339c9d166f5d5423290.js
14.11.2019  14:45           127.945 polyfills-es5.7a437adb78ef54de54d0.js
14.11.2019  14:44             2.389 runtime-es2015.62474928f6359459e271.js
14.11.2019  14:44             2.386 runtime-es5.62474928f6359459e271.js
14.11.2019  14:45               519 safety-worker.js
14.11.2019  14:44           190.800 styles.2d23fff4184672f07cf1.css
14.11.2019  14:45               519 worker-basic.min.js
              23 Datei(en),      2.700.258 Bytes

There are less files in Version 9.0.0-rc.1, but the overall file size is increased. I didn't update material, so there shouldn't been any restructuring.
Here is my package.json:

{
  "name": "frontend",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "postinstall": "ngcc --properties es2015 browser module main --first-only --create-ivy-entry-points",
    "start": "ng serve",
    "build": "ng build",
    "build:stats": "ng build --stats-json --namedChunks=true --prod",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e",
    "analyze": "webpack-bundle-analyzer dist/stats-es2015.json"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "~9.0.0-rc.1",
    "@angular/cdk": "~8.2.3",
    "@angular/common": "~9.0.0-rc.1",
    "@angular/compiler": "~9.0.0-rc.1",
    "@angular/core": "~9.0.0-rc.1",
    "@angular/forms": "~9.0.0-rc.1",
    "@angular/material": "^8.2.3",
    "@angular/platform-browser": "~9.0.0-rc.1",
    "@angular/platform-browser-dynamic": "~9.0.0-rc.1",
    "@angular/router": "~9.0.0-rc.1",
    "@angular/service-worker": "~9.0.0-rc.1",
    "@auth0/angular-jwt": "^3.0.0",
    "@ngrx/effects": "^8.5.0",
    "@ngrx/entity": "^8.5.0",
    "@ngrx/router-store": "^8.5.0",
    "@ngrx/schematics": "^8.5.0",
    "@ngrx/store": "^8.5.0",
    "@ngrx/store-devtools": "^8.5.0",
    "date-fns": "^2.6.0",
    "hammerjs": "^2.0.8",
    "rxjs": "~6.5.3",
    "tslib": "^1.10.0",
    "zone.js": "~0.10.2"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.900.0-rc.1",
    "@angular/cli": "^9.0.0-rc.1",
    "@angular/compiler-cli": "~9.0.0-rc.1",
    "@angular/language-service": "~9.0.0-rc.1",
    "@types/jasmine": "~3.3.8",
    "@types/jasminewd2": "~2.0.3",
    "@types/node": "^12.11.1",
    "codelyzer": "^5.1.2",
    "jasmine-core": "~3.4.0",
    "jasmine-spec-reporter": "~4.2.1",
    "karma": "~4.1.0",
    "karma-chrome-launcher": "~2.2.0",
    "karma-coverage-istanbul-reporter": "~2.0.1",
    "karma-jasmine": "~2.0.1",
    "karma-jasmine-html-reporter": "^1.4.0",
    "protractor": "~5.4.0",
    "ts-node": "~7.0.0",
    "tslint": "~5.15.0",
    "typescript": "~3.6.4"
  }
}

@filipesilva filipesilva self-assigned this Nov 14, 2019
@Splaktar
Copy link
Member

While 8.2.x of Angular Material and the CDK may not completely break when used with Angular 9.0.0-rc.1, this is not a supported configuration. Please update Angular Material and the CDK to the latest RC (9.0.0-rc.1). There were quite a number of changes to better support Ivy in the 9.0.0-x releases of Angular Material/CDK that did not go into the 8.2.x releases.

It looks like @parys is the only one who has reported an issue with a supported configuration. Is it possible that you can post a GitHub repo with a reproduction?

@elvirdolic
Copy link

@Splaktar my setup is based on angular material 9.0.0-x. angular 9.0.0-x and angular-cli 9.0.0-x @filipesilva how is this possible without any code changes, just run material schematics update where the import path of the modules changed.

@parys
Copy link

parys commented Nov 14, 2019

@Splaktar Right now have no time. but you can look at my repo mylfc. in master is the latest stable angular. At brunch poc/angular9 updated
here is my app branches https://github.com/parys/MyLFC/tree/master/src/MyLiverpool.Web.WebApiNext/ClientApp
https://github.com/parys/MyLFC/tree/poc/angular9/src/MyLiverpool.Web.WebApiNext/ClientApp
if it's not working solution for you please notify me and when I will have some time will post repo with only angular apps without dotnet stuff :)

@Splaktar
Copy link
Member

Splaktar commented Nov 14, 2019

@parys based on the commit, did you use ng update @angular/material @angular/cdk --next to do this update? It doesn't look like the ng update schematics ran.

Can you try running the update schematics manually via ng update @angular/material --migrate-only --from 8 --to 9?

@elvirdolic did you run this manually for your project before posting those size results?

This issue was fixed in PR angular/components#17704 today. We're hoping to get out an rc.2 ASAP so that these migrations can get more testing.

@elvirdolic
Copy link

@Splaktar yes i run the schematics manually with —migrate-only flag when I realized that it didn’t worked by default. We have a quiet big monorepo running this manually would have take too much time. I experienced that some files were not changed and I changed the import paths manually.

@Splaktar
Copy link
Member

@elvirdolic if you have any info on why certain files might have been missed, please open up an issue for that in the Angular Components repo.

@filipesilva
Copy link
Contributor

@parys thank you for the repro! This are the steps I followed to use it:

 git clone https://github.com/parys/MyLFC/
cd MyLFC/src/MyLiverpool.Web.WebApiNext/ClientApp/
yarn
yarn build --output-path dist/ivy

This got me an Ivy build in dist/ivy.

Then I added "angularCompilerOptions": { "enableIvy": false } to src/tsconfig.app.json and ran yarn build --output-path dist/ve to get a View Engine (non-Ivy) build in dist/ve.

To calculate the total size for es2015 bundles in Ivy and VE I used the following commands:

$ du -ach --max-depth=1 dist/ivy/*-es2015*.js
20K     dist/ivy/10-es2015.66f1eb6cd644d67f15ac.js
40K     dist/ivy/11-es2015.0b25ed23683e63edae11.js
24K     dist/ivy/12-es2015.3a06345c9606b3cb8362.js
20K     dist/ivy/13-es2015.8b5a695de5cd68380ac6.js
36K     dist/ivy/14-es2015.45a5aaca76e3deccec4e.js
12K     dist/ivy/15-es2015.13c04e1a0449697b4370.js
16K     dist/ivy/1-es2015.04de2045cc179e64f670.js 
724K    dist/ivy/20-es2015.d70ba6b906a9303a4044.js
20K     dist/ivy/21-es2015.1ae7bc356bff8b92250c.js
8.0K    dist/ivy/22-es2015.97b04a055b5f962e0309.js
20K     dist/ivy/23-es2015.f48ce3c563c84873e4ce.js
20K     dist/ivy/24-es2015.b58ac4301d3a403ff8c4.js
16K     dist/ivy/25-es2015.f779726ae819aa9739f6.js
36K     dist/ivy/26-es2015.01ae8157f3f380909ea2.js
28K     dist/ivy/27-es2015.a5154c0aee44ea51e928.js
52K     dist/ivy/28-es2015.fa9edb5e0d2684ee21ee.js
52K     dist/ivy/29-es2015.18d6fa26c54cd9313e7c.js
32K     dist/ivy/2-es2015.59540042273d26a17f33.js 
4.0K    dist/ivy/30-es2015.d5b3aae4d15fbad1c629.js
8.0K    dist/ivy/31-es2015.121dfca27ac90849a097.js
8.0K    dist/ivy/32-es2015.51a965f1045bc0e40032.js
8.0K    dist/ivy/33-es2015.e49cdd59d097a7be93ce.js
88K     dist/ivy/34-es2015.b7bb306b334a8dff2b75.js
16K     dist/ivy/35-es2015.a9b5ea4321a9fa57bcdb.js
8.0K    dist/ivy/36-es2015.7ba869149da02b085bf4.js
16K     dist/ivy/37-es2015.ef6457b56281155d3388.js
8.0K    dist/ivy/38-es2015.40bd972c02184a18eef1.js
4.0K    dist/ivy/39-es2015.b047fd864a142314cfd6.js
16K     dist/ivy/3-es2015.cbe344149634737fc684.js 
12K     dist/ivy/40-es2015.8c9381dc0ec0f646cd24.js       
8.0K    dist/ivy/41-es2015.d847d183be44b05fa266.js       
36K     dist/ivy/42-es2015.96223f01291c211cd4ca.js       
12K     dist/ivy/43-es2015.b62260233be0d6f8d472.js       
20K     dist/ivy/44-es2015.1220c9a4e782b623849e.js       
28K     dist/ivy/4-es2015.b842266e2f6893b4dc3c.js        
16K     dist/ivy/5-es2015.084e91003abe78df367e.js        
64K     dist/ivy/6-es2015.472e4ff75cdfb2259d88.js        
20K     dist/ivy/8-es2015.160eead525971e57ec5d.js        
48K     dist/ivy/9-es2015.e1f46ad685ec827665c5.js        
24K     dist/ivy/common-es2015.1cc936be97b3297c7814.js   
1.2M    dist/ivy/main-es2015.d29f2ce5e2c36181e304.js     
1.0K    dist/ivy/polyfills-es2015.f3658a1e714c1192c0ee.js
4.0K    dist/ivy/runtime-es2015.0e22c5d5d399b8826217.js  
2.8M    total
$ du -ach --max-depth=1 dist/ve/*-es2015*.js
16K     dist/ve/11-es2015.436fd4d1bf6c2f0af9f9.js
16K     dist/ve/12-es2015.ea4b19038c80d89e69ce.js
32K     dist/ve/13-es2015.efc10db2fca227bbe236.js
60K     dist/ve/14-es2015.91df8614ec1caae43957.js
40K     dist/ve/15-es2015.2990bb15dfa6ce50f91a.js
20K     dist/ve/16-es2015.e0377ebbf3e47c6176cf.js
24K     dist/ve/17-es2015.5ec1d39a99d8da6bcc2c.js
56K     dist/ve/18-es2015.6bf738114da2a757bfbf.js
48K     dist/ve/19-es2015.4975181c69a937241848.js
12K     dist/ve/1-es2015.e2edbcc2ba94d3eeb590.js
724K    dist/ve/24-es2015.a54325b4608772fa6a63.js
60K     dist/ve/25-es2015.e4b5460568b28b30e4f6.js
56K     dist/ve/26-es2015.b3a858106e8843e08d0a.js
44K     dist/ve/27-es2015.75f511dd04669a4298f5.js
60K     dist/ve/28-es2015.9fbb6faf061afb5906da.js
140K    dist/ve/29-es2015.acbf6174001c8fadef14.js
28K     dist/ve/2-es2015.d988558ff162cb002673.js
12K     dist/ve/30-es2015.31b863d3559f50aacc60.js
144K    dist/ve/31-es2015.3e5f8dea4af5ba9f5e08.js
32K     dist/ve/32-es2015.182bc0c78723ed7d0b05.js
48K     dist/ve/33-es2015.6f3cc3b8b1b9be1ab8a2.js
80K     dist/ve/34-es2015.9ee5d6fb696cc566e922.js
52K     dist/ve/35-es2015.1940a4b6b9de5becc968.js
80K     dist/ve/36-es2015.4e2148a4004807778a4e.js
20K     dist/ve/37-es2015.bb2a2644e78a5ad4b82e.js
12K     dist/ve/38-es2015.9081e5668f1f357b5284.js
16K     dist/ve/39-es2015.17e16102a3aefbc4e3fe.js
4.0K    dist/ve/3-es2015.5e726b861d01ef28e2b0.js
172K    dist/ve/40-es2015.f2a15b2740f8fdc676b7.js
12K     dist/ve/41-es2015.6a33304b86fe61a6c7bf.js
64K     dist/ve/42-es2015.577ec06bbd3d89f34bdb.js
44K     dist/ve/43-es2015.d1a8977b4782c345b13e.js
8.0K    dist/ve/44-es2015.520a10ae0e9eaa3125dd.js
28K     dist/ve/45-es2015.0a07fd9a79e4bc0ebecc.js
12K     dist/ve/46-es2015.a4ab78d3fffea4014f81.js
16K     dist/ve/47-es2015.d6b5df0f892830a121d6.js
44K     dist/ve/48-es2015.2f5b1e959ada640f93e3.js
24K     dist/ve/4-es2015.f151106c7ac588e420d4.js
20K     dist/ve/5-es2015.79b722303bba5036b8ec.js
16K     dist/ve/6-es2015.5302d2088d0cc1cb1b35.js
32K     dist/ve/7-es2015.c83e7bb4e8f7349d9f16.js
12K     dist/ve/8-es2015.5a2be8ff289c8acaad71.js
56K     dist/ve/9-es2015.6b38148134b0713697bc.js
28K     dist/ve/common-es2015.d8f40e56a357ada60df5.js
1.1M    dist/ve/main-es2015.cc5edbff7dd51d002dd6.js
1.0K    dist/ve/polyfills-es2015.b998c65176a95cc7e582.js
4.0K    dist/ve/runtime-es2015.c3b1be294314c03cc5e5.js
3.6M    total

I can verify exactly what you described: Ivy is a total of 2.8M while VE is 3.6M. Ivy did have a slightly bigger (1.2 vs 1.1M) main bundle.

I chalk this one off as a victory for Ivy though. It's a huge size savings!

@filipesilva
Copy link
Contributor

@elvirdolic well anytime that dependencies are updated, the total application code changes. In version 9 we also switch projects over to using Ivy so that might change things further.

@elvirdolic @wambowams if you can provide me access to the project I can investigate your cases directly. Making a private github project (which is free now) and inviting me to it might be the best way to do it without exposing client projects to the web.

@wambowams
Copy link
Author

@filipesilva I'm not allowed to share the projects source to anyone outside our company. But thank u for the offer. I will update material and will take more attention to file size over the next releases.

@elvirdolic
Copy link

@filipesilva our main went from 2MB to 2.2MB after upgrade. Overall size reduction is massive but the main is bigger :). If you can guide me what do you need, I could help to create a reproduction.

@vladimiry
Copy link

vladimiry commented Feb 11, 2020

Overall size reduction is massive but the main is bigger :)

I recently switched to the ES/ivy way of importing the lazy module and I noticed the same issue you described (main bundle got bigger, lazy bundle got smaller, so some code got moved to main bundle from the lazy one). But I got the expected behavior back by explicitly telling the webpack that I want _db-view module to be put into a separate chunk.

So if you load the lazy module using old/deprecated way, using NgModuleFactoryLoader.load("./_db-view/db-view.module#DbViewModule") + AngularCompilerPlugin.additionalLazyModules, then the entire lazy module gets automatically put into a separate chunk. But if you use ES importing you have to tweak the webpack's optimization.splitChunks config to get entire lazy module to be put in a separate chunk, at lest in my case.

Not sure this info will be helpful to someone since I don't use Angular CLI in the referenced project but use AngularCompilerPlugin directly.

@filipesilva
Copy link
Contributor

@elvirdolic I'm currently following up on this in https://github.com/angular/angular-cli/issues/16866. If you could provide me with a repro, even privately, I could take a look.

@vladimiry I'm very interested in what you're doing! Can you give me a bit more context please? I didn't quite follow. An example would be super cool too!

@filipesilva filipesilva unpinned this issue Feb 12, 2020
@vladimiry
Copy link

vladimiry commented Feb 12, 2020

@filipesilva, I just described the use of chunks splitting webpack's feature.

See 4 different output listings using angular v9.0.0:

  • ES import of _db-view module (notice _db-view.js has not been created, ie all the custom app code is put into single index.js chunk)
573964 index.js
4438375 vendor.js
4011 _db-view.js
577075 index.js
4438375 vendor.js
131362 _db-view.js
442694 index.js
4438375 vendor.js
133796 _db-view.js
442564 index.js
4438375 vendor.js

So if NgModuleFactoryLoader.load("./_db-view/db-view.module#DbViewModule") + AngularCompilerPlugin.additionalLazyModules used then there is no need to tweak the webpack config. But if you switch to the ES import the webpack config needs to be adjusted in order to put entire _db-view module/folder into a separate _db-view.js chunk.

@filipesilva
Copy link
Contributor

@vladimiry not super sure what's happening there. That would make sense if you were not using Ivy though.

You had const {DbViewModule} = await import("src/web/browser-window/app/_db-view/db-view.module"); as the ES dynamic import. But with VE, we don't recognize this imports properly everywhere. In fact, we only recognize this format:

// This ONLY matches the original source code format below:
// loadChildren: () => import('IMPORT_STRING').then(M => M.EXPORT_NAME)
// And expects that source code to be transformed by NGC (see comment for importFactory).
// It will not match nor alter variations, for instance:
// - not using arrow functions
// - using `await` instead of `then`
// - using a default export (https://github.com/angular/angular/issues/11402)
// The only parts that can change are the ones in caps: IMPORT_STRING, M and EXPORT_NAME.

But I think you were using Ivy in your example? So that's really weird.

@vladimiry
Copy link

vladimiry commented Feb 13, 2020

@filipesilva, the comment you referenced seems to be related to rewriting the Route definitions during the compiling stage. But I was describing the case of lazy-loading the Angular module without using the Route-thing, just dynamic lazy-loading the module from any point of the app.

But I think you were using Ivy in your example?

Yes, Ivy enabled there starting from some Angular v8 version.

@filipesilva
Copy link
Contributor

Tried to reproduce by doing this:

  • ng new latest-app --routing && cd latest-app
  • ng generate module lazy --route lazy --module app.module
  • ng build --prod, saw a lazy chunk with 751 bytes
  • added "lazyModules": ["src/app/lazy/lazy.module.ts"] to my build options
    • this passes it on to AngularCompilerPlugin.additionalLazyModules
  • built again, saw a lazy chunk with 751 bytes
  • replaced the ES dynamic import with NgModuleFactoryLoader.load in src/app/app-routing.module.ts
const routes: Routes = [
  // { path: 'lazy', loadChildren: () => import('./lazy/lazy.module').then(m => m.LazyModule) }
];
NgModuleFactoryLoader.load('./lazy/lazy.module#LazyModule');
  • built again, saw error:
ERROR in src/app/app-routing.module.ts:16:23 - error TS2339: Property 'load' does not exist on type 'typeof NgModuleFactoryLoader'.

16 NgModuleFactoryLoader.load('./lazy/lazy.module#LazyModule');
  • reverted the previous change, opened node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/webpack-configs/browser.js and manually changed the cache groups
                cacheGroups: {
                    default: !!commonChunk && {
                        chunks: 'async',
                        minChunks: 2,
                        priority: 10,
                    },
                    common: !!commonChunk && {
                        name: 'common',
                        chunks: 'async',
                        minChunks: 2,
                        enforce: true,
                        priority: 5,
                    },
                    vendors: false,
                    vendor: !!vendorChunk && {
                        name: 'vendor',
                        chunks: 'initial',
                        enforce: true,
                        test: (module, chunks) => {
                            const moduleName = module.nameForCondition ? module.nameForCondition() : '';
                            return /[\\/]node_modules[\\/]/.test(moduleName)
                                && !chunks.some(({ name }) => utils_1.isPolyfillsEntry(name)
                                    || globalStylesBundleNames.includes(name));
                        },
                    },
                  "lazy": {
                    test: /src[\\/]app[\\/]lazy/,
                    name: "lazy",
                    chunks: "all",
                  },
                },
  • built again, saw a lazy chunk with 751 bytes

So I'm really confused by the behaviour you're seeing. I don't understand how you could use NgModuleFactoryLoader.load at all, and I can't imagine how these bundles could be any different when using Ivy.

Any chance you could give me a repro, or instructions on how to build your repo and what changes to make to see this behaviour?

@vladimiry
Copy link

vladimiry commented Feb 13, 2020

I don't understand how you could use NgModuleFactoryLoader.load at all

I put it as NgModuleFactoryLoader.load in above messages for shortness. So the instance needs to be injected:

    constructor(
        private moduleLoader: NgModuleFactoryLoader,
    ) {}

And then you call it like on this line: const moduleFactory = await this.moduleLoader.load("./_db-view/db-view.module#DbViewModule");. On that commit on the left side is a use of old/deprecated way of lazy-loading the modules with NgModuleFactoryLoader, on the right side is the ES import + webpack optimization.splitChunks tweak.

or instructions on how to build your repo and what changes to make to see this behaviour

Repo is here https://github.com/vladimiry/ElectronMail/ To build Angular-related stuff you run yarn build:web:browser-window (the build outcome comes into ./app/web/browser-window/). The commit that switched the lazy module loading from using NgModuleFactoryLoader to regular ES import + webpack optimization.splitChunks tweak.

@filipesilva
Copy link
Contributor

@vladimiry I did this:

  • git clone https://github.com/vladimiry/ElectronMail/ && cd ElectronMail
  • yarn
  • yarn build:web:browser-window && ls -la app/web/browser-window/
total 5109
drwxr-xr-x 1 kamik 197609       0 Feb 13 16:05 .
drwxr-xr-x 1 kamik 197609       0 Feb 13 16:05 ..
-rw-r--r-- 1 kamik 197609  131593 Feb 13 16:05 _db-view.js
drwxr-xr-x 1 kamik 197609       0 Feb 13 16:05 assets
-rw-r--r-- 1 kamik 197609     833 Feb 13 16:05 index.css
-rw-r--r-- 1 kamik 197609     542 Feb 13 16:05 index.html
-rw-r--r-- 1 kamik 197609  443705 Feb 13 16:05 index.js
-rw-r--r-- 1 kamik 197609  195805 Feb 13 16:05 vendor.css
-rw-r--r-- 1 kamik 197609 4438375 Feb 13 16:05 vendor.js
  • edited webpack-configs/web/browser-window.ts to remove the cache group for dbview
                cacheGroups: {
                    commons: {
                        test: /[\\/]node_modules[\\/]|[\\/]vendor[\\/]/,
                        name: "vendor",
                        chunks: "all",
                    },
                    // "_db-view": {
                    //     test: /src[\\/]web[\\/]browser-window[\\/]app[\\/]_db-view/,
                    //     name: "_db-view",
                    //     chunks: "all",
                    // },
                },
  • rm -rf app/web/browser-window/ && yarn build:web:browser-window && ls -la app/web/browser-window/
total 5101
drwxr-xr-x 1 kamik 197609       0 Feb 13 16:15 .
drwxr-xr-x 1 kamik 197609       0 Feb 13 16:15 ..
drwxr-xr-x 1 kamik 197609       0 Feb 13 16:15 assets
-rw-r--r-- 1 kamik 197609     833 Feb 13 16:15 index.css
-rw-r--r-- 1 kamik 197609     486 Feb 13 16:15 index.html
-rw-r--r-- 1 kamik 197609  574975 Feb 13 16:15 index.js
-rw-r--r-- 1 kamik 197609  195805 Feb 13 16:15 vendor.css
-rw-r--r-- 1 kamik 197609 4438375 Feb 13 16:15 vendor.js

So without the cacheGroups your build doesn't actually produce another chunk. This makes me think that _db-view ends up not being lazy loaded at all.

I checked your tsconfig and noticed you were using "module": "commonjs",. This causes typescript to not actually emit the ES import statements. I added "compilerOptions": { "module": "esnext", }, in src/web/browser-window/tsconfig.json (couldn't add it in the base tsconfig because you also use it for compiling the webpack configs) and built again:

  • rm -rf app/web/browser-window/ && yarn build:web:browser-window && ls -la app/web/browser-window/
total 5145
drwxr-xr-x 1 kamik 197609       0 Feb 13 16:25 .
drwxr-xr-x 1 kamik 197609       0 Feb 13 16:25 ..
-rw-r--r-- 1 kamik 197609  147580 Feb 13 16:25 0.js
-rw-r--r-- 1 kamik 197609  195806 Feb 13 16:25 1.js
-rw-r--r-- 1 kamik 197609   30699 Feb 13 16:25 2.js
-rw-r--r-- 1 kamik 197609  145509 Feb 13 16:25 3.js
drwxr-xr-x 1 kamik 197609       0 Feb 13 16:25 assets
-rw-r--r-- 1 kamik 197609     833 Feb 13 16:25 index.css
-rw-r--r-- 1 kamik 197609     486 Feb 13 16:25 index.html
-rw-r--r-- 1 kamik 197609  144076 Feb 13 16:25 index.js
-rw-r--r-- 1 kamik 197609  195805 Feb 13 16:25 vendor.css
-rw-r--r-- 1 kamik 197609 4380827 Feb 13 16:25 vendor.js

Now we can actually see multiple separate chunks be created automatically (one for each lazy import) and a much smaller index.js.

You can even do better if you disable your vendor cacheGroups. That doesn't help at all because it prevents optimizations in the eagerly loaded chunks, and also eagerly loads dependencies for your lazy chunks.

total 5129
drwxr-xr-x 1 kamik 197609       0 Feb 13 16:28 .
drwxr-xr-x 1 kamik 197609       0 Feb 13 16:28 ..
-rw-r--r-- 1 kamik 197609  596791 Feb 13 16:28 0.js
-rw-r--r-- 1 kamik 197609  268453 Feb 13 16:28 1.js
-rw-r--r-- 1 kamik 197609  150874 Feb 13 16:28 2.js
-rw-r--r-- 1 kamik 197609  195806 Feb 13 16:28 3.js
-rw-r--r-- 1 kamik 197609   30699 Feb 13 16:28 4.js
-rw-r--r-- 1 kamik 197609  483746 Feb 13 16:28 5.js
-rw-r--r-- 1 kamik 197609  145509 Feb 13 16:28 6.js
drwxr-xr-x 1 kamik 197609       0 Feb 13 16:28 assets
-rw-r--r-- 1 kamik 197609  196638 Feb 13 16:28 index.css
-rw-r--r-- 1 kamik 197609     370 Feb 13 16:28 index.html
-rw-r--r-- 1 kamik 197609 3155513 Feb 13 16:28 index.js

This way you get a slightly smaller total payload, and a significantly smaller initial payload.

More to the point insofar as this issue is concerned though, the cache group doesn't do anything useful when you already have ES import() statements with Ivy.

@vladimiry
Copy link

vladimiry commented Feb 13, 2020

@filipesilva, thanks for thorough analysis. So "compilerOptions": { "module": "esnext", } is the key thing here which I missed.

You can even do better if you disable your vendor cacheGroups. That doesn't help at all because it prevents optimizations in the eagerly loaded chunks, and also eagerly loads dependencies for your lazy chunks.

Yeah, that vendor cacheGroups added there initially and intentionally for my convenience (the css part of this bundle gets independently loaded by different windows, hacky stuff) but maybe it's time to reconsider and get rid of it even though that's a desktop app (the size is not so important, but code parsing still takes time same like in the regular browser). You also probably noticed that there is no any code minification applied, it's also by design as it's the desktop app, not the real web.

@santhony7
Copy link

This was pretty frustrating when expecting the file size to improve. I have a fairly large app and the file size on main went up from 587K to 610K. I'm not even sure where to start looking for the issue.

"dependencies": {
"@angular/animations": "^9.0.2",
"@angular/common": "^9.0.2",
"@angular/compiler": "^9.0.2",
"@angular/core": "^9.0.2",
"@angular/forms": "^9.0.2",
"@angular/localize": "~9.0.2",
"@angular/material": "^9.0.0",
"@angular/platform-browser": "^9.0.2",
"@angular/platform-browser-dynamic": "^9.0.2",
"@angular/platform-server": "^9.0.2",
"@angular/router": "^9.0.2",
"@nguniversal/common": "^8.1.1",
"@nguniversal/express-engine": "^8.1.1",
"@nguniversal/module-map-ngfactory-loader": "^8.1.1",
"angular2-text-mask": "^9.0.0",
"core-js": "^2.6.5",
"custom-event-polyfill": "^1.0.7",
"fingerprintjs2": "^2.0.6",
"gridlex": "^2.7.1",
"http-proxy-middleware": "^0.18.0",
"immutable": "^3.8.2",
"jsvat": "^2.1.2",
"ngx-cookie-service": "^2.2.0",
"node-fetch": "^2.3.0",
"primeng": "9.0.0-rc.4",
"rxjs": "^6.5.3",
"sass-loader": "^7.1.0",
"ts-loader": "^4.5.0",
"tslib": "^1.10.0",
"url-search-params-polyfill": "^4.0.1",
"zone.js": "~0.10.2"
},
"devDependencies": {
"@angular-devkit/build-angular": "~0.900.3",
"@angular/cdk": "^9.0.0",
"@angular/cli": "9.0.3",
"@angular/compiler-cli": "9.0.2",
"@angular/language-service": "9.0.2",
"@types/google.analytics": "0.0.39",
"@types/jasmine": "~2.5.53",
"@types/jasminewd2": "^2.0.6",
"@types/node": "^12.11.1",
"codelyzer": "^5.1.2",
"compression": "^1.7.4",
"cookie-parser": "^1.4.4",
"express": "^4.16.4",
"git-describe": "^4.0.4",
"jasmine-core": "~2.6.2",
"jasmine-spec-reporter": "~4.1.0",
"karma": "^4.0.1",
"karma-chrome-launcher": "~2.1.1",
"karma-cli": "~1.0.1",
"karma-coverage-istanbul-reporter": "^1.4.3",
"karma-jasmine": "^1.1.2",
"karma-jasmine-html-reporter": "^0.2.2",
"nodemon": "^1.18.11",
"protractor": "^5.4.2",
"ts-node": "~3.2.0",
"tslint": "~5.11.0",
"typescript": "^3.7.5",
"webpack-cli": "^3.3.0"
}

@filipesilva
Copy link
Contributor

@santhony7 can you check if your total app size, with the size of the lazy bundles included, went down?

@izmaylovdev
Copy link

izmaylovdev commented Mar 2, 2020

@filipesilva got same problem, here is bundle-analyzer results
Before:
image
After:
image

@izmaylovdev
Copy link

I think this may be due to ngcc processing @angular/* packages, should ngcc do this?

@filipesilva
Copy link
Contributor

Yes, ngcc should process those packages.

Webpack Bundle analyzer won't give the correct numbers in a lot of cases though. Using source-map-explorer will give you a more accurate picture of the code in your bundles, as described in https://angular.io/guide/deployment#inspect-the-bundles.

@santhony7
Copy link

@filipesilva Yeah, I do know that the total size has been reduced but I also think it is important to be very specific about that when claiming file size reduction. As you know, the browser's time-to-interactive or the page-speed-index is pretty much the only metric that matters to leadership. Selling them the upgrade on the promise of faster (initial) download only to find out you made it worse can be a bit disheartening.

@filipesilva
Copy link
Contributor

To the best of my knowledge, we only have one situation currently where the main bundle gets bigger: https://github.com/angular/angular-cli/issues/16866. Still trying to figure out what we can do in that case. Do you also use material in your app?

@izmaylovdev
Copy link

Yes. I use material, but it is not big part of my app. Thanks for your help.

@santhony7
Copy link

@filipesilva Yes sir we do. "@angular/material": "^9.1.0",

@yamidvo
Copy link

yamidvo commented Mar 26, 2020

Hi everyone! my main.js is considerably bigger with ivy. Any idea what it could be?

Before:
Captura de Pantalla 2020-03-26 a la(s) 12 32 09 p  m
After:
Captura de Pantalla 2020-03-26 a la(s) 12 31 55 p  m

@filipesilva
Copy link
Contributor

@yamidvo the tool you are using (webpack-bundle-analyzer) will not provide very precise numbers with Angular CLI 9, because we process bundles after they leave webpack. A better tool to get that data would be source-map-explorer as described in https://angular.io/guide/deployment#inspect-the-bundles. That will give you very precise measurements.

@parys
Copy link

parys commented Mar 26, 2020

2020-03-26_21-17-31
@filipesilva
Full bundle: 2.88 MB
Main bundle: 972, 9 KB (size in webpack-bundle-analyzer 973.6 KB (less than 1KB)
Angular modules: 704.45 KB + rxjs 48.26 + zone.js 35.7 = 788 KB is only for angular stuff. ( and I've already moved to lazy modules almost all material modules that not used at the index page. As I remember angular 9 decrease full size from 3.4 to 2.9 MB but increased main bundle a lot( and almost all is taken by angular(

@yamidvo
Copy link

yamidvo commented Mar 26, 2020

Similarly, the difference is large

before:
Captura de Pantalla 2020-03-26 a la(s) 1 54 14 p  m

after:
Captura de Pantalla 2020-03-26 a la(s) 1 54 21 p  m

@filipesilva
Copy link
Contributor

@parys I can't say much regarding that screenshot as I don't have anything to compare it to. Could you include a screenshot of the source map explorer output from before 9 please?

@yamidvo I noticed you have a large shared module, which can be a problem as described in #16146 (comment). Have you tried what I mention in the "What you can do right now" section of that comment? You might have static imports to your shared code from your main entry point, causing it to not be loaded lazily at all. I don't think this is a problem we can fix on our side.

Either way, something else you two can do is to opt out of Ivy, as described in https://angular.io/guide/ivy#opting-out-of-ivy-in-version-9. This should get back to the setup used in Angular version 8.

@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 Apr 30, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests