angular - SystemJS 6.x 设置/注册模块或在动态加载模块时提供映射

标签 angular angular-cli angular8 systemjs

我正在尝试在我的 Angular 8 应用程序中使用 systemjs 版本 6.x 动态加载模块。

鉴于当前的文档,看起来我可以使用 SystemJS API 以编程方式注册或设置模块。

https://github.com/systemjs/systemjs/blob/master/docs/api.md#systemsetid-module---module

尝试这个,但看起来 systemjs 没有找到 @angular/core

import * as angularCore from '@angular/core';
System.set('@angular/core', angularCore);

我应该使用 set 吗?或者注册这个? https://github.com/systemjs/systemjs/blob/master/docs/api.md#systemregisterdeps-declare

看来我还可以提供导入 map :

https://github.com/systemjs/systemjs/blob/master/docs/import-maps.md

我尝试在index.html中添加该映射,但没有成功

<script type="systemjs-importmap">
{
  "imports": {
    "@angular/core": "node_modules/@angular/core/bundles/core.umd.js"
  }
}
</script>

在使用 Angular CLI 时,systemjs 是否已包含在我的 Angular 构建中,这样我就可以注入(inject)我的 Angular 应用程序已在使用的 SystemJS,以希望所有映射都已为我的所有依赖项定义?

最佳答案

我有一个可行的解决方案,基于 https://github.com/systemjs/systemjs/issues/2152#issuecomment-610470021 中的评论

我使用的是 SystemJS 6.6.1。

重要的事情之一是您想要加载 umd 模块。因此,您需要在 angular.json 文件中添加 extras/amd.js 脚本:

"scripts": [
  "node_modules/systemjs/dist/system.js",
  "node_modules/systemjs/dist/extras/amd.js"
]

因此请务必将这两个脚本添加到您的 angular.json 文件中,然后您就可以使用以下代码:

// tslint:disable-next-line:variable-name
const SystemJS = (window as any).System;

export class ModuleLoader {
  // based on https://github.com/systemjs/systemjs/issues/2152#issuecomment-610470021

  /**
   * Call this BEFORE calling load(url)
   */
  register(modules: { [name: string]: object }): Promise<this> {
    const imports: { [name: string]: string } = {};
    Object.keys(modules).forEach(key => {
      imports[key] = './lib/' + key;
    });
    const script = document.createElement('script');
    script.type = 'systemjs-importmap';
    script.textContent = JSON.stringify({imports}, null, 3);
    document.head.appendChild(script);
    return SystemJS.prepareImport().then(() => {
      const baseUrl = this.getBaseUrl();
      Object.keys(modules).forEach(key => {
        SystemJS.set(baseUrl + 'lib/' + key, modules[key]);
      });
      return this;
    });
  }

  load(url: string): Promise<any> {
    return SystemJS.import(url);
  }

  private getBaseUrl(): string {
    let baseUrl;
    const baseEl = document.querySelector('base[href]');
    if (baseEl) {
      baseUrl = (baseEl as any).href;
    }

    if (!baseUrl && typeof location !== 'undefined') {
      baseUrl = location.href.split('#')[0].split('?')[0];
      const lastSepIndex = baseUrl.lastIndexOf('/');
      if (lastSepIndex !== -1) {
        baseUrl = baseUrl.slice(0, lastSepIndex + 1);
      }
    }
    return baseUrl;
  }

}

您不需要在index.html 中创建脚本标记。这是由 ModuleLoader 处理的。

用法:

const libPath = 'https://path/to/angular/umd/library';

const loader = new ModuleLoader();

loader.register({
  '@angular/core': angularCore,
  '@angular/common': angularCommon,
  '@angular/common/http': angularCommonHttp,
  '@angular/forms': angularForms,
  '@angular/animations': angularAnimations,
  '@angular/platform-browser': angularPlatformBrowser,
  '@angular/platform-browser-dynamic': angularPlatformBrowserDynamic
}).then(() => {

  loader.load(libPath).then(async lib => {
    if (lib.default) {
      lib = lib.default;
    }
    ... do your stuff with the module
  });

});

关于angular - SystemJS 6.x 设置/注册模块或在动态加载模块时提供映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59634659/

相关文章:

angular - Angular 中的原理图是什么?

angular - 作业名称 "..getProjectMetadata"不存在

javascript - 获取子组件中 ngModel 的值

angular - WebStorm (v2.3.1) : Live reload after file change (html) does not work. SyntaxError: Unexpected token < in JSON at position 0

javascript - Angular 5 和转换仅在 'new' 项中

Angular CLI : "Unexpected token import" while test execution using karma

angular - 如何降级 Angular CLI 版本?

css - 如何将字体文件从 css 文件加载到 Angular 元素中

angular - 如何将 NgRx 8 操作与 NgRx 7 reducer 一起使用

javascript - 当值相同时,Angular @Input() 值不会改变