【问题标题】:SSR - Angular Universal 9 loading my root twice and hangingSSR - Angular Universal 9 加载我的根两次并挂起
【发布时间】:2024-01-12 07:37:01
【问题描述】:

我试图找出为什么我的代码使用 Angular 9 SSR 绑定根两次。

我尝试了 eventReplayer.replayAll() 技巧,但我仍然卡住了,我注意到当我滚动到页面时,我终于完美加载了正确的根目录,而另一个根目录被删除(ng-non-bindable ),所以我删除了 PrebootModule 只是为了缩小问题范围,我在我的 dom 中有一个根,但应用程序无法正常运行。

app.component.ts

BrowserModule.withServerTransition({appId: 'dcaa'}),
PrebootModule.withConfig({appRoot: 'dcaa-root'}),
.
.
.
{
      provide: APP_INITIALIZER,
      useFactory: function (document: HTMLDocument, platformId: Object): Function {
        return () => {
          if (isPlatformBrowser(platformId)) {
            const dom = getDOM();
            const styles: any[] = Array.prototype.slice.apply(document.querySelectorAll('style[ng-transition]'));
            styles.forEach(el => {
              // Remove ng-transition attribute to prevent Angular appInitializerFactory
              // to remove server styles before preboot complete
              el.removeAttribute('ng-transition');
            });
            document.addEventListener('PrebootComplete', () => {
              // After preboot complete, remove the server scripts
              setTimeout(() => styles.forEach(el => dom.remove(el)));
            });
          }
        };
      },
      deps: [DOCUMENT, PLATFORM_ID],
      multi: true
    }

app.routes.ts

imports: [RouterModule.forRoot(routes, {
    scrollPositionRestoration: 'disabled',
    relativeLinkResolution: 'corrected',
    preloadingStrategy: PreloadAllModules,
    initialNavigation: 'enabled'
  }),

app.server.module.ts

imports: [
    AppModule,
    ServerModule,
    ServerTransferStateModule,
    FlexLayoutServerModule
  ],

ma​​in.ts

document.addEventListener('DOMContentLoaded', () => {
  platformBrowserDynamic()
    .bootstrapModule(AppModule)
    .catch(err => console.log(err));
});

【问题讨论】:

    标签: angular server-side-rendering angular9 angular-universal


    【解决方案1】:

    当我在浏览器端的 ngAfterViewInit 期间尝试操作 DOM 时,我遇到了与预启动相同的问题,这导致 PrebootComplete 无法正确触发,因为 DOM 已更改。

    解决方法是在您的组件中注入 EventReplayer

    import { EventReplayer } from 'preboot';
    
    constructor(
        @Inject(PLATFORM_ID) private platformId: any,
        private replayer: EventReplayer
      )
    

    然后重播预启动事件:

    ngAfterViewInit() {
        if (isPlatformBrowser(this.platformId)) {
          // ....
          // Manipulate your DOM here 
          // ....
    
          this.replayer.replayAll()      
        }
      }
    

    【讨论】:

      最近更新 更多