SystemJS 6.x set/register modules or provide mapping when dynamically loading module

五迷三道 提交于 2021-02-04 20:59:59

问题


I am trying to load modules dynamically with systemjs version 6.x in my Angular 8 application.

Given there current documentation it looks like I can either user the SystemJS API to register or set a module programatically.

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

Trying this, however it doesn't look like systemjs is finding @angular/core

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

Should I be using set? Or register for this? https://github.com/systemjs/systemjs/blob/master/docs/api.md#systemregisterdeps-declare

Looks like I can also provide an import map:

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

I tried adding that mapping in index.html without any luck

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

Is systemjs already included with my angular build when using Angular CLI in such a way that I can just inject the SystemJS that my angular application is already using in hopes that all mappings are already defined for all my dependencies?


回答1:


I have a working solution, based on the comments in https://github.com/systemjs/systemjs/issues/2152#issuecomment-610470021

I am using SystemJS 6.6.1.

One of the important things is that you want to load an umd module. Therefor you need to add the extras/amd.js script in your angular.json file:

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

So be sure to add these two scripts to your angular.json file and then you could use this code:

// 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;
  }

}

You do not need to create a script tag in your index.html. This is handled by the ModuleLoader.

Usage:

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
  });

});


来源:https://stackoverflow.com/questions/59634659/systemjs-6-x-set-register-modules-or-provide-mapping-when-dynamically-loading-mo

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!