我正在尝试从远程CDN URL加载角度包。使用-prod标志,使用角度CLI编译角度资产。
ng build -prod
以下内容来自主机应用程序(http://localhost:4200
)中的system-config文件。
{
map: {'sharedcomponent':'http://mycdn.com/shared-component'}
packages: {
"http://mycdn.com/shared-component": {
"main": "main.js",
"meta": {
"*": {
"format": "system",
"scriptLoad": true
}
}
}
}
主机应用程序稍后导入该组件会返回一个空对象。
System.import('sharedcomponent')
.then(function(comp){
console.log(comp); //outputs {}
});
在控制台中检查SystemJS.defined
时,我可以看到在“localhost:4200”域而不是CDN域下加载的所有捆绑模块。
但是,如果我部署非捆绑版本,则每件事都会正确加载。
任何人都可以提供任何见解吗?这是一个带有systemjs还是角度CLI的问题?
答案 0 :(得分:0)
通过SystemJS代码调试后,我能够确定问题所在。
调用System.register时,模块名称将使用System.decanonicalize方法解析为绝对URL。该方法使用基本url对象而不是加载bundle的包的URL。
修复是将名称解析推迟到您可以访问loader.address属性的reduce步骤。
幸运的是,您可以利用钩子进行必要的更改。
加载systemjs后,我重写System.register函数,使其不会对名称进行decanonical化。
System.register = function(name, deps, declare) {
if (typeof name != 'string') {
declare = deps; deps = name; name = null;
}
if (typeof declare == 'boolean')
return this.registerDynamic.apply(this, arguments);
this.pushRegister_({
amd: false,
entry: {
name: name,
deps: deps,
declare: declare,
declarative: true,
executingRequire: false,
esmExports: false,
evaluated: false,
originalIndices: null,
execute: null,
normalizedDeps: null,
groupIndex: null,
module: null,
esModule: null
}
});
};
然后我覆盖reduceRegister_函数以查找元数据标志,以确定是否应该使用decanonicalize方法来解析模块名称。
如果设置为false,我只需使用load.address与基本URL对象解析名称。
System.reduceRegister_ = function(load, register){
if (register) {
let entry = register && register.entry;
entry.name = (load.metadata && load.metadata.decanonicalize === false) ?
new URL(entry.name, load.address).href.replace(/%05/g, '#') :
this.decanonicalize(entry.name, load.address);
}
this.__proto__.reduceRegister_.call(this, load, register);
}
包配置在这里:
{
map: {'sharedcomponent':'http://mycdn.com/shared-component'}
packages: {
"http://mycdn.com/shared-component": {
"main": "main.js",
"meta": {
"*": {
"format": "system",
"scriptLoad": true,
"decanonicalize":false
}
}
}