5

我正在尝试将外部模块(托管在 git/npm 存储库中)作为延迟加载模块包含在我的 Angular 应用程序中。

我正在使用 ngc 编译器编译我的外部模块:

node_modules/.bin/ngc -p tsconfig-aot.json

这是我的编译器配置的样子:

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "baseUrl": "src",
    "declaration": true,
    "outDir": "./release/src"
  },
  "files": [
    "./src/index.ts"
  ],
  "angularCompilerOptions": {
    "genDir": "release",
    "skipTemplateCodegen": true,
    "entryModule": "index#ExternalModule",
    "skipMetadataEmit": false,
    "strictMetadataEmit": true
  }
}

在我的主应用程序中,我正在延迟加载给定的模块:

RouterModule.forRoot([
      { path: '', component: HomeComponent, pathMatch: 'full'},
      { path: 'lazy', loadChildren: './lazy/lazy.module#LazyModule'},
      { path: 'external', loadChildren: '@angular-universal-serverless/external-module/release#ExternalModule'}
])

出于编译目的,我使用 @ngtools/webpack 插件。

JIT 编译没有任何问题,但是 AOT 编译给了我错误:

ERROR in ./src/ngfactory lazy
Module not found: Error: Can't resolve '/path/to/my/project/angular-universal-serverless/src/ngfactory/node_modules/@angular-universal-serverless/external-module/release/src/index.js' in '/Users/mtreder/Documents/private/work/angular-universal-serverless/src/ngfactory'
 @ ./src/ngfactory lazy
 @ ./~/@angular/core/@angular/core.es5.js
 @ ./src/main.server.aot.ts

所以我决定检查ngc编译器的输出是什么(由 webpack 插件在后台调用):

node_modules/.bin/ngc -p tsconfig.server.aot.json

实际上,/path/to/my/project/angular-universal-serverless/src/ngfactory/node_modules目录中缺少我的模块。

ls src/ngfactory/node_modules/
@angular        @nguniversal        @types          idb         ng-http-sw-proxy    rxjs            typescript-collections

如何强制 ngc 将给定模块放在ngfactory输出目录中?

我的主要应用程序可以在这里找到:https ://github.com/maciejtreder/angular-universal-serverless/tree/externalModule

和这里的外部模块:https ://github.com/maciejtreder/angular-external-module

4

2 回答 2

5

1)这里的第一个问题是 AOT 编译器不编译你的模块(node_modules文件夹默认不包括在内),所以你必须将它包含在files你的 ts 配置选项中:

tsconfig.browser.json

tsconfig.server.json

tsconfig.server.aot.json

"files": [
  "./node_modules/@angular-universal-serverless/external-module/release/src/externalComponent/external.module.d.ts"
],
"include": [
  "./src/main.browser.ts",
  "./src/app/lazy/lazy.module.ts",
  "./src/app/httpProxy/http-proxy.module.ts"
]

我们不能将它添加到includes数组中,因为打字稿会排除它

使用“include”包含的文件可以使用“exclude”属性过滤

在文档中查看更多详细信息

2)然后 \node_modules\@angular-universal-serverless\external-module\release\package.json应该有typings如下字段:

"name": "@angular-universal-serverless/external-module",
"main": "./src/index.js",
"typings": "./src/externalComponent/external.module.d.ts", <=== this one

我们必须使用external.module.d.ts,因为 Angular 不会为@ngtools/webpack 插件为 ContextElementDependency 创建映射时创建ngfactory文件:index.d.ts

const factoryPath = lazyRoute.replace(/(\.d)?\.ts$/, '.ngfactory.ts');
// where lazyRoute === .../external-module/release/src/externalComponent/external.module.d.ts
const lr = path.relative(this.basePath, factoryPath);
this._lazyRoutes[k + '.ngfactory'] = path.join(this.genDir, lr);

如果您不想更改,请package.json更改loadChildren字段:

{ 
  path: 'external', 
  loadChildren: '@angular-universal-serverless/external-module/release/src/externalComponent/external.module#ExternalModule'
}

在此处输入图像描述

于 2017-10-16T21:05:07.897 回答
0

也许为时已晚,但我希望这可以帮助某人。

我写了一个非常简单的节点脚本来运行npm install。它确实是一个安装后脚本。它将源文件复制node_modules到主项目下的文件夹中。然后它会更新对主路由文件中延迟加载模块的引用。

它对我的团队非常有效,我们大大提高了应用程序的性能。

脚本很短,有据可查,请查看

https://gist.github.com/insanediv/8b4ebba06824a3eb8233e10287a1cdcd

于 2019-11-03T15:13:32.873 回答