【问题标题】:Angular Universal requires initialNavigation=enabled which breaks APP_INITIALIZER and GuardsAngular Universal 需要 initialNavigation=enabled 这会破坏 APP_INITIALIZER 和 Guards
【发布时间】:2020-12-08 08:46:21
【问题描述】:

在将 Angular Universal 添加到我们的应用时,我们必须在路由器上设置 initialNavigation="enabled" 标志,以避免闪烁。

现在这给我们带来了 2 个问题:

  1. 我们动态创建路线,现在打开其中一条路线失败
  2. 因为应用程序不等待APP_INITIALIZERs 加载,所以无法加载受保护的路由,因为保护始终假定用户未授权,因为检查发生在APP_INITIALIZER

我发现了几个关于此的 Github 问题(即https://github.com/angular/universal/issues/1623),但没有一个真正提供解决方案。

如何在等待APP_INITIALIZERs 执行的同时使用initialNavigation="enabled"

编辑 (01/02/2021):在 Angular 11 中,措辞已更改,该选项现在称为 enabledBlocking。但是这里提到的问题并没有涉及到。

【问题讨论】:

  • 你找到解决办法了吗?
  • 我确实一起破解了一些东西,是的:github.com/angular/universal/issues/1817#issuecomment-699898024
  • 感谢您的快速回复,将看看它!
  • 我进步了很多,但我卡在了 DYNAMIC_ROUTES 注入器令牌上。这是一项服务还是它看起来如何?非常感谢!谢谢!
  • 而且它确实有效!你太棒了!非常感谢您的帮助!

标签: angular angular-universal


【解决方案1】:
  1. 'enabledBlocking' - 初始导航在根之前开始 组件被创建。引导程序被阻塞,直到初始 导航完成。服务器端需要此值 渲染工作。
  2. 'enabledNonBlocking' - (默认)初始导航在之后开始 根组件已创建。引导程序未被阻止 在完成初始

希望对你有帮助

 RouterModule.forRoot(routes, {
      relativeLinkResolution: 'corrected',
      initialNavigation: 'enabledBlocking',
      useHash: true
    }),

【讨论】:

  • 这是 Angular v11 引入的更改,但它只是清理了措辞/删除了旧选项,对问题中描述的问题没有帮助。 enabledBlockingenabled (angular.io/api/router/InitialNavigation) 的一对一替换
【解决方案2】:

我也会提供我在这里找到的解决方案。我还在 Angular Universal 的 Github 存储库中以 issue 的形式发布了它。如果对 Universal 进行了更改,这将使这更容易,我会更新这个答案。

解决方案: 基本上我现在所做的,是在 Angular 应用程序完全启动之前,在服务器和应用程序中获取有关页面的数据。在路由器进行初始导航之前,更改app-routing.modules-constructor 中的routes-array 显然已经足够早地获取动态路由了。

看起来或多或少是这样的(正如 Nicolae 所说,这可以重构以避免重复代码):

server.ts:

server.get('*', (req, res) => {
  // fetch dynamic routes
  // /!\ duplicate code to src/main.ts
  fetch('http://static.content/')
    .then(response => response.json())
    .then(resp => {
      const routes = resp.entries.map(route => ({
        path: route.path,
        component: StaticContentComponent,
        data: {
          id: route._id,
          name: route.name
        }
      }));

      res.render(indexHtml, {
        req,
        providers: [
          { provide: APP_BASE_HREF, useValue: req.baseUrl },
          { provide: DYNAMIC_ROUTES, useValue: routes }
        ]
      });
    });
  });

  return server;
}

main.ts基本一样:

document.addEventListener('DOMContentLoaded', () => {
  // fetch dynamic routes
  // /!\ duplicate code to server.ts
  fetch('http://static.content/')
    .then(response => response.json())
    .then(resp => {
      const routes = resp.entries.map(route => ({
        path: route.path,
        component: StaticContentComponent,
        data: {
          id: route._id,
          name: route.name
        }
      }));

      platformBrowserDynamic([
        { provide: DYNAMIC_ROUTES, useValue: routes }
      ])
        .bootstrapModule(AppModule)
        .catch(err => console.error(err));
    });
});

然后在我的app-routing.module.ts 中,我将DYNAMIC_ROUTES 中提供的数据添加到路由中:

const DYNAMIC_ROUTES = new InjectionToken<IEnvironment>('dynamicRoutes');

@NgModule({
  imports: [
    RouterModule.forRoot(routes, {
      initialNavigation: 'enabled'
    })
  ],
  exports: [RouterModule]
})
export class AppRoutingModule {
  constructor(@Inject(DYNAMIC_ROUTES) private dynamicRoutes, private router: Router) {
    const config = router.config;
    config.unshift(...this.dynamicRoutes);
    this.router.resetConfig(config);
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-14
    • 2019-01-25
    • 2011-06-11
    • 2018-04-28
    • 1970-01-01
    • 2014-11-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多