错误参考错误:文档未定义
import { readFileSync } from 'fs';
const domino = require('domino'); // import the library `domino`
const DIST_FOLDER = join(process.cwd(), 'dist/browser');
const template = readFileSync(join(DIST_FOLDER, 'index.html')).toString(); // use `index.html` as template
const win = domino.createWindow(template); // create object Window
global['window'] = win;
global['Event'] = win.Event; // assign the `win.Event` to prop `Event`
global['document'] = win.document;
即使在 Server.ts 中添加此解决问题,但在性能上 TTFB 时间太高。 有解决办法吗...?
尝试使用@angular/common包提供的DOCUMENT常量
import { Inject, Injectable } from '@angular/core';
import { DOCUMENT } from '@angular/common';
@Injectable()
export class MyService {
constructor(@Inject(DOCUMENT) private document: Document) {}
}
这些全局变量包括 window、document、localStorage、indexedDB、setTimeout 和 setInterval,您不能在 Angular 通用应用程序中使用
使用 Anguar 公共模块中的文档对象
从库导入
import { DOCUMENT } from '@angular/common';
投入使用
@Inject(DOCUMENT) private document: Document,
尽管有标题,但看起来您的问题更多的是关于缓慢的 TTFB,而不是
document
未定义的错误。
关于未定义文档错误,解决办法是:
使用以下注入
@Inject(DOCUMENT) private document
如果错误出现在你自己的代码中如果错误出现在第 3 方库中,并且无法将这些库替换为与 Angular Universal 兼容的其他库,请使用
domino
。要解决TTFB慢的问题,没有什么神奇的解决办法。尽量避免渲染那些绝对不需要在服务器端渲染的组件,确保没有长时间运行的 API 调用,使用缓存
如果您有一个与 Angular Universal 不兼容的库,则不应在服务器上渲染此包,而应在服务器返回响应后在客户端上渲染它。
isBrowser = false;
constructor(@Inject(PLATFORM_ID) private platformId) {
this.isBrowser = isPlatformBrowser(this.platformId);
}
现在你必须像这样使用该包:
if (this.isBrowser) {
... use package
}
或者你可以在html代码中使用ngIf。
文档中指出:某些常见的浏览器 API 和功能可能在服务器上不可用。应用程序无法使用特定于浏览器的全局对象,例如窗口、文档、导航器或位置以及 HTMLElement 的某些属性。
一般来说,依赖于浏览器特定符号的代码只能在浏览器中执行,而不是在服务器上执行。这可以通过 afterRender 和 afterNextRender 生命周期挂钩来强制执行。这些仅在浏览器上执行并在服务器上跳过。
因此,依赖于浏览器特定 API 的代码应移至 afterRender 和 afterNextRender 生命周期挂钩。 例如
import { Component, ViewChild, afterNextRender } from '@angular/core';
@Component({
selector: 'my-cmp',
template: `<span #content>{{ ... }}</span>`,
})
export class MyComponent {
@ViewChild('content') contentRef: ElementRef;
constructor() {
afterNextRender(() => {
// Safe to check `scrollHeight` because this will only run in the
browser, not the server.
console.log('content height: ' +
this.contentRef.nativeElement.scrollHeight);
});
} }
您也可以使用 afterRender()。 您需要重新启动服务器才能显示更改