Mat*_* M. 3 reactjs service-worker create-react-app workbox
初步考虑:
"react": "^16.8.2",
"react-scripts": "2.1.5"
Run Code Online (Sandbox Code Playgroud)
我创建了一个新的react应用,我需要实现推送通知。在学习完本教程后,我能够在5分钟内启动并运行,但是现在我必须在react应用程序中实现相同的策略(kinda)。
我面临的问题是我可以订阅Notification API,但是我不确定如何编辑service-worker.js文件以添加事件侦听器来捕获push事件(Handle a Push EventGoogle指南中的章节)
Feu*_*ugy 11
可以使用Create React App自定义您的服务人员,但这可能非常困难且棘手。
CRA开箱即用,使用Workbox GenerateSW Webpack插件生成service-worker.js文件,并且您无法向其中注入任何代码(使用CRA @ 1可以,而自CRA @ 2起就不能再使用任何代码)
您有几种策略,我将从最简单的策略开始。
src/index.js启用服务工作者中:
// serviceWorker.unregister()
serviceWorker.register()
Run Code Online (Sandbox Code Playgroud)在src/serviceWorker.js注册您的自定义文件:
// if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
if ('serviceWorker' in navigator) {
Run Code Online (Sandbox Code Playgroud)
// const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
const swUrl = `${process.env.PUBLIC_URL}/custom-service-worker.js`;
Run Code Online (Sandbox Code Playgroud)
你必须运行开发服务器时更改名称的原因,CRA提供了一个 模拟的service-worker.js
在public/文件夹中,创建custom-service-worker.js文件。的WebPack会复制它的是中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语法并导入模块
/* eslint no-restricted-globals: "off" */
import * as precaching from 'workbox-precaching'
// your own imports
if (self.__precacheManifest) {
precaching.precacheAndRoute(self.__precacheManifest)
}
// your own code
Run Code Online (Sandbox Code Playgroud)npm add --save-dev react-app-rewiredpackage.json,在"scripts",替换react-scripts为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
}
}
Run Code Online (Sandbox Code Playgroud)优点:可以在service-worker文件中使用ES2016 / TypeScript代码。您仍然可以从Workbox网络缓存功能中受益,对其进行完全控制
缺点:复杂且脆弱,因为有多种配置。
我使用了最后一个解决方案,因为我既需要来自Workbox的缓存代码,又需要import我的服务工作者文件中的一些代码。
react-app- rewire - workbox可能有助于简化Webpack配置(用于主应用程序的配置)。有待测试。