英文:
Angular Prerendering: Using JS conditionally causes 'document is not defined'
问题
I understand your question. It seems that Bootstrap is causing issues with pre-rendering due to its access to the document
object even before Bootstrap.Modal
is instantiated. To address this, you can try the following:
-
Lazy Loading: You can try lazy loading Bootstrap or delaying its initialization until the component has fully loaded. This might prevent it from accessing
document
too early. -
Server-Side Rendering (SSR) Compatibility: Some libraries are not designed to work with SSR. Check if Bootstrap provides any SSR compatibility or if there are alternative libraries that work better in a server-side rendering environment.
-
Debugging: To find the exact file where
document
is called, you can use source maps and debugging tools in your development environment. Look for any parts of the Bootstrap code that might be causing this issue. -
Alternative Libraries: If Bootstrap continues to be problematic, consider using alternative libraries that are designed with server-side rendering in mind or have fewer dependencies on the DOM.
Remember to consult Bootstrap's documentation and community forums for any updates or solutions related to server-side rendering compatibility.
英文:
I'm using Angular 15 and I'm trying to pre-render a website for SEO purposes. I understand that facilities such as document
and window
aren't available when pre-rendering because the code isn't running on a browser.
I'm using a few JS libraries that manipulate the DOM directly and in order to support pre-rendering I'm doing this:
import Typed from 'typed.js';
export class ExampleComponent implements OnInit {
typed?: Typed;
constructor(
@Inject(PLATFORM_ID) private platformId: any
) { }
ngOnInit(): void {
if (isPlatformBrowser(this.platformId)) {
this.typed = new Typed('#searchdomain', {
strings: ["example", "anoter" ""],
typeSpeed: 80,
contentType: "text"
});
}
}
As you can see Typed
is only instantiated if the application is running on a browser.
Now I tried to do the same with Bootstrap 5 however it fails.
import * as Bootstrap from 'bootstrap/dist/js/bootstrap.esm.min.js';
export class ExampleComponent implements OnInit {
private bsModalInstance?: Bootstrap.Modal;
@ViewChild('bsmodal', {read: ElementRef, static: false}) modalRef?: ElementRef;
constructor(
@Inject(PLATFORM_ID) private platformId: any
) { }
ngOnInit(): void {
if (isPlatformBrowser(this.platformId)) {
this.bsModalInstance = new Bootstrap.Modal(this.modalRef?.nativeElement);
}
}
Output of npm run prerender
:
⠴ Prerendering 2 route(s) to -path-\-proj-\dist\-proj-\browser...
Unhandled Promise rejection: document is not defined ; Zone: <root> ; Task: Promise.then ; Value: ReferenceError: document is not defined
at enableDismissTrigger (-path-\-proj-\dist\-proj-\server\main.js:1:3878580)
at -path-\-proj-\dist\-proj-\server\main.js:1:3879522
at -path-\-proj-\dist\-proj-\server\main.js:1:3977330
at Object.<anonymous> (-path-\-proj-\dist\-proj-\server\main.js:1:3977562)
at Module._compile (internal/modules/cjs/loader.js:1085:14)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
at Module.load (internal/modules/cjs/loader.js:950:32)
at Function.Module._load (internal/modules/cjs/loader.js:790:12)
at Module.require (internal/modules/cjs/loader.js:974:19)
at require (internal/modules/cjs/helpers.js:101:18) ReferenceError: document is not defined
at enableDismissTrigger (-path-\-proj-\dist\-proj-\server\main.js:1:3878580)
at -path-\-proj-\dist\-proj-\server\main.js:1:3879522
at -path-\-proj-\dist\-proj-\server\main.js:1:3977330
at Object.<anonymous> (-path-\-proj-\dist\-proj-\server\main.js:1:3977562)
at Module._compile (internal/modules/cjs/loader.js:1085:14)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
at Module.load (internal/modules/cjs/loader.js:950:32)
at Function.Module._load (internal/modules/cjs/loader.js:790:12)
at Module.require (internal/modules/cjs/loader.js:974:19)
at require (internal/modules/cjs/helpers.js:101:18)
✖ Prerendering routes to -path-\-proj-\dist\-proj-\browser failed.
document is not defined
Why does it fail when Bootstraps's Bootstrap.Modal
isn't even instantiated?
Is there any way to have more debug so I can find the exact file where document.
is called?
Update: I decided to add a console.log()
on the component's constructor and it never shows up. I believe bootstrap, when imported, is accessing the document
right away, even before the Bootstrap.Modal
call.
Thank you.
答案1
得分: 1
这确实是由Bootstrap在导入时访问windows
、document
和一些其他对象引起的问题。这个问题已经在https://github.com/twbs/bootstrap/pull/34989上进行讨论,并有一个修复了一些问题但不是全部的PR。
我决定分支该存储库并将进一步的修复添加到jo-ssr-friendly
分支。同时,我也将它重新基于了最新的稳定版本。
如果将来有人遇到这个问题,可以直接从我的分支安装所有这些修复:
npm install "https://github.com/TCB13/bootstrap.git#jo-ssr-friendly" --save
英文:
This was indeed a problem caused by Bootstrap accessing the windows
, document
and some other objects when imported. This was already under discussion at https://github.com/twbs/bootstrap/pull/34989 with a PR that fixed some of the issues but not all.
I decided to fork the repository and add further fixes to the jo-ssr-friendly
branch. Also rebased it to the latest stable release.
If anyone comes across this in the future all those fixes can be installed directly from my fork:
npm install "https://github.com/TCB13/bootstrap.git#jo-ssr-friendly" --save
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论