在具有路由的模块中导入具有路由的延迟加载模块会中断路由

msa*_*ord 5 lazy-loading angular angular-router

我们的angular 4.3.6应用程序具有延迟加载的模块,例如Fleet,Maintenance,Car等。

我的顶级应用路由器如下所示:

const routes: Routes = [
  { path: '', redirectTo: 'fleet', pathMatch: 'full' },
  {
    path: '',
    component: AppComponent,
    canActivate: [AuthenticationGuard],
    children: [
      {
        path: 'fleet',
        loadChildren: "./modules/fleet.module",
        canActivate: [AuthenticationGuard]
      },
      {
        path: 'car/:id',
        loadChildren: "./modules/car.module",
        canActivate: [AuthenticationGuard]
      },
      {
        path: 'maintenanceProgram',
        loadChildren: "./modules/maintenanceProgram.module",
        canActivate: [AuthenticationGuard]
      }
}
Run Code Online (Sandbox Code Playgroud)

我们确实有一个共享模块,其中包含在整个应用程序中使用的通用组件(我们有很多通用组件)。但是,有一些组件(如模式)仅由MaintenanceProgramCar模块共享,而在其他任何地方均未使用。

为了使共享模块合理,我仅将这些曾经重复使用的组件包括在MaintenanceProgram模块中,然后将它们导出,然后将MaintenanceProgram模块导入Car模块中,以访问导出的组件。

无论是CarMaintenanceProgram模块具有以下嵌入子路由调用在各自的@NgModule.imports[]

汽车:

const CarModuleRoutes = RouterModule.forChild([
  {
    path: '',
    component: CarComponent,
    canActivate: [AuthenticationGuard]
  },
  {
    path: ':id',
    component: CarComponent,
    canActivate: [AuthenticationGuard]
  }
]);
Run Code Online (Sandbox Code Playgroud)

和维护计划:

const MaintenanceProgramModuleRoutes = RouterModule.forChild([
  {
    path: '',
    component: MaintenanceProgramComponent,
    canActivate: [AuthenticationGuard]
  }
]);
Run Code Online (Sandbox Code Playgroud)

这显然也不是正确的方法

  1. 子路由,或
  2. 到模块包含

因为当我加载Car路线时,我会获得维护计划的默认路线

我试过了:

  1. 更改的进口秩序MaintenanceProgramModuleRoutesCarModuleRoutesCarModule@NgModule.imports[]
  2. 从CarModule删除空路径。

*是创建另一个包含路由器而不包含共享组件的共享模块的唯一解决方案,还是有另一种更优雅的方式来实现此目的?

这是一个简化的示例,实际上,我们有许多路由和数百个组件,它们仅被重用两次或三次。随着应用程序的增长,这个问题肯定会持续到将来,因此我需要一个可伸缩且可维护的解决方案。创建数十个或更多额外的共享模块是不可行的。

Twi*_*her 6

实际上,在创建共享模块时,无需关心使用共享模块一小部分的模块,因为Angular的摇树将仅保留导入模块中使用的代码,并删除其余部分。

我已经准备了一个最小的项目来演示它:https : //github.com/youkouleley/Angular-treeshaking-demo

该项目有两个惰性模块:AModuleBModule。这两个模块都将导入SharedModuleSharedModule导出三个组成部分:

  • AComponent用于AModule
  • BComponent用于BModule
  • BothComponent用于AModule BModule

这是ng build在生产模式下打开该项目并打开4-es2015.<hash>.js文件时所获得的:

(window.webpackJsonp = window.webpackJsonp || []).push([[4], {
      KImX: function (n, l, u) {
        "use strict";
        u.r(l);
        var t = u("8Y7J");
        class a {
          constructor() {}
          ngOnInit() {}
        }
        var r = u("phyl");
        class o {}
        var c = u("pMnS"),
        s = t.gb({
            encapsulation: 0,
            styles: [[""]],
            data: {}
          });
        function b(n) {
          return t.sb(0, [(n()(), t.ib(0, 0, null, null, 1, "p", [], null, null, null, null, null)), (n()(), t.rb(-1, null, ["a works!"]))], null, null)
        }
        function i(n) {
          return t.sb(0, [(n()(), t.ib(0, 0, null, null, 1, "app-a", [], null, null, null, b, s)), t.hb(1, 114688, null, 0, a, [], null, null)], function (n, l) {
            n(l, 1, 0)
          }, null)
        }
        var p = t.eb("app-a", a, i, {}, {}, []),
        e = u("gJxL"),
        f = u("SVse"),
        h = u("iInd"),
        d = u("PCNd");
        u.d(l, "AModuleNgFactory", function () {
          return v
        });
        var v = t.fb(o, [], function (n) {
            return t.ob([t.pb(512, t.j, t.T, [[8, [c.a, p, e.a]], [3, t.j], t.u]), t.pb(4608, f.i, f.h, [t.r, [2, f.o]]), t.pb(1073742336, f.b, f.b, []), t.pb(1073742336, h.l, h.l, [[2, h.q], [2, h.k]]), t.pb(1073742336, d.a, d.a, []), t.pb(1073742336, o, o, []), t.pb(1024, h.i, function () {
                  return [[{
                        path: "a",
                        component: a
                      }, {
                        path: "both",
                        component: r.a
                      }
                    ]]
                }, [])])
          })
      },
      PCNd: function (n, l, u) {
        "use strict";
        u.d(l, "a", function () {
          return t
        });
        class t {}
      },
      gJxL: function (n, l, u) {
        "use strict";
        var t = u("8Y7J"),
        a = u("phyl");
        u.d(l, "a", function () {
          return s
        });
        var r = t.gb({
            encapsulation: 0,
            styles: [[""]],
            data: {}
          });
        function o(n) {
          return t.sb(0, [(n()(), t.ib(0, 0, null, null, 1, "p", [], null, null, null, null, null)), (n()(), t.rb(-1, null, ["both works!"]))], null, null)
        }
        function c(n) {
          return t.sb(0, [(n()(), t.ib(0, 0, null, null, 1, "app-both", [], null, null, null, o, r)), t.hb(1, 114688, null, 0, a.a, [], null, null)], function (n, l) {
            n(l, 1, 0)
          }, null)
        }
        var s = t.eb("app-both", a.a, c, {}, {}, [])
      },
      phyl: function (n, l, u) {
        "use strict";
        u.d(l, "a", function () {
          return t
        });
        class t {
          constructor() {}
          ngOnInit() {}
        }
      }
    }
  ]);
Run Code Online (Sandbox Code Playgroud)

需要注意的是,BComponentSharedModule从丢失AModule块。对于BModule不包含的块,相同AComponent

同样,当设置获得注意此行为commonChunkfalse在构建选项。此选项使您可以选择:

  • falseSharedModule直接将所需的部分捆绑到导入它的惰性模块中。优点:懒模块之间的平均加载时间。缺点:SharedModule懒模块之间重复了一些代码,整体应用程序大小更大
  • true(默认):有一个包含的部件的共同块SharedModule被用于哪个至少由两个懒惰模块(其余部分被捆绑到懒惰模块本身)。优点:没有重复的代码,总体上减小了应用程序的大小。缺点:第一个惰性模块的加载速度较慢(即使当前路由不需要它,它也会加载公共块)

结论是,Angular构建为SharedModulewith commonChunk设置为true或的优化false(取决于您的上下文),您实际上不必担心SharedModule大小。因此,您不必尝试像混合模式一样同时执行功能模块角色和共享模块角色的奇怪模式。