registerServiceWorker.js

create-react-app 里面有这么一个文件: registerServiceWorker.js,刚开始只知道和刚出的 离线缓存 有关,具体都做了什么事情不清楚,于是网上找了些介绍,现在大致总结如下:

Service workers 本质上充当Web应用程序与浏览器之间的代理服务器,也可以在网络可用时作为浏览器和网络间的代理。它们旨在(除其他之外)使得能够创建有效的离线体验,拦截网络请求并基于网络是否可用以及更新的资源是否驻留在服务器上来采取适当的动作。他们还允许访问推送通知和后台同步API。

registerServiceWorker.js就是用来控制 Service workers 的注册和卸载,它可以在 生产环境 中,注册一个service worker来为本地缓存提供服务。这使得应用程序在随后的访问中加载更快,并且可以实现离线加载。

  • 源码介绍

该文件主要导出两个方法:

register():注册

export default function register() {
  //当前环境是生产环境并且浏览器支持serverWorker
  // The URL constructor is available in all browsers that support SW.
  if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
    //返回一个新的URL,作为生成静态文件夹的路径,下面说明...
    const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
    //如果静态文件和当前环境不在同一个域,注册没有意义,那就直接返回。
    if (publicUrl.origin !== window.location.origin) {
      return;
    }
    window.addEventListener('load', () => {
      //页面加载完成执行以下代码....
      const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
      if (isLocalhost) {
        // 如果是本地环境,调用checkValidServiceWorker进行注册
        checkValidServiceWorker(swUrl);
        // 注册成功后,打印信息
        navigator.serviceWorker.ready.then(() => {
          console.log(
            'This web app is being served cache-first by a service ' +
              'worker. To learn more, visit https://goo.gl/SC7cgQ'
          );
        });
      } else {
        // 如果不是本地环境(已经暴露在外网)仅仅只注册 service worker
        registerValidSW(swUrl);
      }
    });
  }
}

new URL(process.env.PUBLIC_URL, window.location),如果第一个参数是绝对路径,第二个参数忽略。如果第一个参数是相对路径,就会把第一个参数拼接到第二个参数后面。这里第一个参数是public目录的绝对路径。

unregister():取消注册

export function unregister() {
  //如果支持serviceWorker,并且处于就绪状态,那么调用其提供的取消注册方法
  if ('serviceWorker' in navigator) {
    navigator.serviceWorker.ready.then(registration => {
      registration.unregister();
    });
  }
}

isLocalhost:判断是不是本地环境

const isLocalhost = Boolean(
  window.location.hostname === 'localhost' ||
    // [::1] is the IPv6 localhost address.
    window.location.hostname === '[::1]' ||
    // 127.0.0.1/8 is considered localhost for IPv4.
    window.location.hostname.match(
      /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
    )
);

registerValidSW:注册有效serviceWorker

function registerValidSW(swUrl) {
  //注册有效的serviceWorker,然后使用提供的API进行操作
  navigator.serviceWorker
    .register(swUrl)
    .then(registration => {
      //如果内容有更新,就会自动进行安装
      registration.onupdatefound = () => {
        const installingWorker = registration.installing;
        installingWorker.onstatechange = () => {
          //安装之后判断安装状态进行提示
          if (installingWorker.state === 'installed') {
            if (navigator.serviceWorker.controller) {
              console.log('New content is available; please refresh.');
            } else {
              console.log('Content is cached for offline use.');
            }
          }
        };
      };
    })
    .catch(error => {
      console.error('Error during service worker registration:', error);
    });
}

checkValidServiceWorker:检测serviceWorker状态

function checkValidServiceWorker(swUrl) {
  // 向服务端申请资源
  fetch(swUrl)
    .then(response => {
      // 如果连接失败或者没有返回js
      if (
        response.status === 404 ||
        response.headers.get('content-type').indexOf('javascript') === -1
      ) {
        // 那么当 service worker 状态就绪的时候取消其注册状态
        navigator.serviceWorker.ready.then(registration => {
          registration.unregister().then(() => {
            //并且重新加载页面
            window.location.reload();
          });
        });
      } else {
        // 如果申请到资源,那么就调用 registerValidSW 方法来进行加载
        registerValidSW(swUrl);
      }
    })
    .catch(() => {
      console.log(
        'No internet connection found. App is running in offline mode.'
      );
    });
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容