初步考虑:
"react": "^16.8.2", "react-scripts": "2.1.5"
我创建了一个新的react应用,我需要实现推送通知。遵循本教程,我能够在5分钟内启动并运行,但是现在我必须在React应用程序中实施相同的策略(kinda)。
我面临的问题是我可以订阅Notification API,但是我不确定如何编辑service- worker.js文件以添加事件侦听器以捕获push事件(Handle a Push EventGoogle指南中的章节)
service- worker.js
push
Handle a Push Event
可以使用Create React App自定义您的服务人员,但这可能非常困难且棘手。
开箱即用,CRA使用针线GenerateSW的WebPack插件生成service- worker.js的文件,你不能注入任何代码,它(你可能与CRA @ 1,不宜与CRA以来@ 2更多)
您有几种策略,我将从最简单的策略开始。
src/index.js
// serviceWorker.unregister() serviceWorker.register()
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提供了一个 模拟的service-worker.js
service-worker.js
public/
custom-service-worker.js
build/
优点 :快速,肮脏的胜利
缺点 :您的自定义文件未使用Webpack处理(没有导入),并且由于绕过Workbox插件,您必须自己实现网络缓存逻辑(假设您需要PWA)
有一个模块:cra-append-sw。您负责提供附加的代码。
优点 :易于设置,可利用GenerateSW
缺点 :附加的代码使用Babel /Webpack处理,但不使用CRA的配置(您可以选择退出)。仍然使用GenerateSW为您处理网络缓存。不确定在本地开发时是否有效
应用解决方案1的前两个步骤:更改src/index.js并src/serviceWorker.js
在src/文件夹中,创建custom-service-worker.js文件。它将由Webpack处理,因此您可以使用ES2016 / TypeScript语法并导入模块
src/
/* eslint no-restricted-globals: "off" */ import * as precaching from 'workbox-precaching' // your own imports if (self.__precacheManifest) { precaching.precacheAndRoute(self.__precacheManifest) } // your own code
安装react-app-rewire:
npm add --save-dev react-app-rewired
package.json
"scripts"
react-scripts
react-app-rewired
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 } }
优点 :您可以在service-worker文件中使用ES2016 / TypeScript代码。您仍然可以从Workbox网络缓存功能中受益,对其进行完全控制
缺点 :复杂且脆弱,因为有多种配置。
我使用了最后一个解决方案,因为我既需要来自Workbox的缓存代码,也需要import我的Service Worker文件中的一些代码。
import
react-app- rewire - workbox可能有助于简化Webpack的配置(用于主应用程序的配置)。有待测试。