How to make Angular Universal and PWA work together?

Twi*_*her 8 javascript progressive-web-apps angular-universal angular angular-service-worker

I have a SSR Angular app which I am trying to transform into a PWA. I want it to be server-side rendered for SEO and for the "fast first rendering" that it provides.

The PWA mode works fine when combined with SSR, but once the app is loaded, when we refresh it, the client index HTML file is loaded instead of the server-side rendered page.

I have dug into the code of ngsw-worker.js and I saw this:

// Next, check if this is a navigation request for a route. Detect circular
// navigations by checking if the request URL is the same as the index URL.
if (req.url !== this.manifest.index && this.isNavigationRequest(req)) {
    // This was a navigation request. Re-enter `handleFetch` with a request for
    // the URL.
    return this.handleFetch(this.adapter.newRequest(this.manifest.index), context);
}
Run Code Online (Sandbox Code Playgroud)

I have no control over this file since it's from the framework and not exposed to developers. Did anybody find a solution or workaround for this?

Twi*_*her 7

我找到了一个可行的解决方案,navigationUrls属性ngsw-config.json包含包含或排除的导航 URL 列表(带有感叹号),如文档所述

然后我这样配置:

"navigationUrls": [
    "!/**"
]
Run Code Online (Sandbox Code Playgroud)

这样index.html,无论 URL 是什么,当应用程序首次被请求(或刷新)时,任何 URL 都不会重定向到服务器端呈现的应用程序。

更进一步,Service Worker 管理的三种 URL 是:

  • 非导航 URL:由 Service Worker 缓存并在生成的ngsw.json文件中列出的静态文件及其相应的哈希值
  • 导航 URL:index.html默认重定向到,如果使用"!/**"配置则转发到服务器
  • GET 对后端的请求:转发到后端

为了区分GET XMLHttpRequest导航请求和导航请求,Service Worker 使用Request.mode属性以及导航和请求后端时Accept包含的标头。text/htmlapplication/json, text/plain, */*

编辑:这实际上不是一个好的做法,原因有两个:

  • 根据网络质量,不能保证服务器端版本的渲染速度比缓存的浏览器版本快
  • 它打破了“后台更新”机制。实际上,服务器端呈现的应用程序将始终引用最新版本的 JavaScript 文件

有关这方面的更多详细信息,请查看 Angular 团队成员对我的功能请求的回答:https : //github.com/angular/angular/issues/30861