我们可以在 AOT 之后向 Angular 应用程序添加功能模块吗

Posted

技术标签:

【中文标题】我们可以在 AOT 之后向 Angular 应用程序添加功能模块吗【英文标题】:Can we add a feature module to an Angular app after AOT 【发布时间】:2018-02-25 15:26:19 【问题描述】:

我正在开发一个类似于 WordPress 和其他 CMS 应用程序的开源平台,但专注于与典型 Java 构建管道的互操作性。

目标是创建一些可重用的库,为开发人员提供构建/运行时依赖项,以创建可在平台部署后应用到平台的功能模块 [插件]。

我使用 AngularJS + Spring 框架创建了一个很好的原始版本。 本质上,它将扫描依赖 jar 以查找与特定模式匹配的静态文件,为文件创建 MVC 资源解析,然后将这些文件 url 包含到索引页面中。

这有效地允许资源库包含服务器和客户端资源以扩展运行平台。

*但是!一位同事说我的 font-end 已经过时了,我需要更新 Angular =P

因此,我开始在 Angular 4 中将 UI 重写为单独的资源依赖项,在发布为 jar 之前,可以在功能模块项目中使用它进行测试。 我真的很喜欢 Angular 4 [TS],因为它更像是开发我精通的服务器代码。

切入正题...如果功能模块提供客户端资源,我如何在运行时加载它们? 我想我可以使用 JIT 并在浏览器中加载 js 路径,但出于性能原因我想使用 AOT。

我正在考虑 - 解压缩资源,运行编译,然后提供页面。 或者有没有办法在 AOT 已经执行后动态加载 Angular 模块?

参考项目 - https://github.com/savantly-net/sprout-platform

【问题讨论】:

也许 Angular 文档会有所帮助? angular.io/guide/dynamic-component-loader 不幸的是,我不相信 AOT 可以做到这一点。有趣的是,如果您可以同时运行 AOT 和 JIT 组件。也许使用某种类型的代理 ngModule 和一个通用接口并将运行时组件加载到一个单独的文件中 没有应用程序不会知道任何有关已加载模块的信息。只链接到它。在你调用这个链接之后,你可以调用从服务器加载模块的函数,就像***.com/questions/42953858/… :) 我认为这比同时使用 AOT 和 JIT 更好。它给你更好的表现 为了更安全,您可以查看universal.angular.io,它为您提供服务器端渲染。但我不使用它:(这就是为什么我不知道设置和使用有多难 您可以在同一页面中拥有多个 AOT 编译的 Angular 应用程序。这对你有用吗? (但我个人认为最好在单独的应用程序包中预编译功能模块组合,然后页面中只有一个应用程序) 【参考方案1】:

我能够通过在我的主应用程序中引用生成的 NgModuleFactory 文件来加载外部插件,但仍然需要在主机应用程序中进行一些预编译配置。

经过数小时尝试不同的解决方案后,我确定最适合我的用例是将插件作为打字稿文件提供在应用程序目录外部的文件夹中,然后在准备好开始为应用程序提供服务时进行编译.

这是如何为我工作的一个例子 - https://github.com/savantly-net/sprout-platform/tree/development/web/sprout-web-ui

我使用一个简单的 ts 模块来导入/导出插件 - [此处使用相对路径,但也适用于绝对路径]https://github.com/savantly-net/sprout-platform/blob/development/web/sprout-web-ui/sprout.conf.ts

import  WikiModule  from './plugins/wiki/';

export const plugins = [
  WikiModule
]

然后使用扩展运算符重新导出模块 -https://github.com/savantly-net/sprout-platform/blob/development/web/sprout-web-ui/src/app/plugins/plugins.module.ts

import  NgModule  from '@angular/core';
import  CommonModule  from '@angular/common';
import  plugins  from '../../../sprout.conf';
import  MenuModule  from '@savantly/ngx-menu';
import  SecurityModule  from '@savantly/ngx-security';
import  SproutPluginModule  from '@savantly/ngx-sprout-plugin';
import  Observable  from 'rxjs/Observable';

const log = (msg: string, obj?: any) => 
  console.log('[PluginsModule] ' + msg);
  if (obj) 
    console.log(obj);
  



@NgModule(
  imports: [
    CommonModule,
    SproutPluginModule,
    MenuModule,
    SecurityModule,
    ...plugins
  ],
  exports: [...plugins],
  declarations: []
)
export class PluginsModule 
  private ngModules: NgModule[] = [];

  getNgModules(): Observable<NgModule[]> 
    return Observable.of(this.ngModules);
  

  constructor() 
   log('Loaded plugins');
  
  

这不是真正的即插即用解决方案,但是如果没有在 [预编译] 配置文件中明确引用插件文件夹,构建过程将无法执行 tree-shaking。

【讨论】:

以上是关于我们可以在 AOT 之后向 Angular 应用程序添加功能模块吗的主要内容,如果未能解决你的问题,请参考以下文章

Angular2 AOT 编译与静态外部 js 文件

在运行时为 AOT 编译的 Angular 应用程序获取 --locale 的值

angular4 aot throw require 未定义错误

AOT Build 上的 Kendo Angular2 输入组件损坏

在 AOT 中构建 Angular 模块时出现打字稿错误

使用 AOT 的 Angular 多入口点