angular - SystemJS 6.x set/register modules or provide mapping when dynamically loading module
问题描述
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?
解决方案
根据https://github.com/systemjs/systemjs/issues/2152#issuecomment-610470021中的评论,我有一个可行的解决方案
我正在使用 SystemJS 6.6.1。
重要的事情之一是您要加载 umd 模块。因此,您需要extras/amd.js
在 angular.json 文件中添加脚本:
"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
});
});
推荐阅读
- react-native - Net-info 发生错误在 React-Native 中不起作用
- sql - 如何检查sql server中是否存在多种日期格式?
- php - 如何在使用 Laravel 上传时从公用文件夹中删除旧图像
- mysql - 在 OnModelCreating 中更改 Hangfire 表名称
- c++ - 对象:无法为位于不同线程中的父级创建子级
- c++ - 为什么在hackerrank中的许多问题中都进行了拆分字符串?
- google-apps-script - 如何使用数组设置值并匹配长度
- python - 如何在 Python 循环中满足这些条件
- sql-server - T-SQL 在将新的自联接添加到现有查询时,是否有任何功能可以避免列名不明确
- excel - 使用bloomberg获取历史期权数据到excel