最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 基于 Service Worker 进行多页面通信 | 项目复盘

    正文概述 掘金(一个卷er)   2021-03-21   588

    一、项目简介

    基于 Service Worker 实现在浏览器多页面(多标签页之间)进行消息同步。

    二、项目背景

    我们知道,在一个大型的后台管理项目中,我们往往需要管理复杂的角色权限逻辑、管理用户的个性化配置,对于数据展示的一致性有较高的要求。

    例如,当用户同时打开多个浏览器页面进行浏览和操作时,由于数据不能在多页面同步,可能会导致用户的误操作或者误解。

    为了减少用户的误操作和优化用户的使用体验,我们可以基于 Service Worker 进行多页面的消息同步,使得操作一个页面可以同时刷新多个页面的信息。

    三、实践过程

    基本原理

    Service worker 也是 worker 的一种,也就是说,它运行在 worker 上下文中,不能直接访问 DOM。Service worker 的生命周期与页面无关,它可以自动控制指定 域/请求路径 下的所有客户端页面。它的生命周期主要分为以下几个过程: 基于 Service Worker 进行多页面通信 | 项目复盘

    安装并调试

    在 React 项目中,可以使用 create-react-app 的 pwa 模板

    $ npx create-react-app my-app --template cra-template-pwa
    $ npx create-react-app my-app-ts --template cra-template-pwa-typescript
    

    安装成功,会在 src 目录下生成 service-worker.jsserviceWorkerRegistration.js 两个文件。

    为了在本地进行测试,我们先改写下默认的 serviceWorkerRegistration.js文件 基于 Service Worker 进行多页面通信 | 项目复盘 webpack.config.js 中使用 WorkboxWebpackPlugin 来打包 service-worker.js 文件,这里我们同样把生产环境的判断移除。 基于 Service Worker 进行多页面通信 | 项目复盘index.js 中安装注册 基于 Service Worker 进行多页面通信 | 项目复盘

    如果不想使用 cra 的模板来搭建,其实也很简单,不管使用 webpack 打包或者其他工具打包,我们只要保证最终的 service-worker.js 文件可以在项目的指定路径下直接访问即可。在 webpack 中我们可以借助 WorkboxWebpackPlugin 或者 CopyWebpackPlugin 来处理。

    运行 yarn start --watch,我们看到 Service worker 已经成功注册并激活了。

    基于 Service Worker 进行多页面通信 | 项目复盘

    在控制台的 Application 面板,我们可以看到当前域名下注册的文件,以及当前多少窗口/客户端处于Service worker 的控制下 基于 Service Worker 进行多页面通信 | 项目复盘

    通信

    接下来,我们来看看在具体的代码中,我们如何实现多页面的消息通知。

    改写 service-worker.js 文件

    /* eslint-disable no-restricted-globals */
    import { clientsClaim } from "workbox-core";
    import { precacheAndRoute } from "workbox-precaching";
    
    clientsClaim();
    precacheAndRoute(self.__WB_MANIFEST);
    
    // 监听来自网页客户端的消息
    self.addEventListener("message", (event) => {
      if (event.data && event.data.type === "SKIP_WAITING") {
        self.skipWaiting();
      }
      var promise = self.clients.matchAll().then(function (clientList) {
        var senderID = event.source.id;
        // 消息不传递给发送者本身
        clientList.forEach(function (client) {
          if (client.id === senderID) {
            return;
          }
          client.postMessage({
            client: senderID,
            message: event.data,
          });
        });
      });
      if (event.waitUntil) {
        event.waitUntil(promise);
      }
    });
    

    在页面中监听

    const useNotification = () => {
      const [data, setData] = useState({});
      useEffect(() => {
        if ("serviceWorker" in navigator) {
          let listener = (event) => {
            const clientId = event.data.client;
            console.log(`receive message from ${clientId}`);
            setData(event.data);
          };
          navigator.serviceWorker.addEventListener("message", listener);
          return () => {
            navigator.serviceWorker.removeEventListener("message", listener);
          };
        }
      }, []);
      const postMessage = useCallback((message) => {
        if ("serviceWorker" in navigator) {
          navigator.serviceWorker.controller.postMessage(message);
        }
      }, []);
      return [data, postMessage];
    };
    

    实现效果

    基于 Service Worker 进行多页面通信 | 项目复盘

    四、总结思考

    本文只是通过一个简单的 Demo 来梳理 Service worker 进行通信的基本步骤,更加复杂的应用只需要在这个 Demo 上进一步拓展即可。

    基于 Service Worker 我们还可以实现很多功能,比如后台同步、资源缓存、请求拦截等。

    参考 Service Worker Cookbook

    本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情


    起源地下载网 » 基于 Service Worker 进行多页面通信 | 项目复盘

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元