R3InjectorError(AppServerModule) 没有提供 InjectionToken compilerOptions
R3InjectorError(AppServerModule) No provider for InjectionToken compilerOptions
我收到以下错误:
render error Error [NullInjectorError]: R3InjectorError(AppServerModule)[RouterModule -> Router -> NgModuleFactoryLoader -> Compiler -> InjectionToken compilerOptions -> InjectionToken compilerOptions -> InjectionToken compilerOptions]:
NullInjectorError: No provider for InjectionToken compilerOptions!
我按照 https://angular.io/guide/universal 提供的说明进行操作,但似乎我需要添加的调整很少,例如使用 domino
来模拟 document
对象来工作。让我很难找出问题出在哪里的问题之一是 main.js
中指出了错误
render error Error [NullInjectorError]: R3InjectorError(AppServerModule)[RouterModule -> Router -> NgModuleFactoryLoader -> Compiler -> InjectionToken compilerOptions -> InjectionToken compilerOptions -> InjectionToken compilerOptions]:
NullInjectorError: No provider for InjectionToken compilerOptions!
at ɵɵinject (<project-dir>\dist\apps\ui\server\main.js:219196:57)
at injectArgs (<project-dir>\dist\apps\ui\server\main.js:219291:23)
at Object.factory (<project-dir>\dist\apps\ui\server\main.js:229671:52)
at R3Injector.hydrate (<project-dir>\dist\apps\ui\server\main.js:229582:35)
at R3Injector.get (<project-dir>\dist\apps\ui\server\main.js:229404:33) {
ngTempTokenPath: null,
ngTokenPath: [
'RouterModule',
'Router',
'NgModuleFactoryLoader',
'Compiler',
'InjectionToken compilerOptions',
'InjectionToken compilerOptions',
'InjectionToken compilerOptions'
]
} undefined
我无法让 ng run dev:ssr
改为显示打字稿。
这是条目 server.ts
:
import { ngExpressEngine } from '@nguniversal/express-engine';
import 'zone.js/dist/zone-node';
// import * as express from 'express';
const express = require('express');
import { APP_BASE_HREF } from '@angular/common';
import { Express, Request, Response } from 'express';
import { existsSync } from 'fs';
import { join } from 'path';
import { uiTransports } from 'src/server/transports/transports.winston';
import * as winston from 'winston';
const domino = require('domino');
const fs = require('fs');
import 'localstorage-polyfill';
const winstonLogger = winston.createLogger({
transports: uiTransports,
});
winstonLogger.info('Starting up UI Server');
// Simulate browser
const distFolder = join(process.cwd(), `dist/apps/ui/browser`);
winstonLogger.info(`Browser dist folder is located at ${distFolder}`);
const templateA = fs.readFileSync(join(distFolder, 'index.html')).toString();
const win = domino.createWindow(templateA);
win.Object = Object;
win.Math = Math;
// (global as any).console = winstonLogger;
(global as any).window = win;
(global as any).document = win.document;
(global as any).branch = null;
(global as any).object = win.object;
(global as any).HTMLElement = win.HTMLElement;
(global as any).navigator = win.navigator;
(global as any).localStorage = localStorage;
(global as any).sessionStorage = localStorage;
(global as any).getComputedStyle = () => {
return {
getPropertyValue() {
return '';
},
};
};
// Browser simulation end
import { AppServerModule } from './src/main.server';
// The Express app is exported so that it can be used by serverless Functions.
export function app(): Express {
const server: Express = express();
const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index';
winstonLogger.info(`Index HTML located at ${indexHtml}`);
// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
server.engine(
'html',
ngExpressEngine({
bootstrap: AppServerModule,
}),
);
server.set('view engine', 'html');
server.set('views', distFolder);
winstonLogger.info('Engine setup completed');
// Example Express Rest API endpoints
// server.get('/api/**', (req, res) => { });
// Serve static files from /browser
server.get(
'*.*',
express.static(distFolder, {
maxAge: '1y',
}),
);
// All regular routes use the Universal engine
server.get('*', (req: Request, res: Response) => {
try {
winstonLogger.info(`Rendering for request ${req.url} started`);
res.render(
indexHtml,
// templateA,
{
req,
res,
// url: req.url,
// cookies: req.cookies,
// bootstrap: AppServerModule,
providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }],
},
(err: Error, html: string) => {
console.error('render error', err, html);
res.status(html ? 200 : 500).send(html || err.message);
},
);
winstonLogger.info(`Rendering for request ${req.url} completed`);
} catch (ex) {
winstonLogger.error('error from server', ex);
}
});
return server;
}
function run(): void {
const port = process.env.PORT || 4000;
// Start up the Node server
const server = app();
winstonLogger.info(`Server is about to start to listen to port ${port}`);
server.listen(port, () => {
winstonLogger.info(`Node Express server listening on http://localhost:${port}`);
});
}
// Webpack will replace 'require' with '__webpack_require__'
// '__non_webpack_require__' is a proxy to Node 'require'
// The below code is to ensure that the server is run only when not requiring the bundle.
declare const __non_webpack_require__: NodeRequire;
const mainModule = __non_webpack_require__.main;
const moduleFilename = (mainModule && mainModule.filename) || '';
if (moduleFilename === __filename || moduleFilename.includes('iisnode')) {
run();
}
export * from './src/main.server';
这里是app.server.module.ts
import { NgModule } from '@angular/core';
import { ServerModule } from '@angular/platform-server';
import { IonicServerModule } from '@ionic/angular-server'; // i added this thinking it might help
import { AppComponent } from './app.component';
import { AppModule } from './app.module';
@NgModule({
imports: [AppModule, ServerModule, IonicServerModule],
bootstrap: [AppComponent],
})
export class AppServerModule {}
如有任何建议,我们将不胜感激!
编辑:
原来错误来自下面的deps: [[Optional(), COMPILER_OPTIONS]],
:
@NgModule({
declarations: [DynamicComponentDirective],
exports: [DynamicComponentDirective],
})
export class DynamicComponentModule {
static forRoot(metadata: NgModule): ModuleWithProviders<DynamicComponentModule> {
console.log('compiler options');
return {
ngModule: DynamicComponentModule,
providers: [
{
provide: Compiler,
useFactory: createJitCompiler,
/**
* This leads to the following error:
* R3InjectorError(AppServerModule)[RouterModule -> Router -> NgModuleFactoryLoader -> Compiler -> InjectionToken compilerOptions -> InjectionToken compilerOptions -> InjectionToken compilerOptions]: NullInjectorError: No provider for InjectionToken compilerOptions!
*/
// deps: [[Optional(), COMPILER_OPTIONS]],
},
{
provide: DynamicComponentOptions,
useValue: {
ngModuleMetadata: metadata,
},
},
],
};
}
}
我假设我需要将它注入 AppServerModule
@NgModule({
imports: [
...
],
bootstrap: [...],
providers: [/* I think i need to add a provider for it here */],
})
export class AppServerModule {}
不知道怎么做,有人可以帮忙吗?
事实证明这是 SSR 的 angular.json
配置问题,按照与 https://github.com/Angular-RU/universal-starter/blob/master/angular.json 相同的配置解决了问题。
我收到以下错误:
render error Error [NullInjectorError]: R3InjectorError(AppServerModule)[RouterModule -> Router -> NgModuleFactoryLoader -> Compiler -> InjectionToken compilerOptions -> InjectionToken compilerOptions -> InjectionToken compilerOptions]:
NullInjectorError: No provider for InjectionToken compilerOptions!
我按照 https://angular.io/guide/universal 提供的说明进行操作,但似乎我需要添加的调整很少,例如使用 domino
来模拟 document
对象来工作。让我很难找出问题出在哪里的问题之一是 main.js
render error Error [NullInjectorError]: R3InjectorError(AppServerModule)[RouterModule -> Router -> NgModuleFactoryLoader -> Compiler -> InjectionToken compilerOptions -> InjectionToken compilerOptions -> InjectionToken compilerOptions]:
NullInjectorError: No provider for InjectionToken compilerOptions!
at ɵɵinject (<project-dir>\dist\apps\ui\server\main.js:219196:57)
at injectArgs (<project-dir>\dist\apps\ui\server\main.js:219291:23)
at Object.factory (<project-dir>\dist\apps\ui\server\main.js:229671:52)
at R3Injector.hydrate (<project-dir>\dist\apps\ui\server\main.js:229582:35)
at R3Injector.get (<project-dir>\dist\apps\ui\server\main.js:229404:33) {
ngTempTokenPath: null,
ngTokenPath: [
'RouterModule',
'Router',
'NgModuleFactoryLoader',
'Compiler',
'InjectionToken compilerOptions',
'InjectionToken compilerOptions',
'InjectionToken compilerOptions'
]
} undefined
我无法让 ng run dev:ssr
改为显示打字稿。
这是条目 server.ts
:
import { ngExpressEngine } from '@nguniversal/express-engine';
import 'zone.js/dist/zone-node';
// import * as express from 'express';
const express = require('express');
import { APP_BASE_HREF } from '@angular/common';
import { Express, Request, Response } from 'express';
import { existsSync } from 'fs';
import { join } from 'path';
import { uiTransports } from 'src/server/transports/transports.winston';
import * as winston from 'winston';
const domino = require('domino');
const fs = require('fs');
import 'localstorage-polyfill';
const winstonLogger = winston.createLogger({
transports: uiTransports,
});
winstonLogger.info('Starting up UI Server');
// Simulate browser
const distFolder = join(process.cwd(), `dist/apps/ui/browser`);
winstonLogger.info(`Browser dist folder is located at ${distFolder}`);
const templateA = fs.readFileSync(join(distFolder, 'index.html')).toString();
const win = domino.createWindow(templateA);
win.Object = Object;
win.Math = Math;
// (global as any).console = winstonLogger;
(global as any).window = win;
(global as any).document = win.document;
(global as any).branch = null;
(global as any).object = win.object;
(global as any).HTMLElement = win.HTMLElement;
(global as any).navigator = win.navigator;
(global as any).localStorage = localStorage;
(global as any).sessionStorage = localStorage;
(global as any).getComputedStyle = () => {
return {
getPropertyValue() {
return '';
},
};
};
// Browser simulation end
import { AppServerModule } from './src/main.server';
// The Express app is exported so that it can be used by serverless Functions.
export function app(): Express {
const server: Express = express();
const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index';
winstonLogger.info(`Index HTML located at ${indexHtml}`);
// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
server.engine(
'html',
ngExpressEngine({
bootstrap: AppServerModule,
}),
);
server.set('view engine', 'html');
server.set('views', distFolder);
winstonLogger.info('Engine setup completed');
// Example Express Rest API endpoints
// server.get('/api/**', (req, res) => { });
// Serve static files from /browser
server.get(
'*.*',
express.static(distFolder, {
maxAge: '1y',
}),
);
// All regular routes use the Universal engine
server.get('*', (req: Request, res: Response) => {
try {
winstonLogger.info(`Rendering for request ${req.url} started`);
res.render(
indexHtml,
// templateA,
{
req,
res,
// url: req.url,
// cookies: req.cookies,
// bootstrap: AppServerModule,
providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }],
},
(err: Error, html: string) => {
console.error('render error', err, html);
res.status(html ? 200 : 500).send(html || err.message);
},
);
winstonLogger.info(`Rendering for request ${req.url} completed`);
} catch (ex) {
winstonLogger.error('error from server', ex);
}
});
return server;
}
function run(): void {
const port = process.env.PORT || 4000;
// Start up the Node server
const server = app();
winstonLogger.info(`Server is about to start to listen to port ${port}`);
server.listen(port, () => {
winstonLogger.info(`Node Express server listening on http://localhost:${port}`);
});
}
// Webpack will replace 'require' with '__webpack_require__'
// '__non_webpack_require__' is a proxy to Node 'require'
// The below code is to ensure that the server is run only when not requiring the bundle.
declare const __non_webpack_require__: NodeRequire;
const mainModule = __non_webpack_require__.main;
const moduleFilename = (mainModule && mainModule.filename) || '';
if (moduleFilename === __filename || moduleFilename.includes('iisnode')) {
run();
}
export * from './src/main.server';
这里是app.server.module.ts
import { NgModule } from '@angular/core';
import { ServerModule } from '@angular/platform-server';
import { IonicServerModule } from '@ionic/angular-server'; // i added this thinking it might help
import { AppComponent } from './app.component';
import { AppModule } from './app.module';
@NgModule({
imports: [AppModule, ServerModule, IonicServerModule],
bootstrap: [AppComponent],
})
export class AppServerModule {}
如有任何建议,我们将不胜感激!
编辑:
原来错误来自下面的deps: [[Optional(), COMPILER_OPTIONS]],
:
@NgModule({
declarations: [DynamicComponentDirective],
exports: [DynamicComponentDirective],
})
export class DynamicComponentModule {
static forRoot(metadata: NgModule): ModuleWithProviders<DynamicComponentModule> {
console.log('compiler options');
return {
ngModule: DynamicComponentModule,
providers: [
{
provide: Compiler,
useFactory: createJitCompiler,
/**
* This leads to the following error:
* R3InjectorError(AppServerModule)[RouterModule -> Router -> NgModuleFactoryLoader -> Compiler -> InjectionToken compilerOptions -> InjectionToken compilerOptions -> InjectionToken compilerOptions]: NullInjectorError: No provider for InjectionToken compilerOptions!
*/
// deps: [[Optional(), COMPILER_OPTIONS]],
},
{
provide: DynamicComponentOptions,
useValue: {
ngModuleMetadata: metadata,
},
},
],
};
}
}
我假设我需要将它注入 AppServerModule
@NgModule({
imports: [
...
],
bootstrap: [...],
providers: [/* I think i need to add a provider for it here */],
})
export class AppServerModule {}
不知道怎么做,有人可以帮忙吗?
事实证明这是 SSR 的 angular.json
配置问题,按照与 https://github.com/Angular-RU/universal-starter/blob/master/angular.json 相同的配置解决了问题。