简体   繁体   中英

Angular - How to do code-splitting in Angular 9 - Ivy?

In Angular 8 ( 8.2.14 ), my app can do code splitting by lazy loaded modules. The build logs is as follows (some redundant lines is omitted), 36 chunks:

chunk {3} runtime-es2015.c423f91aaae76527df5b.js (runtime) 3.08 kB [entry] [rendered]
chunk {3} runtime-es5.c423f91aaae76527df5b.js (runtime) 3.07 kB [entry] [rendered]
chunk {2} 2-es2015.539ede95a6745ef5d2bf.js () 22.6 kB  [rendered]
...
chunk {12} polyfills-es2015.32f951d8d1908f922bdc.js (polyfills) 35.6 kB [initial] [rendered]
chunk {10} 10-es2015.8da7355d1a7b512401a1.js () 31.7 kB  [rendered]
...
chunk {0} 0-es5.bfd951267cfba9ec1f8d.js () 32.4 kB  [rendered]
chunk {1} common-es2015.10ba6f24dba298440ecc.js (common) 13.4 kB  [rendered]
chunk {1} common-es5.10ba6f24dba298440ecc.js (common) 19.6 kB  [rendered]
...
chunk {11} main-es2015.29e5558ae4fba71b1763.js (main) 755 kB [initial] [rendered]
chunk {11} main-es5.29e5558ae4fba71b1763.js (main) 806 kB [initial] [rendered]
chunk {36} 36-es2015.f988ae90643f26871ae8.js () 231 kB  [rendered]
...
chunk {15} vendor-es5.e7af4362172dcd47c55b.js (vendor) 1.41 MB [initial] [rendered]
chunk {14} styles.5ab582a2e3cd140ea795.css (styles) 301 kB [initial] [rendered]

After upgraded to Angular 9 ( 9.1.12 ), using ng update ( ng update @angular/core@9 @angular/cli@9 ).

The app run fine but the production build consist of several big bundles, build logs as follows, 6 chunks:

chunk {0} runtime-es2015.602346de10cd8007336b.js (runtime) 2.25 kB [entry] [rendered]
chunk {0} runtime-es5.602346de10cd8007336b.js (runtime) 2.25 kB [entry] [rendered]
chunk {3} polyfills-es2015.b2b33e7ed47c34d70569.js (polyfills) 37.4 kB [initial] [rendered]
chunk {2} main-main-module-es2015.f40c22576bd3c677d2bf.js (main-main-module) 1.63 kB  [rendered]
chunk {2} main-main-module-es5.f40c22576bd3c677d2bf.js (main-main-module) 3.24 kB  [rendered]
chunk {4} polyfills-es5.9fc110dc43c419da899c.js (polyfills-es5) 130 kB [initial] [rendered]
chunk {1} main-es2015.49ac9fca75e556a35c57.js (main) 1.45 MB [initial] [rendered]
chunk {1} main-es5.49ac9fca75e556a35c57.js (main) 1.54 MB [initial] [rendered]
chunk {6} vendor-es2015.b8aa44d253e8fc5e1203.js (vendor) 2.28 MB [initial] [rendered]
chunk {6} vendor-es5.b8aa44d253e8fc5e1203.js (vendor) 2.44 MB [initial] [rendered]
chunk {5} styles.03960512702293db9549.css (styles) 288 kB [initial] [rendered]

So, how to do code-splitting on lazy loaded modules in Angular 9, Ivy renderer?

Notes:

  • The upgrade is ran automatically by ng update , no manual fixes.

  • All loadChildren is changed to new syntax:

     loadChildren: () => import('../authentication/authentication.module').then((m) => m.AuthenticationModule),
  • The relevant angular.json configs is here:

     "production": { "fileReplacements": [ { "replace": "apps/web-web/src/environments/environment.ts", "with": "apps/web-web/src/environments/environment.prod.ts" } ], "optimization": true, "outputHashing": "all", "sourceMap": false, "extractCss": true, "namedChunks": false, "extractLicenses": true, "vendorChunk": true, "buildOptimizer": true, "budgets": [ { "type": "initial", "maximumWarning": "2mb", "maximumError": "5mb" }, { "type": "anyComponentStyle", "maximumWarning": "6kb", "maximumError": "10kb" } ], "serviceWorker": true, "ngswConfigPath": "apps/web-web/ngsw-config.json" } }
  • This a project inside a Nx workspace with xplat .

  • We don't want to upgrade to Angular 10 now, as we are sharing code with a Nativescript Angular project, and want to wait until Nativescript works well with Angular 10.

  • Typescript configs:

     // tsconfig.json { "compileOnSave": false, "compilerOptions": { "rootDir": ".", "sourceMap": true, "declaration": false, "moduleResolution": "node", "emitDecoratorMetadata": true, "experimentalDecorators": true, "importHelpers": true, "target": "es2015", "module": "esnext", "typeRoots": ["node_modules/@types"], "lib": ["es2017", "dom"], "skipLibCheck": true, "skipDefaultLibCheck": true, "resolveJsonModule": true, "allowSyntheticDefaultImports": true, "baseUrl": ".", "paths": { "@workspacename/*": ["libs/*"], "@workspacename/nativescript": ["xplat/nativescript/index.ts"], "@workspacename/nativescript/*": ["xplat/nativescript/*"], "@workspacename/web": ["xplat/web/index.ts"], "@workspacename/web/*": ["xplat/web/*"], "core-js/es7/reflect": ["node_modules/core-js/proposals/reflect-metadata"], "core-js/es6/*": ["node_modules/core-js/es/*"] } }, "exclude": ["node_modules", "tmp"] } // apps/project-name/tsconfig.json { "extends": "../../tsconfig.json", "compilerOptions": { "types": ["node", "jest"] }, "include": ["**/*.ts"] } // apps/project-name/tsconfig.app.json { "extends": "./tsconfig.json", "compilerOptions": { "outDir": "../../dist/out-tsc", "types": [] }, "files": [ "src/main.ts", "src/polyfills.ts" ], "include": [ "**/*.d.ts" ], "exclude": [ "src/test-setup.ts", "**/*.spec.ts", "**/*.stories.ts" ] }

Make sure you are not importing your lazy (child) modules into app.module.

(wrong)

app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

import { CustomersModule } from './customers/customers.module';
import { OrdersModule } from './orders/orders.module';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    CustomersModule,
    OrdersModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

(right)

app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

(both wrong and right code above uses this routing file:)

app-routing.module.ts:

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

const routes: Routes = [
  { path: 'customers', loadChildren: () => import('./customers/customers.module').then(m => m.CustomersModule) },
  { path: 'orders', loadChildren: () => import('./orders/orders.module').then(m => m.OrdersModule) }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM