我正在尝试将Angular Service Worker集成到现有项目中。如果我理解正确,有两种情况下数据是如何缓存在Angular SW中的。可以预取或懒散地更新资产数据,并缓存特定的API调用和其他XHR请求。
我试图实现的是首先通过网络加载特定的资产,如果请求超时或无法访问,它将通过缓存提供服务。就像缓存API调用时的新鲜
策略一样。但似乎没有可能为在Angular项目中作为资产加载的JS文件配置这种新鲜加载机制。我设置了一个示例项目进行测试:https://github.com/philipp-schaerer-lambdait/angular-service-worker-test
以下示例是一个标准的Angular App,不包含我正在使用的实际项目,但显示了我想要缓存的元素,结构如下所示:
\_ Angular root
|_ src/
|_ index.html <----------- links to excluded_asset.js
|_ app/
|_ assets/
|_ excluded_asset.js <-- this one is excluded in ngsw-config.json
|_ included_asset.js
|_ ...
以下是相关配置:
ngsw配置。json
{
"index": "/index.html",
"assetGroups": [
{
"name": "app",
"installMode": "prefetch",
"resources": {
"files": ["/favicon.ico", "/index.html", "/*.css", "/*.js"]
}
},
{
"name": "assets",
"installMode": "lazy",
"updateMode": "prefetch",
"resources": {
"files": ["/assets/**", "!/assets/excluded_asset.js"]
}
}
]
}
是否可以通过对资产使用installMode和updateMode来实现像freshness策略这样的缓存行为?
我尝试将其从资产缓存中排除,并通过网络加载,但显然在脱机后服务人员不会提供。
之后,我尝试通过数据组再次将其包括在内,并将策略设置为新鲜度,但似乎一旦资产从资产配置中排除,它就不会再次被缓存。此外,我认为数据组设置不能用于此文件。
"dataGroups": [
{
"name": "config",
"urls": ["assets/excluded_asset.js"],
"cacheConfig": {
"maxSize": 10,
"maxAge": "1d",
"timeout": "100",
"strategy": "freshness"
}
}
}
我错过了什么还是没有办法通过新鲜
策略缓存资产?最好不要移动文件或更改文件的请求方式。
编辑
我试图将其移动到缓存资产目录之外,并将其包含在数据组设置中,但也没有成功。
我也有同样的问题。我发现总是有最新的js和css文件的解决方案只是排除索引。来自缓存资产的html。
{
"index": "/index.html",
"assetGroups": [
{
"name": "app",
"installMode": "prefetch",
"updateMode": "prefetch",
"resources": {
"files": [
"/*.css",
"/*.js",
"!/index.html" // Right here!!!!!
]
}
},
{
"name": "assets",
"installMode": "lazy",
"updateMode": "lazy",
"resources": {
"files": ["/static/**"]
}
}
]
}
确保将“outputHashing”:“all”,添加到角度构建配置中。这样,当您对代码进行更改时,它将生成一个具有不同名称的文件。然后,它会自动将脚本标记(或链接标记)添加到html文件中(服务人员将忽略该文件),并在您将更改推送到生产时,立即添加索引。html将指向您的新js和css文件。
当然,这很糟糕:你的指数。html不会被服务人员缓存,但至少它允许返回的用户直接拥有最新的文件。
我真的希望有一种方法可以为资产提供“新鲜度”选项...
带有Service Worker的新应用程序
该命令将如下所示:
ng new myApp --service-worker (or using the alias — -sw )
使用此service worker标志,Angular CLI 1.6将为我们实现一些自动化:
无论如何,即使在CLI 1.6发布之后,知道如何再现这些步骤也很好,因为我们必须手动执行这些步骤才能将NGSW支持添加到现有应用程序中。让我们将角度服务人员添加到pWater。
将Angular Service Worker添加到现有应用程序
让我们手动执行上面相同的4个步骤:
1、安装NGSW
npm install @angular/service-worker --save
2、启用构建支持(仅适用于Angular CLI 1.6,请参见下面的注意事项)
ng set apps.0.serviceWorker=true
或者在.angular-cli.json
文件中手动添加/编辑此参数。
重要!目前,当我们使用Angular CLI 1.5时,请确保您在中没有此属性。angular-cli.json
,它会导致构建错误。请参阅下面Angular CLI 1.5中如何模拟此步骤。
3.在您的AppModule
中注册NGSW。这是它在Angular CLI 1.6中的外观:
import { ServiceWorkerModule } from '@angular/service-worker'
import { environment } from '../environments/environment';
...
@NgModule({
imports: [
...
environment.production ? ServiceWorkerModule.register('/ngsw-worker.js') : []
],
...
})
export class AppModule { }
4.创建NGSW配置文件(默认名称为src/ngsw-config.json)。这里默认内容将由Angular CLI 1.6生成。
{
"index": "/index.html",
"assetGroups": [{
"name": "app",
"installMode": "prefetch",
"resources": {
"files": [
"/favicon.ico",
"/index.html"
],
"versionedFiles": [
"/*.bundle.css",
"/*.bundle.js",
"/*.chunk.js"
]
}
}, {
"name": "assets",
"installMode": "lazy",
"updateMode": "prefetch",
"resources": {
"files": [
"/assets/**"
]
}
}]
}
目前,在使用Angular CLI 1.5时,我们还必须模拟步骤2中的构建支持。实际上,除了ng build--prod
命令之外,还应该执行2个额外的操作(为了使用NGSW,使用生产构建很重要!):
基于NGSW配置文件src/ngsw-config.json使用NGSW CLI ngsw-config生成NGSW控制(清单)文件ngsw.json。
将NGSW本身从npm\U模块包文件夹复制到我们的dist文件夹。
要使用一个简单的命令生成具有NGSW支持的生产构建,让我们添加一些npm脚本:
{
...
"scripts": {
...
"ngsw-config": "node_modules/.bin/ngsw-config dist src/ngsw-config.json",
"ngsw-copy": "cp node_modules/@angular/service-worker/ngsw-worker.js dist/",
"build-prod-ngsw": "ng build --prod && npm run ngsw-config && npm run ngsw-copy",
"serve-prod-ngsw": "npm run build-prod-ngsw && http-server dist -p 8080"
}
}
现在,如果我们运行npm run build prod ngsw,我们将在dist文件夹中获得角度PWA。或者,我们可以通过运行npm run serve prod ngsw,使用最简单的http服务器为其提供服务。
重要!不要使用ng service
来测试您的Angular Service Worker。此开发服务器并非旨在与PWA流协作工作。始终构建应用程序的生产版本,并使用任何静态Web服务器从您的分发文件夹中提供它。
应用程序外壳
如果我们执行上述操作并运行npm run build prod ngsw — 默认形式的角度PWA已经为我们准备好了!部署应用程序或使用任何静态web服务器在本地运行它(在我的情况下,您可以运行npm run serve prod ngsw来构建和服务)。
我们脱机后,应用程序将正常工作。为什么?因为NGSW缓存了配置文件assetgroups部分中列出的所有资源,现在它负责从缓存存储中为它们提供服务,而缓存存储中现在充满了记录:
服务工作者已注册并处于活动状态
我们可以查看缓存响应的内容(目前仅在Chrome Canary中提供)
NGSW使用缓存存储HTTP响应数据和一些元数据来处理版本控制:
NGSW存储类型
如果您使DevTools保持打开状态,那么在服务工作者端的每个操作之后,缓存存储部分中的条目很可能不会自动更新。如果希望查看实际数据,请右键单击并选择“刷新缓存”。
对。NGSW配置文件的默认形式对于我们的案例来说是不够的,因为我们使用的是材质图标网络字体。显然,这些资源(对应的CSS和WOFF2文件)没有被NGSW缓存,但我们可以通过在assetGroup
中添加一个组来轻松修复它除了默认的app
和资产
的。让我们称之为fonts
:
{
...
"assetGroups": [
...
{
"name": "fonts",
"resources": {
"urls": [
"https://fonts.googleapis.com/**",
"https://fonts.gstatic.com/**"
]
}
}]
}
使用globs语法指定这些资源是有意义的,因为字体文件的确切URL可能会不时更改以支持webfont版本控制。此外,您可能会注意到,我们既没有指定installMode,也没有指定updateMode。一方面,在生成的NGSW控制文件中,两者都将设置为预取,因为这是默认值。另一方面,它们只有在被请求后才会被缓存,因为URL的细节是列出资源的方式。
重建、运行并切换到脱机模式后,我们将看到应用程序的正常状态以及所有图标。
在缓存存储中,我们将看到两个新条目:
NGSW生成的存储
我们甚至可以预览缓存的字体:
assetGroup
和dataGroup
之间存在根本区别。
运行时缓存
对我的时间线APIendpoint使用网络优先策略,对收藏夹endpoint使用缓存优先策略。src/ngsw config中的相应设置。json将如下所示:
{
...
"dataGroups": [{
"name": "api-freshness",
"urls": [
"/timeline"
],
"cacheConfig": {
"strategy": "freshness",
"maxSize": 100,
"maxAge": "3d",
"timeout": "10s"
}
},
{
"name": "api-performance",
"urls": [
"/favorites"
],
"cacheConfig": {
"strategy": "performance",
"maxSize": 100,
"maxAge": "3d"
}
}
]
}
有一个定义NGSW行为的主开关:
cacheConfig/strategy。对于网络优先策略,它是新鲜度,对于缓存优先 — <代码>性能
。
现在,构建、服务、单击加载我的时间线和加载我的收藏夹按钮以获取和缓存API响应,并切换到脱机。
关于在线模式的优化。返回联机并单击一次或两次时间线/收藏夹。很明显,收藏夹会立即加载,因为我们跳过了整个网络旅行,从缓存中获取数据。使用“缓存配置”(cacheConfig)部分中的设置指定缓存的时间 — 我们在那里有细粒度的控制。
NGSW在一些真正智能的网络优化方面帮助了我们很多,只需要我们提供一些JSON配置。
嗨,我正在使用https://tools.pingdom.com来测试我的wordpress网站速度,我有一个杠杆浏览器缓存的F,它说: 以下可缓存资源的新鲜度寿命很短。为以下资源指定至少一周的到期日: https://ssl.google-analytics.com/ga.js https://fonts.googleapis.com/css?family=Droid桑 https://font
我有一个基于service worker的离线应用程序,允许用户离线下载pdf文件。 有一个文本文件,其中包含pdf文件的下载路径和特定格式的文件标题(以及css、js和图像路径),应用程序通过ajax读取此文本文件并绘制所有可用pdf文件的列表(通过显示标题和下载链接) 在安装过程中,工作人员读取相同的文件,并将所有pdf文件与文本文件一起放入缓存中,以便这些文件可以离线访问。 当我用一些新的p
问题内容: 我的任务是利用SpringCache作为我们的一项服务,以减少数据库查找的次数。在测试实现时,我注意到一些可缓存操作通过日志语句多次调用。调查显示,如果在可缓存的方法中调用了可缓存的操作,则嵌套操作根本不会被缓存。因此,嵌套操作的后续调用将导致进一步的查找。 下面列出了描述问题的简单单元测试: 这两种方法的实际工作对于测试用例本身并不重要,因为仅应测试缓存。 我以某种方式理解了为什么不
问题内容: 我们希望在生产部署中缓存崩溃,但不要浪费大量时间来弄清楚这样做的系统。我的想法是将具有当前版本号的paras应用于css和js文件的末尾: 两个问题:这会有效地打破缓存吗?由于参数表明这是动态内容,因此该参数会导致浏览器从不缓存该URL的响应吗? 问题答案: 参数表示查询字符串,因此浏览器将认为这是从到的新路径。因此导致它从文件而不是从缓存加载。如你所愿。 而且,浏览器将假定下次调用时
问题内容: 我们希望在生产部署中缓存崩溃,但不要浪费大量时间来弄清楚这样做的系统。我的想法是将具有当前版本号的paras应用于css和js文件的末尾: 两个问题:这会有效地打破缓存吗?由于参数表明这是动态内容,因此该参数会导致浏览器从不缓存该URL的响应吗? 问题答案: 参数表示查询字符串,因此浏览器将认为这是从到的新路径。因此导致它从文件而不是从缓存加载。如你所愿。 而且,浏览器将假定下次调用时
我有一个spring/hibernate项目,我试图通过ehcache和terracotta将二级缓存添加到hibernate。一切似乎都很好,我甚至可以在terracota控制台中看到我试图缓存的实体的条目。但根据数据库的统计数据和日志,根本没有缓存任何内容! 负载命中率是0%,负载统计也是0。我做错了什么? 这是我所做的,我通过maven添加了所需的罐子。 更改了我的Hibernate属性以启