这个错误通常是由于Node.js环境中缺少对客户端事件API(例如window和document)的支持而引起的。 在Angular应用程序中使用的大多数常规事件(如click和mouseover)在服务器上不起作用,因此需要手动创建它们的替代品。
以下是解决此问题的代码示例:
在app.server.module.ts中导入以下代码:
import 'zone.js/dist/zone-node';
import { ngExpressEngine } from '@nguniversal/express-engine';
import * as express from 'express';
import { join } from 'path';
import { AppServerModule } from './app/app.server.module';
import { APP_BASE_HREF } from '@angular/common';
import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader';
export function createApiRequestOptions(req: express.Request) {
return {
headers: {
Cookie: req.header('Cookie')
}
};
}
export function serverFactory(): express.Express {
const server = express();
const distFolder = join(process.cwd(), 'dist/browser');
const indexHtml = existsSync(join(distFolder, 'index.html')) ? 'index.html' : 'index';
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./dist/server/main');
server.engine('html', ngExpressEngine({
bootstrap: AppServerModuleNgFactory,
providers: [
provideModuleMap(LAZY_MODULE_MAP),
{ provide: APP_BASE_HREF, useValue: '/' },
{ provide: 'REQUEST', useFactory: (req: any) => ({ ...req, apiRequestOptions: createApiRequestOptions(req) }), deps: [express.Request] },
]
}));
server.set('view engine', 'html');
server.set('views', distFolder);
server.get('/api/*', (req, res) => {
const http = require('http');
const url = require('url');
const options = createApiRequestOptions(req);
const apiReq = http.request(url.parse(`http://localhost:3000${req.originalUrl}`), options, (apiRes: any) => {
const headers = apiRes.headers;
res.writeHead(apiRes.statusCode, { ...headers });
apiRes.pipe(res);
apiRes.on('close', () => {
res.end();
});
});
apiReq.on('error', (e: ErrorEvent) => {
console.error(e);
});
apiReq.end();
});
server.get('*.*', express.static(distFolder, {
maxAge: '1y'
}));
server.get('*', (req, res) => {
res.render(indexHtml, {
req,
providers: [
{ provide: 'REQUEST', useValue: req },
]
});
});
return server;
}
export const appUrl = 'http://localhost:4000';
在server.ts文件中,将以下代码放在创建服务器的代码之前:
global['Event'] = null;
global['window'] = { location: { href: null }, Evergreen: { isDocumentReplaced: true }};
global['document'] = { cookie: '', createElement: () => ({}) };
global['navigator'] = {};
global['requestAnimationFrame'] = (callback) => setTimeout(callback, 0, Date.now());
global['XMLHttpRequest'] = require('xmlhttprequest').XMLHttpRequest;
这会在Node.js环境中创建所需的全局变量。请注意,这些变量的实际值不重要,只要
上一篇:AngularUniversalSSR在初始导航后不能使用包含参数的路由
下一篇:AngularUniversalSSR中使用withServerTransition时,ViewEncapsulation无法从服务器传输到浏览器