我看到事件侦听器被添加到registration
对象中.
但是像"激活"、"推送"和"获取"这样的事件应该在service worker本身内处理,而不是在注册对象上处理.
这意味着这将是not%的工作:
function registerValidSW(swUrl, config) {
navigator.serviceWorker.register(swUrl).then((registration) => {
// That gets logged
console.log("? ~ file: serviceWorker.js:168 ~ Registered service worker:");
console.log(
"? ~ file: serviceWorker.js:168 ~ navigator.serviceWorker.register ~ registration:",
registration
);
// Incorrect: Adding 'activate' event listener to registration object
registration.addEventListener("activate", function (event) {
// That does not get logged
console.log("? ~ file: Added activate event listener to registration");
});
// Incorrect: Adding 'push' event listener to registration object
registration.addEventListener("push", async function (event) {
// That does not get logged
console.log("? ~ file: Added push event listener to registration");
});
// Incorrect: Adding 'fetch' event listener to registration object
registration.addEventListener("fetch", (event) => {
// That does not get logged
console.log("? ~ file: Added fetch event listener to fetch");
});
});
}
服务工作者文件是在服务工作者的上下文中运行的单独的JavaScript文件,而不是在页面的主线程中运行.
在页面的主线程中(例如,在serviceWorker.js
文件中),注册服务工作者,就像您已经在做的那样.该部分负责注册服务工作者文件,不处理"激活"、"推送"和"获取"等服务工作者事件.
在服务工作者文件(例如,service-worker.js
)中,您将为"Activate"、"Push"和"Fetch"添加事件侦听器.该文件应该与navigator.serviceWorker.register(swUrl)
调用注册的文件相同.
例如:
// The 'activate' event
self.addEventListener('activate', event => {
console.log("? ~ Service Worker activated!");
// Your activation logic here
});
// The 'push' event
self.addEventListener('push', event => {
console.log("? ~ Push event received!");
// Your push logic here
});
// The 'fetch' event
self.addEventListener('fetch', event => {
console.log("? ~ Fetch event triggered!");
// Your fetch logic here
});
该代码应该放在不使用ES6导入或其他页面级代码的单独的JavaScript文件中,因为它将在服务工作者上下文中运行.
然后,您可以判断在触发相应事件时是否看到这些日志(log)消息.
我没有service-worker.js
%的档案.
尽管如此,这是用于登记的swUrl
:const swUrl = ${process.env.PUBLIC_URL}/service-worker.js; registerValidSW(swUrl, config);
Should I add it somewhere or something?
I'm also confused how come it doesn't exist, and the PWA setup works correct.
I see the "Create React App" (CRA) feature should automatically generate a service worker file for you when you opt into using a service worker (for example, by using the cra-template-pwa
template or manually configuring it).
In a standard CRA setup, you don't have to write your own service worker file, but it does indeed exist and is usually generated during the build process.
由于在Create Reaction App(CRA)项目中生成的服务工作者文件通常是构建过程的一部分,并且每次构建项目时它都会被覆盖,这意味着如果您直接修改它,然后运行构建,...您所做的更改将丢失.
相反,您可以try 运行npm run eject
(或yarn eject
),这将公开所有配置文件,包括服务工作者文件.这允许您直接修改它,但缺点是必须自己管理整个构建配置.
另一种方法是创建您自己的自定义服务工作者文件并将其包含在您的项目中.您可以像生成的服务工作者一样注册它.确保在这个定制服务工作者中自己处理所有必要的缓存和其他PWA功能.
例如,要创建和注册自定义服务工作者(custom-sw.js
):
// custom-sw.js (Your custom service worker file)
self.addEventListener('activate', event => {
console.log("Custom service worker activated!");
});
self.addEventListener('push', event => {
console.log("Custom push event received!");
});
self.addEventListener('fetch', event => {
console.log("Custom fetch event triggered!");
});
然后,在您的serviceWorker.js
文件中,您可以将注册URL更改为指向您的定制服务人员:
const swUrl = `${process.env.PUBLIC_URL}/custom-sw.js`;
registerValidSW(swUrl, config);
确保从正确的位置提供自定义服务工作者文件.您可能需要更新生成配置或将文件放在public
文件夹中,具体取决于项目的 struct .
Or you can use Workbox: a set of libraries that can make service worker development easier, and it's often used with CRA to create custom service worker logic.
See "Making a Progressive Web App"
从Create Reaction App 4开始,您可以将src/service-worker.js文件添加到您的项目中,以使用对Workbox的InjectManifest插件的内置支持,该插件将编译您的服务工作器并向其中注入要预缓存的URL列表.
OP在 comments 中提到了页面"How to add event listeners to create-react-app default sw.js file",并补充道:
这要简单得多.您只需在构建完成后将监听程序附加到服务工作者文件
该方法有效地允许您将自定义代码注入到生成的服务工作者文件中,而不必直接修改它,保留了CRA构建过程的优势,同时仍然允许您灵活地添加自定义逻辑.
您可以在一个单独的文件(如sw-epilog.js
)中编写您的自定义服务工作者代码.这可能包括您想要附加到生成的服务工作进程中的事件侦听器或其他代码.
在构建过程完成后,您可以使用package.json
文件中的脚本将此自定义代码文件连接到生成的服务工作者文件的末尾.shell 命令cat src/sw-epilog.js >> build/service-worker.js
中的>>
操作符通过获取sw-epilog.js
的内容并将其附加到service-worker.js
的末尾来实现这一点.
您可以在生成过程中包含此串联步骤,以便在每次生成项目时自动执行.