reactjs - Webpack React Custom ServiceWorker 一切未定义
问题描述
在本文之后,我尝试将自定义服务工作者添加到我的 Create React App 项目中:
https://medium.com/@chinmaya.cp/custom-service-worker-in-cra-create-react-app-3b401d24b875
但是,在构建时,我从未定义所有内容的文件中得到了很长一段时间的错误sw-custom.js
(见下图):
这是我的文件:
react-build.js
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.
console.log('Building SW');
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,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();
sw-custom.js
if ('function' === typeof importScripts) {
importScripts(
'https://storage.googleapis.com/workbox-cdn/releases/5.1.2/workbox-sw.js'
);
// Global workbox
if (workbox) {
console.log('Workbox is loaded');
// Disable logging
workbox.setConfig({ debug: false });
//`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();
console.log('TESTTESTTEST');
});
// 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/(.*)'),
workbox.strategies.cacheFirst({
cacheName: 'googleapis',
plugins: [
new workbox.expiration.Plugin({
maxEntries: 30,
}),
],
})
);
// Image caching
workbox.routing.registerRoute(
/\.(?:png|gif|jpg|jpeg|svg)$/,
workbox.strategies.cacheFirst({
cacheName: 'images',
plugins: [
new workbox.expiration.Plugin({
maxEntries: 60,
maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days
}),
],
})
);
// JS, CSS caching
workbox.routing.registerRoute(
/\.(?:js|css)$/,
workbox.strategies.staleWhileRevalidate({
cacheName: 'static-resources',
plugins: [
new workbox.expiration.Plugin({
maxEntries: 60,
maxAgeSeconds: 20 * 24 * 60 * 60, // 20 Days
}),
],
})
);
} else {
console.error('Workbox could not be loaded. No offline support');
}
}
税务局sw.js
// register() is not called by default.
// 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 subsequent visits to a page, after all the
// existing tabs open on the page have been closed, since previously cached
// resources are updated in the background.
// To learn more about the benefits of this model and instructions on how to
// opt-in, read [link removed to post on SO]
// This optional code is used to register a service worker.
// register() is not called by default.
const isLocalhost = Boolean(
window.location.hostname === 'localhost' ||
// [::1] is the IPv6 localhost address.
window.location.hostname === '[::1]' ||
// 127.0.0.0/8 are considered localhost for IPv4.
window.location.hostname.match(
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
)
);
export function register(config) {
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
// The URL constructor is available in all browsers that support SW.
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
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/facebook/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. Let's check if a service worker still exists or not.
checkValidServiceWorker(swUrl, config);
// Add some additional logging to localhost, pointing developers to the
// service worker/PWA documentation.
navigator.serviceWorker.ready.then(() => {
console.log(
'This web app is being served cache-first by a service ' +
'worker. To learn more, visit x'
);
});
} else {
// Is not localhost. Just register service worker
registerValidSW(swUrl, config);
}
});
askNotificationPerms();
}
}
function registerValidSW(swUrl, config) {
navigator.serviceWorker
.register(swUrl)
.then((registration) => {
registration.onupdatefound = () => {
const installingWorker = registration.installing;
if (installingWorker == null) {
return;
}
installingWorker.onstatechange = () => {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
// At this point, the updated precached content has been fetched,
// but the previous service worker will still serve the older
// content until all client tabs are closed.
console.log(
'New content is available and will be used when all ' +
'tabs for this page are closed. See x'
);
// Execute callback
if (config && config.onUpdate) {
config.onUpdate(registration);
}
} 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.');
// Execute callback
if (config && config.onSuccess) {
config.onSuccess(registration);
}
}
}
};
};
})
.catch((error) => {
console.error('Error during service worker registration:', error);
});
}
function checkValidServiceWorker(swUrl, config) {
// Check if the service worker can be found. If it can't reload the page.
fetch(swUrl, {
headers: { 'Service-Worker': 'script' },
})
.then((response) => {
// Ensure service worker exists, and that we really are getting a JS file.
const contentType = response.headers.get('content-type');
if (
response.status === 404 ||
(contentType != null && contentType.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, config);
}
})
.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();
})
.catch((error) => {
console.error(error.message);
});
}
}
export function askNotificationPerms() {
if ('PushManager' in window) {
console.log('Push notifications are supported');
}
}
我猜 React 正在尝试编译自定义服务工作者文件,而它应该只被使用sw-build.js
非常感谢帮助:)
解决方案
推荐阅读
- django - Django - 服务器只能在一个浏览器中运行,直到我重新启动它
- java - 如何使用 ArrayList 将随机形状绘制到我的框架中?
- c - Gdb 没有“看到”我放置的断点,所以它贯穿整个程序
- java - 按位置组织 RecyclerView 中的视图
- excel - ThisWorkbooks.Sheets.Formula = 2 个单元格和一个数字之间的加法
- javascript - 是否可以在 websockets 中创建房间的概念?
- mongodb - 查看单个文档的数组时,mongoose .find() 没有结果
- c - 理解 C 中递归数据结构的构造
- c++ - 为什么命名右值引用是左值表达式?
- c - 我应该选择哪种方式进行 shell 命令解析?