使用 Service Worker 和推送通知做出反应

2024-03-22

一些初步考虑:

"react": "^16.8.2",
"react-scripts": "2.1.5"

我创建了一个新的反应应用程序,我需要实现推送通知。 下列的this https://developers.google.com/web/fundamentals/codelabs/push-notifications/在教程中,我能够在 5 分钟内启动并运行,但现在我必须在 React 应用程序中实施相同的策略(有点)。

我面临的问题是我能够订阅通知 API,但我不知道如何编辑service-worker.js文件添加一个事件监听器来捕获push event (Handle a Push Event谷歌指南中的章节)


使用 Create React App 自定义您的 Service Worker 是可能的,但可能相当困难且棘手。

CRA 使用 Workbox 开箱即用生成软件 https://developers.google.com/web/tools/workbox/modules/workbox-webpack-plugin#generatesw_plugin_1要生成的 webpack 插件service-worker.js文件,并且您不能向其中注入任何代码(您could https://medium.com/founding-ithaka/implementing-push-notifications-with-create-react-app-bf35cd25d870使用 CRA@1,自 CRA@2 起不再使用)

你有几种策略,我将从最简单的一种开始。

解决方案 1:提供您自己的 service-worker 文件

  • in src/index.js启用服务工作者:
    // serviceWorker.unregister()
    serviceWorker.register()
    
  • in src/serviceWorker.js注册您的自定义文件:

    // if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
    if ('serviceWorker' in navigator) {
    
    // const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
    const swUrl = `${process.env.PUBLIC_URL}/custom-service-worker.js`;
    

    运行开发服务器时必须更改名称,CRA 提供了一个mock https://github.com/facebook/create-react-app/issues/2272#issuecomment-302832432 for service-worker.js

  • in public/文件夹,创建custom-service-worker.js文件。 Webpack 会复制它as is in the build/ folder

Pros:快速、肮脏的胜利

Cons:您的自定义文件未使用 Webpack 处理(无导入),并且您必须自己实现网络缓存逻辑(假设您需要 PWA),因为您绕过了 Workbox 插件

解决方案 2:将代码附加到生成的 service-worker

有一个模块:cra-追加-sw https://github.com/bbhlondon/cra-append-sw。 您负责提供附加的代码。

Pros:设置简单,利用GenerateSW的优势

Cons:附加代码使用 Babel/Webpack 处理,但不使用 CRA 的配置(您可以选择退出)。仍然使用GenerateSW它为你处理网络缓存。不确定在本地开发时是否有效

解决方案 3:在自定义 service-worker 文件中使用 Workbox

  • 应用解决方案#1 的前 2 个步骤:更改src/index.js and src/serviceWorker.js

  • in src/文件夹,创建custom-service-worker.js文件。它将由 Webpack 处理,因此您可以使用 ES2016/TypeScript 语法并导入模块

    /* eslint no-restricted-globals: "off" */
    import * as precaching from 'workbox-precaching'
    // your own imports
    
    if (self.__precacheManifest) {
    precaching.precacheAndRoute(self.__precacheManifest)
    }
    
    // your own code
    
  • install 反应应用程序重新接线 https://github.com/timarney/react-app-rewired:

    • npm add --save-dev react-app-rewired
    • in package.json, in "scripts", 代替react-scripts with react-app-rewired
  • 调整 webpack 配置:创建config-overrides.js在根文件夹中:

    const WebpackBeforeBuildPlugin = require('before-build-webpack')
    const WorkboxWebpackPlugin = require('workbox-webpack-plugin')
    const path = require('path')
    const merge = require('lodash.merge')
    const fs = require('fs')
    
    // from https://www.viget.com/articles/run-multiple-webpack-configs-sequentially/
    class WaitPlugin extends WebpackBeforeBuildPlugin {
    constructor(file, interval = 100, timeout = 60e3) {
     super(function(stats, callback) {
       const start = Date.now()
    
       function poll() {
         if (fs.existsSync(file)) {
           callback()
         } else if (Date.now() - start > timeout) {
           throw Error(`Couldn't access ${file} within ${timeout}s`)
         } else {
           setTimeout(poll, interval)
         }
       }
       poll()
     })
    }
    }
    
    const swOutputName = 'custom-service-worker.js'
    const workerSource = path.resolve(__dirname, 'src', swOutputName)
    
    module.exports = {
    webpack: (config, env) => {
     // we need 2 webpack configurations:
     // 1- for the service worker file.
     //    it needs to be processed by webpack (to include 3rd party modules), and the output must be a
     //    plain, single file, not injected in the HTML page
     const swConfig = merge({}, config, {
       name: 'service worker',
       entry: workerSource,
       output: {
         filename: swOutputName
       },
       optimization: {
         splitChunks: false,
         runtimeChunk: false
       }
     })
     delete swConfig.plugins
    
     // 2- for the main application.
     //    we'll reuse configuration from create-react-app, without a specific Workbox configuration,
     //    so it could inject workbox-precache module and the computed manifest into the BUILT service-worker.js file.
     //    this require to WAIT for the first configuration to be finished
     if (env === 'production') {
       const builtWorkerPath = path.resolve(config.output.path, swOutputName)
       config.name = 'main-application'
       config.plugins.push(
         new WorkboxWebpackPlugin.InjectManifest({
           swSrc: builtWorkerPath,
           swDest: swOutputName
         }),
         new WaitPlugin(builtWorkerPath)
       )
     }
    
     // remove Workbox service-worker.js generator
     const removed = config.plugins.findIndex(
       ({ constructor: { name } }) => name === 'GenerateSW'
     )
     if (removed !== -1) {
       config.plugins.splice(removed, 1)
     } 
    
     const result = [swConfig, config]
     // compatibility hack for CRA's build script to support multiple configurations
     // https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/scripts/build.js#L119
     result.output = { publicPath: config.output.publicPath }
     return result
    }
    }
    

Pros:您可以在 service-worker 文件中使用 ES2016/TypeScript 代码。您仍然受益于 Workbox 网络缓存设施,并对其进行完全控制

Cons:复杂且脆弱,因为多重配置 hack。

我使用了最后一个解决方案,因为我需要来自 Workbox 的缓存代码和一些import在我的服务人员文件中。

反应应用程序重新接线工作箱 https://github.com/davejm/react-app-rewire-workbox可能有助于简化 Webpack 配置(主应用程序的配置)。有待测试。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Service Worker 和推送通知做出反应 的相关文章

随机推荐

  • 如何访问所有 URL 的 Selenium Python

    我试图访问所有显示的网址 但它首先访问而不是所有 谷歌搜索网址 browser get https www google co uk search q Rashmi oq Rashmi aqs chrome 69i57j69i60l3 68
  • 如何在 Windows 中查看正在执行的 java 程序的类路径和 jvm 参数

    在 nix 我只是这样做ps ef grep java查看正在执行的 java 程序的 jvm 参数和类路径 如何在 Windows 命令提示符中看到它 我想看看某些 jar 是否实际上位于正在运行的 weblogic 服务器的类路径中 从
  • Javascript for循环var“i”被视为字符串?

    我正在使用 Titanium 构建一些移动应用程序 我注意到这会产生我意想不到的结果 data a b c d for var i in data Ti API debug i 1 这将打印 01 11 12 13 这是 Titanium
  • 错误:java.lang.IllegalArgumentException:不支持额外示例

    如果我执行这个方法 tiff TiffImage getTiffImage rafa i false 然后就是通过下面的异常 谁能给我这个异常的任何解决方案 Exception Stack Trace java lang IllegalAr
  • 在 Objective C 中使用枚举类型作为属性

    我是一名资深的 NET 开发人员 这是我第一次涉足 Objective C 编程 我在处理枚举类型的属性时遇到困难 一些上下文 我有一个类标头和枚举 如下所示 typedef enum Open Unavailable Unknown Lo
  • RichTextBox 和特殊字符 C#

    我需要将 RTF 格式的文本放入 richtextbox 中 我尝试将其与richtextbox rtf TextString参数 但问题是该字符串具有特殊字符 并且 Richtextbox 无法正确显示所有字符串 我正在使用的字符串和代码
  • 字节码指令和处理器操作之间的关系

    Java 规范保证原始变量赋值始终是原子的 除了long和双types 相反 获取并添加 http en wikipedia org wiki Fetch and add对应著名的操作i 增量操作将是非原子的 因为会导致读取 修改 写入操作
  • null 对象的 FluentValidation 规则

    我一直在尝试弄清楚如何创建一个 FluentValidation 规则 在验证其属性之前检查它正在验证的对象的实例是否不为空 我宁愿将这个空验证封装在验证器中 而不是在调用代码中执行它 请参阅下面的示例代码 其中包含需要所需逻辑的注释 na
  • 如何对链表进行排序?

    我有一个链接列表 我想按特殊顺序对其进行排序 我尝试使用冒泡排序 由于我的结构 称为 Node 中有许多数据类型 因此我无法交换这些值 struct Node int data Node next Node int x data x nex
  • 桌面组合被禁用错误

    在我的 NET 4 0 上的 WPF 应用程序中 我让用户报告两个错误 这些错误似乎非常间歇性 我无法处理 下面 我发布了消息和堆栈跟踪的最上面一行 如果需要 我可以发布完整的堆栈跟踪 Message Desktop composition
  • Android:检查我的应用程序是否允许运行后台活动

    我有一个运行秒表服务的应用程序 并且我在前台运行该服务 我有一个显示计时器的通知 每秒更新一次 在我离开应用程序 30 秒后 通知停止更新 我发现原因是我的设备的电池优化 在我的应用程序的系统设置中 有一个电池优化部分 其中包含一个名为Al
  • WebSphere - 无法加载 Logmanager“org.apache.logging.log4j.jul.LogManager”

    我有一个运行 Web 应用程序的 WebSphere 应用程序服务器 我从 Eclipse 启动服务器 该应用程序中的主要日志记录框架是 log4j2 但也有一些使用 java util logging 的第三方库 我想将这些日志重定向到
  • 取消选中单选按钮[重复]

    这个问题在这里已经有答案了 该应用程序是一个步进音序器应用程序 具有 16 个无线电组 每组有 8 个按钮 它工作得很好 除非一个组选择了一个按钮 否则我无法将其关闭 除非我使用我创建的清除按钮来清除所有无线电组 我想添加的是一些代码 它表
  • Go:是否有可以在模板内使用的模数

    我的问题如标题所述 我正在尝试做类似的事情 range index element Products if index 4 0 div class row end div class columns small 3 product img
  • GitLab CI 启用 SCP

    我目前正在使用 GitLab com 上的共享运行器之一 是否可以设置 gitlab ci yaml 文件 以便构建可以将 SCP 文件从远程服务器传输到运行器上 我的目标是 SCP 文件 这些文件是我的构建所必需的依赖项 但它们不会在任何
  • C 数组中的指针递增

    我试图理解下面的程序 具体来说 定义cur name以及指针的递增cur age在 printf 语句中 cur age i 必须索引数组中的每个整数 但我希望它指向内存中的连续地址 而不是给定 int 的下一个整数是 4 个字节 即为什么
  • ASP.NET MVC:可用路由数据的 Uri

    我的问题很简单 我有一个 Uri 我想弄清楚它映射到哪个路由 这样我就可以对路由的各个部分进行一些检查 控制器 操作等 如何从 Uri 转到 RouteData 或 Route 根据 tvanfosson 的指导 我想出了一个可以满足我需要
  • 测试 Bash 函数返回值的正确方法是什么?

    我想测试 Bash 函数的返回值if像这样的声明 if func arg then 但我收到如下错误消息 conditional binary operator expected 这样做的正确方法是什么 是下面这个吗 if func arg
  • 字符串未被识别为有效的日期时间

    我收到此错误 字符串未被识别为有效的日期时间 代码如下 DateTimeOffSet dt new DateTimeOffset Convert ToDateTime DateTime Now ToString dd MM yyyy hh
  • 使用 Service Worker 和推送通知做出反应

    一些初步考虑 react 16 8 2 react scripts 2 1 5 我创建了一个新的反应应用程序 我需要实现推送通知 下列的this https developers google com web fundamentals co