我在加载网站时出现闪烁。 下载来自服务器的 HTML,然后在 UI 中呈现视图,并且在转换之间有一个小的闪烁。
我设法通过添加来修复它:
RouterModule.forRoot([ // ROUTES HERE ], { initialNavigation: 'enabled' })
但我想知道为什么会这样?因为组件的延迟加载? 所以我们在 UI(角度组件)构建 DOM 时在过渡之间出现了闪烁?假设我有一个“光”组件,闪烁会更快吗?
向下滚动到答案的粗体部分, 阅读所有内容以了解正在发生的事情。
关于正在发生的事情的非常简单的解释:
1.) 用户访问您的应用程序(或刷新)
2.) 服务器在服务器中构建html
3.) 它被发送到用户看到它的浏览器
4.) Angular 应用程序“重新创建”应用程序(就好像它是一个常规的非通用应用程序)
5.) 当这种变化发生时,用户会看到一个闪光。
// You can see this by adding:
// You should see a console log in the server
// `Running on the server with appId=my-app-id`
// and then you'll see in the browser console something like
// `Running on the browser with appId=my-app-id`
export class AppModule {
constructor(
@Inject(PLATFORM_ID) private platformId: Object,
@Inject(APP_ID) private appId: string) {
const platform = isPlatformBrowser(this.platformId) ?
'in the browser' : 'on the server';
console.log(`Running ${platform} with appId=${this.appId}`);
}
}
这是有意为之,因为您希望机器人能够获取元标记等。
为了移除闪存,您可以做的是将状态从服务器传输到客户端:
您需要将此添加到 AppServerModule 中的导入
ServerTransferStateModule
您需要将其添加到您的 AppModule:
BrowserTransferStateModule
更新 main.ts 文件以在引导浏览器应用程序之前侦听 DOMContentLoaded:
document.addEventListener('DOMContentLoaded', () => {
platformBrowserDynamic().bootstrapModule(AppModule)
})
然后是一个关于如何转移状态的例子:
import { tap, startWith } from 'rxjs/operators';
import { TransferState, makeStateKey } from '@angular/platform-browser';
const ANIMAL_KEY = makeStateKey<any>('animal');
// omitted ...
ngOnInit() {
const id = this.route.snapshot.paramMap.get('name').toLowerCase();
this.animal$ = this.ssrFirestoreDoc(`animals/${id}`);
}
ssrFirestoreDoc(path: string) {
const exists = this.state.get(ANIMAL_KEY, {} as any);
return this.afs.doc<any>(path).valueChanges().pipe(
tap(animal => {
this.state.set(ANIMAL_KEY, animal)
this.seo.generateTags({
title: animal.name,
description: animal.bio,
image: animal.imgURL
});
}),
startWith(exists))
}
我得到了所有这些: 带有 Firebase 的 Angular Universal 和 代码和更详尽的解释
我也遇到了这个问题,但遗憾的是,initialNavigatin 没有帮助。但是,无论如何,您可以在这个 github 问题上找到“为什么”会发生这种情况的详细信息: https://github.com/angular/angular/issues/15716
确认。在我的应用程序中,所有路由都是延迟加载的,使用带有默认 ViewEncapsulation 的 css 和 angular 开始在浏览器中使用 ng-transition 删除标签,这个过程需要一秒钟。引导程序完成后,它会将样式添加回来。 这是它的样子http://take.ms/1wizt
希望这可以帮助您理解,我仍在尝试在我的应用程序上解决这个问题
@DonDaniel 的回答是正确的,但有点过时了。
在 Angular 6+ 中,您可以使用 TransferHttpCacheModule。 官方文档 解释了 3 行更改是如何产生魔力的。
还有一篇好文章比较旧方法和新方法。
我也收到同样的问题。 SSR 加载了两次。
Angular version : 14.0.4
Firebase version : 9.8.1
我不得不在
enabledBlocking
文件中将“启用”替换为app-routing.module.ts
。
const options: ExtraOptions = {
preloadingStrategy: MyPreloadingStrategyService,
scrollPositionRestoration: 'enabled' ,
initialNavigation : 'enabledBlocking',
onSameUrlNavigation: 'reload'
}
@NgModule({
imports: [RouterModule.forRoot(routes, options)],
exports: [RouterModule]
})
MyPreLoadingStragegyService
页面
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { PreloadingStrategy, Route } from '@angular/router';
@Injectable({
providedIn: 'root'
})
export class MyPreloadingStrategyService implements PreloadingStrategy {
/** */
constructor() { }
/**
* It's used in lazy load module.
* It's used to loaded Modules in the background asynchronously.
* if route.data['preload'] true than preload else load on lazy load route.
* @returns Observable
*/
preload(route: Route, load: () => Observable<any>): Observable<any> {
// console.log('route.data', route.data);
if (route.data && route.data['preload']) {
return load();
} else {
return of(null);
}
}
}
在你的 app.component.ts:
import { isPlatformBrowser, isPlatformServer } from "@angular/common";
this.isServer = isPlatformServer(this.platformId);
this.isBrowser = isPlatformBrowser(this.platformId);
并使用
display: none;
隐藏服务器块以防止闪烁
<div style="display: none" *ngIf="isServer">
<router-outlet></router-outlet>
</div>
<div *ngIf="isBrowser">
<router-outlet></router-outlet>
</div>
解决这个问题的最简单方法。
显示:如果 isPlatformServer() 则无。
让我们为它使用CSS,享受生活
让自己快乐。
<div [ngStyle]=" isServer ? {'display':'none'}:{}">
<router-outlet></router-outlet>
</div>
<div [ngStyle]=" isBrowser ? {}:{'display':'none'}">
<router-outlet></router-outlet>
</div>