【问题标题】:Angular universal flickering角通用闪烁
【发布时间】:2018-10-04 12:20:21
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: angular angular-universal


    【解决方案1】:

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

    在 Angular 6+ 中,您可以使用 TransferHttpCacheModuleOfficial docs 解释 3 行更改如何发挥作用。

    还有一个good article 将旧方法与新方法进行比较。

    【讨论】:

      【解决方案2】:

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

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

      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))
          }
      

      我从以下渠道获得所有这些信息: Angular Universal with FirebaseCode and a more thorough explanation

      【讨论】:

      • this.afs.doc&lt;any&gt; 应该是什么?我想象 AppComponent 的整个 html。你介意再解释一下吗?
      • 这是构造函数:constructor( private afs: AngularFirestore, private seo: SeoService, private route: ActivatedRoute, private state: TransferState ) {} 它所做的只是监听从 firestore 返回的值的变化。这可以很容易地成为您自己的某个状态的选择器。在此示例中,我们只是根据从 firestore 获得的结果更改标题和元标记。请注意,我从angularfirebase.com/lessons/… 获取了所有这些信息
      【解决方案3】:

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

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

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

      【讨论】:

      • 您找到解决方案了吗?对我来说 initialNavigation 也不起作用;/
      • 是的。我的也闪烁,也没有延迟加载或启用。
      猜你喜欢
      • 1970-01-01
      • 2020-02-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-12
      • 2021-04-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多