[英]exclude index.html from service worker cache in create-react-app
I have a reactJs app using create-react-app .我有一个使用create-react-app的reactJs应用程序。 The app uses service-worker and other PWA features but somehow I am seeing that despite updating the website or deploying a new build, chrome always picks index.html
from service worker and does not make a network call at all.该应用程序使用service-worker和其他 PWA 功能,但不知何故,尽管更新了网站或部署了新版本,chrome 总是从 service worker 中选择index.html
并且根本不进行网络调用。
I think caching the index.html using the service worker is the issue but have not been able to exclude it from getting cached, I did check a few questions on SO and issues on github but could not get a fix for this.我认为使用服务工作者缓存 index.html 是问题,但无法将其排除在缓存之外,我确实检查了一些关于 SO 的问题和 github 上的问题,但无法解决此问题。
I am using the default service-worker registration我正在使用默认的 service-worker 注册
registerServiceWorker.js registerServiceWorker.js
// In production, we register a service worker to serve assets from local cache.
// This lets the app load faster on subsequent visits in production, and gives
// it offline capabilities. However, it also means that developers (and users)
// will only see deployed updates on the "N+1" visit to a page, since previously
// cached resources are updated in the background.
// This link also includes instructions on opting out of this behavior.
const isLocalhost = Boolean(
window.location.hostname === 'localhost' ||
// [::1] is the IPv6 localhost address.
window.location.hostname === '[::1]' ||
// 127.0.0.1/8 is considered localhost for IPv4.
window.location.hostname.match(
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
)
);
export default function register() {
if (/*process.env.NODE_ENV === 'production' &&*/ 'serviceWorker' in navigator) {
// alert('found' + process.env.NODE_ENV);
// The URL constructor is available in all browsers that support SW.
const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
if (publicUrl.origin !== window.location.origin) {
// Our service worker won't work if PUBLIC_URL is on a different origin
// from what our page is served on. This might happen if a CDN is used to
// serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374
return;
}
window.addEventListener('load', () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
if (isLocalhost) {
// This is running on localhost. Lets check if a service worker still exists or not.
checkValidServiceWorker(swUrl);
} else {
// Is not local host. Just register service worker
registerValidSW(swUrl);
}
});
} else {
//alert('not found' + process.env.NODE_ENV);
}
}
function registerValidSW(swUrl) {
navigator.serviceWorker
.register(swUrl)
.then(registration => {
registration.onupdatefound = () => {
const installingWorker = registration.installing;
installingWorker.onstatechange = () => {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
// At this point, the old content will have been purged and
// the fresh content will have been added to the cache.
// It's the perfect time to display a "New content is
// available; please refresh." message in your web app.
console.log('New content is available; please refresh.');
} else {
// At this point, everything has been precached.
// It's the perfect time to display a
// "Content is cached for offline use." message.
console.log('Content is cached for offline use.');
}
}
};
};
})
.catch(error => {
console.error('Error during service worker registration:', error);
});
}
function checkValidServiceWorker(swUrl) {
// Check if the service worker can be found. If it can't reload the page.
fetch(swUrl)
.then(response => {
// Ensure service worker exists, and that we really are getting a JS file.
if (
response.status === 404 ||
response.headers.get('Content-Type').indexOf('javascript') === -1
) {
// No service worker found. Probably a different app. Reload the page.
navigator.serviceWorker.ready.then(registration => {
registration.unregister().then(() => {
window.location.reload();
});
});
} else {
// Service worker found. Proceed as normal.
registerValidSW(swUrl);
}
})
.catch(() => {
console.log(
'No internet connection found. App is running in offline mode.'
);
});
}
export function unregister() {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready.then(registration => {
registration.unregister();
});
}
}
Please help.请帮忙。
After trying multiple options, the one that worked best was not I was really willing to implement but could not find anything better. 在尝试了多种选择之后,最有效的选择不是我真的不愿意实施,但却找不到更好的选择。
From the service-worker.js
file remove below lines 从service-worker.js
文件中删除以下行
workbox.routing.registerNavigationRoute("/index.html", {
blacklist: [/^\/_/,/\/[^\/]+\.[^\/]+$/],
});
This will not cache index.html
and try to pull it every time from the server, though this does not sound best but does the trick. 尽管听起来并不是最好的方法,但它不会缓存index.html
并尝试每次从服务器将其拉出。
If you have ejected from create-react-app you can go into /config/webpack.config.js and change the default arguments for GenerateSW() to the following: 如果您从create-react-app中退出,则可以进入/config/webpack.config.js并将GenerateSW()的默认参数更改为以下内容:
new WorkboxWebpackPlugin.GenerateSW({
clientsClaim: true,
exclude: [/\.map$/, /asset-manifest\.json$/, /index.html/],
importWorkboxFrom: "cdn",
navigateFallbackBlacklist: [
// Exclude URLs starting with /_, as they're likely an API call
new RegExp("^/_"),
// Exclude URLs containing a dot, as they're likely a resource in
// public/ and not a SPA route
new RegExp("/[^/]+\\.[^/]+$")
]
This way you don't have to manually change your serviceworker.js after every building. 这样,您不必在每次构建后都手动更改serviceworker.js。
As you probably found out, the blacklist
and navigateFallbackBlacklist
options are not allowed with InjectManifest.正如您可能发现的那样,InjectManifest 不允许使用blacklist
和navigateFallbackBlacklist
选项。
My solution was to make a index-shell.html which can be cached and keep the original index.html out of the cache.我的解决方案是制作一个可以缓存的 index-shell.html 并将原始 index.html 保留在缓存之外。
new InjectManifest({
include: [
/index-shell\.html$/,
],
exclude: [
/index\.html$/,
],
modifyURLPrefix: {'/public/': '/'}, // solved my routing issues with publicPath and what not...
...
})
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.