如何让 Angular Universal 和 PWA 协同工作?

Posted

技术标签:

【中文标题】如何让 Angular Universal 和 PWA 协同工作?【英文标题】:How to make Angular Universal and PWA work together? 【发布时间】:2019-10-16 10:10:10 【问题描述】:

我有一个 s-s-r Angular 应用程序,我正在尝试将其转换为 PWA。我希望它为 SEO 和它提供的“快速首次渲染”在服务器端渲染。

PWA 模式在与 s-s-r 结合使用时可以正常工作,但是一旦加载应用程序,当我们刷新它时,会加载客户端索引 html 文件而不是服务器端呈现的页面。

我研究了ngsw-worker.js 的代码,我看到了这个:

// 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);

我无法控制此文件,因为它来自框架并且未向开发人员公开。 有没有人为此找到解决方案或解决方法?

【问题讨论】:

【参考方案1】:

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

然后我是这样配置的:

"navigationUrls": [
    "!/**"
]

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

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

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

为了将GET XMLHttpRequest 与导航请求区分开来,Service Worker 在导航时使用Request.mode 属性和包含text/htmlAccept 标头,在请求后端时使用application/json, text/plain, */*

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

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

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

更新 v11.0.0

Angular 现在有一个navigationRequestStrategy 选项,允许优先考虑服务器的导航请求。更新日志摘录:

service-worker:添加选项以首选网络进行导航 请求(#38565)(a206852),关闭#38194

要明智地使用!此警告出现在文档中:

freshness 策略通常会导致更多请求发送到 服务器,这会增加响应延迟。建议 尽可能使用默认性能策略。

【讨论】:

以上是关于如何让 Angular Universal 和 PWA 协同工作?的主要内容,如果未能解决你的问题,请参考以下文章

Angular Universal - 部署到 AWS Elastic Beanstalk

Angular 2 Universal - 使用手写笔和 pug 模板的服务器端渲染

如何正确启动 Angular Universal 到实时服务器

如何在 Angular 4 Universal 中发出 http post 请求?

如何在 Angular Universal 中获取完整的基本 URL(包括服务器、端口和协议)?

Angular Universal:如何解决缺少的名称、模块和其他奇怪的事情