我的 Service Worker 未按预期工作
我在我的 React-JS 项目中使用 Service Worker。我们的项目在两种浏览器和操作系统的组合下运行。
-
Chromium-102.0.5005.63 和 Windows 7
-
Chromium-49.0.2623.75 和 Windows XP
Service Worker 在 Chromium-102.0.5005.63 和 Windows 7 下运行良好,但在 Chromium-49.0.2623.75 和 Windows XP 下无法运行,并抛出以下错误:
Uncaught TypeError: Cannot read property of 'set' of undefined
ServiceWorker script evaluation failed
需要提及的几点:
1.
在
https
下加载项目 URL
2. Chromium-49.0.2623.75 支持规范中提到的 Service Worker
参考 1: https://caniuse.com/?search=service%20worker
参考2: https://blog.chromium.org/2016/02/chrome-49-beta-css-custom-properties.html
3.
在 Chromium-49.0.2623.75 中,在生产模式下运行时,navigator 中的“serviceWorker”返回
true
4.
browserslist
已更新,定义如下
package.json
"browserslist": {
"production": [
"> 0.04%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
当我使用
npx browserslist
时,我可以在列表中看到
chrome 49
。
5.
我没有在
service-worker.js
和
serviceWorkerRegistration.js
中使用任何
.set
更新 1:
无法读取未定义的“set”属性
是由 service-worker.js 中的以下方法引起的。
cacheKeyURL.searchParams
未定义。
var REVISION_SEARCH_PARAM = '__WB_REVISION__';
/**
* Converts a manifest entry into a versioned URL suitable for precaching.
*
* @param {Object|string} entry
* @return {string} A URL with versioning info.
*
* @private
* @memberof workbox-precaching
*/
function createCacheKey(entry) {
if (!entry) {
throw new WorkboxError_WorkboxError('add-to-cache-list-unexpected-type', {
entry: entry
});
} // If a precache manifest entry is a string, it's assumed to be a versioned
// URL, like '/app.abcd1234.js'. Return as-is.
if (typeof entry === 'string') {
var urlObject = new URL(entry, location.href);
return {
cacheKey: urlObject.href,
url: urlObject.href
};
}
var revision = entry.revision,
url = entry.url;
if (!url) {
throw new WorkboxError_WorkboxError('add-to-cache-list-unexpected-type', {
entry: entry
});
} // If there's just a URL and no revision, then it's also assumed to be a
// versioned URL.
if (!revision) {
var urlObject = new URL(url, location.href);
return {
cacheKey: urlObject.href,
url: urlObject.href
};
} // Otherwise, construct a properly versioned URL using the custom Workbox
// search parameter along with the revision info.
var cacheKeyURL = new URL(url, location.href);
var originalURL = new URL(url, location.href);
cacheKeyURL.searchParams.set(REVISION_SEARCH_PARAM, revision);
return {
cacheKey: cacheKeyURL.href,
url: originalURL.href
};
}
;// CONCATENATED MODULE: ./node_modules/workbox-precaching/utils/PrecacheInstallReportPlugin.js
您可以在此处查看 service-worker.js: https://drive.google.com/file/d/13bESH2QRG-y_s5WyZjX51FjP-_kC8vmC/view?usp=sharing
更新 2: 看来 URL 对象在 chrome 49 和 102 中的工作方式不同。 我手动将以下代码添加到 service-worker.js(在构建目录中),我不再收到“无法读取未定义的‘set’属性”错误,而是出现“ServiceWorker 安装失败”的情况,由于没有提供任何信息,我不知道为什么。
var cacheKeyURL = new URL(url, location.href);
var originalURL = new URL(url, location.href);
//This Part
if (!cacheKeyURL['searchParams']){
var urlParams = new URLSearchParams(location.search);
cacheKeyURL.searchParams = urlParams;
}
cacheKeyURL.searchParams.set(REVISION_SEARCH_PARAM, revision);
顺便问一下,我怎样才能将“//This Part”添加到原始 service-worker.js 中?
你能帮帮我吗?!
我回答得有点晚了,但我想扩展已接受的@M.H.的答案
来自 mozilla-docs 它指出
If a browser doesn't yet support the
URL() constructor
, you can access a URL object using the Window interface's URL property. Be sure to check to see if any of your target browsers require this to be prefixed.
并且您正在将
searchParams
作为
<URL_instance>['searchParams']
访问。这并不适用于所有情况,仅当您具有
key , value
对时才有效。
因此,最好使用
.
点运算符。
来自文档的更多内容:
URL() 和 searchParams() 在所有设备上都具有完全兼容性。
更改以下代码使用
key
获取
if (!cacheKeyURL['searchParams']){ 👈 instead of using the instance variable
var urlParams = new URLSearchParams(location.search);
cacheKeyURL.searchParams = urlParams;
}
使用
dot
运算符
if (!URL.prototype.searchParams) { 👈 try to access using prototype
URL.prototype.searchParams = new URLSearchParams();
}
希望它能有所帮助,并为接受的答案增加更多价值。
在 chrome 49 中,问题出在
URL
原型和
waitUntil()
上
添加以下代码修复 URL 问题:
if (!URL.prototype.searchParams) {
URL.prototype.searchParams = new URLSearchParams();
}
使用
async-wait-until
同步运行
waitUntil()
(而不是异步)