PlatformRef.bootstrapModule(...) 抛出一个错误 "No ResourceLoader implementation has been provided."
PlatformRef.bootstrapModule(...) throws an error that says "No ResourceLoader implementation has been provided."
我正在尝试创建一个 NgModuleRef<AppModule>
以便将我的一些组件呈现为非 html 格式。
我能够创建一个 PlatformRef
对象,但是当我在这个对象上调用 bootstrapModule(AppModule)
时我得到一个错误:
"Error: No ResourceLoader implementation has been provided. Can't read the url "app.component.html""
可能,我应该在不同于 extraProviders
的地方添加 ResourceLoader
的 DI 注册,但我不知道具体在哪里...
代码:
import { ResourceLoader } from '@angular/compiler';
import { Compiler, CompilerFactory, Injectable, StaticProvider, Type } from '@angular/core';
import { platformDynamicServer } from '@angular/platform-server';
import { AppComponent } from './app/app.component';
import { AppModule } from './app/app.module';
export function createCompiler(compilerFactory: CompilerFactory) {
return compilerFactory.createCompiler();
}
async function generate<M>(moduleType: Type<M>) {
try {
const extraProviders: StaticProvider[] = [
{ provide: ResourceLoader, useClass: ResourceLoaderImpl, deps: [] },
{ provide: Compiler, useFactory: createCompiler, deps: [CompilerFactory] },
];
const platformRef = platformDynamicServer(extraProviders);
const moduleRef = await platformRef.bootstrapModule(moduleType); // <<< BREAKS HERE
const appComponent = moduleRef.injector.get(AppComponent);
console.info(appComponent.title.toString());
} catch (error) {
throw new Error(error.toString());
}
}
generate(AppModule)
.then(message => console.info({ message }))
.catch(error => console.error({ error }));
将ResourceLoaderImpl
class代码复制到@angular/platform-browser-dynamic
(src\resource_loader\resource_loader_impl.ts
)的信中:
@Injectable()
export class ResourceLoaderImpl extends ResourceLoader {
get(url: string): Promise<string> {
let resolve: (result: any) => void;
let reject: (error: any) => void;
const promise = new Promise<string>((res, rej) => {
resolve = res;
reject = rej;
});
const xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'text';
xhr.onload = function() {
// responseText is the old-school way of retrieving response (supported by IE8 & 9)
// response/responseType properties were introduced in ResourceLoader Level2 spec (supported
// by IE10)
const response = xhr.response || xhr.responseText;
// normalize IE9 bug (http://bugs.jquery.com/ticket/1450)
let status = xhr.status === 1223 ? 204 : xhr.status;
// fix status code when it is 0 (0 status is undocumented).
// Occurs when accessing file resources or on Android 4.1 stock browser
// while retrieving files from application cache.
if (status === 0) {
status = response ? 200 : 0;
}
if (200 <= status && status <= 300) {
resolve(response);
} else {
reject(`Failed to load ${url}`);
}
};
xhr.onerror = function() { reject(`Failed to load ${url}`); };
xhr.send();
return promise;
}
}
ResourceLoader
是 CompilerOptions 的一部分,因此您应该提供它们。
它可以通过 platformRef.bootstrapModule 作为第二个 CompilerOptions
参数来完成:
platformRef.bootstrapModule(moduleType, {
providers: [
{
provide: ResourceLoader,
useClass: ResourceLoaderImpl, deps: []
}
]
});
或者您可以尝试提供 COMPILER_OPTIONS
令牌作为多提供商(这里是来自源代码的 an example):
const extraProviders: StaticProvider[] = [
{
provide: COMPILER_OPTIONS,
useValue: {providers: [{provide: ResourceLoader, useClass: ResourceLoaderImpl, deps: []}]},
multi: true
},
{ provide: Compiler, useFactory: createCompiler, deps: [CompilerFactory] },
];
我正在尝试创建一个 NgModuleRef<AppModule>
以便将我的一些组件呈现为非 html 格式。
我能够创建一个 PlatformRef
对象,但是当我在这个对象上调用 bootstrapModule(AppModule)
时我得到一个错误:
"Error: No ResourceLoader implementation has been provided. Can't read the url "app.component.html""
可能,我应该在不同于 extraProviders
的地方添加 ResourceLoader
的 DI 注册,但我不知道具体在哪里...
代码:
import { ResourceLoader } from '@angular/compiler';
import { Compiler, CompilerFactory, Injectable, StaticProvider, Type } from '@angular/core';
import { platformDynamicServer } from '@angular/platform-server';
import { AppComponent } from './app/app.component';
import { AppModule } from './app/app.module';
export function createCompiler(compilerFactory: CompilerFactory) {
return compilerFactory.createCompiler();
}
async function generate<M>(moduleType: Type<M>) {
try {
const extraProviders: StaticProvider[] = [
{ provide: ResourceLoader, useClass: ResourceLoaderImpl, deps: [] },
{ provide: Compiler, useFactory: createCompiler, deps: [CompilerFactory] },
];
const platformRef = platformDynamicServer(extraProviders);
const moduleRef = await platformRef.bootstrapModule(moduleType); // <<< BREAKS HERE
const appComponent = moduleRef.injector.get(AppComponent);
console.info(appComponent.title.toString());
} catch (error) {
throw new Error(error.toString());
}
}
generate(AppModule)
.then(message => console.info({ message }))
.catch(error => console.error({ error }));
将ResourceLoaderImpl
class代码复制到@angular/platform-browser-dynamic
(src\resource_loader\resource_loader_impl.ts
)的信中:
@Injectable()
export class ResourceLoaderImpl extends ResourceLoader {
get(url: string): Promise<string> {
let resolve: (result: any) => void;
let reject: (error: any) => void;
const promise = new Promise<string>((res, rej) => {
resolve = res;
reject = rej;
});
const xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'text';
xhr.onload = function() {
// responseText is the old-school way of retrieving response (supported by IE8 & 9)
// response/responseType properties were introduced in ResourceLoader Level2 spec (supported
// by IE10)
const response = xhr.response || xhr.responseText;
// normalize IE9 bug (http://bugs.jquery.com/ticket/1450)
let status = xhr.status === 1223 ? 204 : xhr.status;
// fix status code when it is 0 (0 status is undocumented).
// Occurs when accessing file resources or on Android 4.1 stock browser
// while retrieving files from application cache.
if (status === 0) {
status = response ? 200 : 0;
}
if (200 <= status && status <= 300) {
resolve(response);
} else {
reject(`Failed to load ${url}`);
}
};
xhr.onerror = function() { reject(`Failed to load ${url}`); };
xhr.send();
return promise;
}
}
ResourceLoader
是 CompilerOptions 的一部分,因此您应该提供它们。
它可以通过 platformRef.bootstrapModule 作为第二个 CompilerOptions
参数来完成:
platformRef.bootstrapModule(moduleType, {
providers: [
{
provide: ResourceLoader,
useClass: ResourceLoaderImpl, deps: []
}
]
});
或者您可以尝试提供 COMPILER_OPTIONS
令牌作为多提供商(这里是来自源代码的 an example):
const extraProviders: StaticProvider[] = [
{
provide: COMPILER_OPTIONS,
useValue: {providers: [{provide: ResourceLoader, useClass: ResourceLoaderImpl, deps: []}]},
multi: true
},
{ provide: Compiler, useFactory: createCompiler, deps: [CompilerFactory] },
];