角通用闪烁

问题描述 投票:0回答:6

我在加载网站时出现闪烁。 下载来自服务器的 HTML,然后在 UI 中呈现视图,并且在转换之间有一个小的闪烁。

我设法通过添加来修复它:

RouterModule.forRoot([ // ROUTES HERE ], { initialNavigation: 'enabled' })

但我想知道为什么会这样?因为组件的延迟加载? 所以我们在 UI(角度组件)构建 DOM 时在过渡之间出现了闪烁?假设我有一个“光”组件,闪烁会更快吗?

angular angular-universal
6个回答
3
投票

向下滚动到答案的粗体部分, 阅读所有内容以了解正在发生的事情。

关于正在发生的事情的非常简单的解释:

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代码和更详尽的解释


1
投票

我也遇到了这个问题,但遗憾的是,initialNavigatin 没有帮助。但是,无论如何,您可以在这个 github 问题上找到“为什么”会发生这种情况的详细信息: https://github.com/angular/angular/issues/15716

确认。在我的应用程序中,所有路由都是延迟加载的,使用带有默认 ViewEncapsulation 的 css 和 angular 开始在浏览器中使用 ng-transition 删除标签,这个过程需要一秒钟。引导程序完成后,它会将样式添加回来。 这是它的样子http://take.ms/1wizt

希望这可以帮助您理解,我仍在尝试在我的应用程序上解决这个问题


1
投票

@DonDaniel 的回答是正确的,但有点过时了。

在 Angular 6+ 中,您可以使用 TransferHttpCacheModule官方文档 解释了 3 行更改是如何产生魔力的。

还有一篇好文章比较旧方法和新方法。


1
投票

我也收到同样的问题。 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);
    }
  }

}

0
投票

TL;DR;

在你的 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>

-2
投票

解决这个问题的最简单方法。

显示:如果 isPlatformServer() 则无。

让我们为它使用CSS,享受生活

让自己快乐。

<div [ngStyle]=" isServer ? {'display':'none'}:{}">
    <router-outlet></router-outlet>
    </div>
    <div [ngStyle]=" isBrowser ? {}:{'display':'none'}">
        <router-outlet></router-outlet>
        </div>
© www.soinside.com 2019 - 2024. All rights reserved.