我有一个创建反应应用程序项目,该项目使用反应路由器和工作箱作为服务人员。
它由 IIS 托管,为了使页面重新加载工作,我已将此 web.config 添加到我的公共目录中。
<?xml version="1.0"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="React Routes" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
这意味着它将始终从根(基本入口点)为应用程序提供服务。这部分效果很好。这个解决方案是必需的,因为我使用BrowserRouter(反应路由器)来获取漂亮的 url。
但是,我也激活了服务人员。我使用工作箱来帮助服务人员。
这是我的工作箱构建脚本
const workboxBuild = require("workbox-build");
const buildSW = () => {
// The build is expected to fail if the
// sw install rules couldn't be generated.
// Add a catch block to handle this scenario.
return workboxBuild
.injectManifest({
swSrc: "src/sw-custom.js", // custom sw rule
swDest: "build/sw.js", // sw output file (auto-generated
globDirectory: "build",
globPatterns: ["**/*.{js,css,html,jpg,jpeg,gif,png,svg}"],
maximumFileSizeToCacheInBytes: 5 * 1024 * 1024,
})
.then(({ count, size, warnings }) => {
warnings.forEach(console.warn);
console.info(`${count} files will be precached,
totaling ${size / (1024 * 1024)} MBs.`);
});
};
buildSW();
最后是我的工作箱代码
if ("function" === typeof importScripts) {
importScripts(
"https://storage.googleapis.com/workbox-cdn/releases/5.1.3/workbox-sw.js"
);
// Global workbox
if (workbox) {
console.log("Workbox is loaded");
//`generateSW` and `generateSWString` provide the option
// to force update an exiting service worker.
// Since we're using `injectManifest` to build SW,
// manually overriding the skipWaiting();
self.addEventListener("install", (event) => {
// self.skipWaiting();
// window.location.reload();
});
self.addEventListener('message', (event) => {
if (event.data && event.data.type === 'SKIP_WAITING') {
self.skipWaiting();
}
});
// Manual injection point for manifest files.
// All assets under build/ and 5MB sizes are precached.
workbox.precaching.precacheAndRoute([]);
// Font caching
workbox.routing.registerRoute(
new RegExp("https://fonts.(?:.googlepis|gstatic).com/(.*)"),
new workbox.strategies.CacheFirst({
cacheName: "googleapis",
plugins: [
new workbox.expiration.ExpirationPlugin({
maxEntries: 100,
maxAgeSeconds: 60 * 24 * 60 * 60, // 60 Days
}),
],
})
);
// Image caching
workbox.routing.registerRoute(
/\.(?:png|gif|jpg|jpeg|svg)$/,
new workbox.strategies.CacheFirst({
cacheName: "images",
plugins: [
new workbox.expiration.ExpirationPlugin({
maxEntries: 1000,
maxAgeSeconds: 60 * 24 * 60 * 60, // 60 Days
}),
],
})
);
// JS, CSS caching
workbox.routing.registerRoute(
/\.(?:js|css)$/,
new workbox.strategies.StaleWhileRevalidate({
cacheName: "static-resources",
plugins: [
new workbox.expiration.ExpirationPlugin({
maxEntries: 100,
maxAgeSeconds: 60 * 24 * 60 * 60, // 60 Days
}),
],
})
);
} else {
console.error("Workbox could not be loaded. No offline support");
}
}
现在是实际问题: 当我离线时,如果我在起始页(url:/)上重新加载页面仍然可以正常工作但是,如果我在 /foo/bar 之类的子页面上并重新加载页面我只是在 chrome 中获取“页面离线”。无论我在哪个 url 上使用 react 路由器,如何让我的 service worker 离线工作?