具有AOT和Rollup的Angular 2子模块路由

时间:2017-04-28 07:27:05

标签: angular2-routing angular2-aot rollupjs

在Angular 2中配置子模块的正确方法是什么,以便它能在AOT和汇总之后工作?我不关心延迟加载,并且很乐意将所有子模块捆绑在一起,但是loadChildren是引用子模块并使用正确的<router-outlet>的最干净的方法,尽管我尝试了各种方法,没有一种方法可以用于开发和生产。

我按照AOT cookbook中的说明准备我的应用以进行部署。我的模块结构是root&gt;帐户&gt; admin,我希望管理员路由加载到帐户组件定义的出口。

以下是帐户模块的路由器配置:

import { NgModule } from '@angular/core';
import { AdminModule }   from './admin/admin.module';

const accountRoutes: Routes = [{
    path: 'account',
    component: AccountComponent,
    children: [
        { path: 'setup', component: SetupComponent },
        { path: 'admin', loadChildren: () => AdminModule }
    ]
}];

这在开发中有效,但NGC编译失败了Error: Error encountered resolving symbol values statically. Reference to a local (non-exported) symbol 'accountRoutes'.

我添加了导出到accountRoutes,但这也无法使用Error: Error encountered resolving symbol values statically. Function calls are not supported.进行编译。

一个建议是使用字符串而不是函数,以便NGC可以编译代码:

loadChildren: 'app/account/admin/admin.module#AdminModule'

这在开发中有效并且编译成功,但编译的应用程序将无法运行,因为SystemJS不可用。错误是:

ERROR Error: Uncaught (in promise): TypeError: System.import is not a function
TypeError: System.import is not a function
at t.loadFactory (build.js:6)
at t.load (build.js:6)
at t.loadModuleFactory (build.js:12)

我尝试在生产版本中包含SystemJS,但它无法找到单独的模块文件app/account/admin/admin.module.ngfactory - 汇总后所有内容都在一个build.js中。可能有一种方法可以使用单独的汇总来构建每个子模块,但这需要做很多工作。

我找到了引用导出函数的建议:

export function loadAdminModule() {
    return AdminModule;
}

loadChildren: loadAdminModule

这在开发中有效,但在生产中,运行时编译器不可用,因此它会记录build.js:1 ERROR Error: Uncaught (in promise): Error: Runtime compiler is not loaded

可以修改辅助函数,使其在生产中通过引用NgFactory来工作,但这在开发中不起作用。

import { AdminModuleNgFactory }   from '../../../aot/src/app/account/admin/admin.module.ngfactory';

export function loadAdminModule() {
    return AdminModuleNgFactory;
}

loadChildren: loadAdminModule

是否有支持使用loadChildren的方式,以便它可以使用AOT食谱中的说明?是否更好地使用webpack?

2 个答案:

答案 0 :(得分:2)

对于有同样问题的人,这里是我正在使用的临时解决方法。希望很快会有更好的答案。

我现在在专用文件submodules.ts中定义我的子模块。我有两个版本的此文件,submodules-jit.ts用于开发,submodules-aot.ts用于AOT /汇总部署到生产。我gitignore submodules.ts并在我的npm startnpm build:aot脚本中添加了命令,替换为正确的脚本。

// submodules-jit.ts
import { AdminModule } from './account/admin/admin.module'
export function adminModule(): any { return AdminModule; }

// submodules-aot.ts
import { AdminModuleNgFactory } from '../../aot/src/app/account/admin/admin.module.ngfactory'
import { AdminModule } from './account/admin/admin.module'
export function adminModule(): any { return AdminModuleNgFactory; }
export function adminModuleKeep(): any { return AdminModule; }

必须在AOT文件中引用AdminModule才能保留它。

然后我在我的路线中使用adminModule功能:

import { adminModule } from '../submodules'
{ path: 'admin', loadChildren: adminModule }

最后为方便起见,npm脚本会放入正确的文件中。

"build:aot": "cp src/submodules-aot.ts src/app/submodules.ts && ngc -p tsconfig-aot.json && rollup -c rollup-config.js",
"start": "cp src/submodules-jit.ts src/app/submodules.ts && concurrently \"npm run build:watch\" \"npm run serve\""

毋庸置疑,这是一个可怕的黑客攻击,但它保留了路由文件的清洁和大部分的邪恶在一个地方。

答案 1 :(得分:0)

在我的情况下,我解决了从外部模块加载路线的提示,然后阅读this issue on angular/cli issue page

所以,我出来重构我的路线:

import { TestModule } from './pathToModule/test.module';

export function exportTestModule() {
    return TestModule;
}

. . .

{
    path: 'test',
    loadChildren: exportTestModule
}

要:

. . .
{
    path: 'test',
    loadChildren: './pathToModule#TestModule'
}