PWA 中 Service Worker 的使用技巧总结

阅读时长 12 分钟读完

前言

随着网页的不断发展,PWA(Progressive Web Apps)已经形成了一种新的网页应用程序的范式,它具有像本地应用程序一样的功能和用户体验,同时又无需下载和安装。其中,Service Worker 是实现 PWA 的关键技术之一。

在这篇文章中,我们将详细介绍 Service Worker 技术,并给出一些实用的技巧和指导,帮助开发者更好地应用 Service Worker 技术。

什么是 Service Worker?

Service Worker 是一个运行在浏览器背后的 JavaScript工具,它能够拦截并处理来自浏览器的所有网络请求,包括页面、图片、资源等,从而可以实现离线缓存、消息推送等高级功能。

Service Worker 本质上是一个脚本,它可以在浏览器进程和网络中间建立一个缓存层,以便在没有网络连接时可以提供离线支持,同时也可以通过缓存加速网页加载。

Service Worker 的生命周期是完全独立于网页的,它可以在网页关闭后继续运行,并保持和服务器的连接。这意味着 Service Worker 可以在后台执行一些任务,例如预载入资源、更新缓存等。

PWA 中的 Service Worker

PWA 中通过 Service Worker 实现以下功能:

  • 离线缓存:在没有网络连接时,通过 Service Worker 技术可以让网页依然可以访问,仅仅只是没有实时数据的更新。对于一些需要频繁访问的数据可以通过离线缓存减少重复请求,提高网页访问效率。
  • 快速加载:通过 Service Worker 技术可以将页面的资源预缓存,网页打开速度会得到很大的提升(如像素级预缓存)。
  • 消息推送:通过 Service Worker 技术可以将消息推送给用户,相比传统的安卓 APP,可以获得更好的体验,同时还可以节省用户的流量。
  • 后台任务:Service Worker 一旦被安装后就可以在后台周期性地执行任务,如资源的更新、数据预载等操作。

Service Worker 基本用法

下面我们来介绍 Service Worker 的基本用法,首先需要对 Service Worker 进行注册。一旦 Service Worker 被注册,当满足某些条件时,浏览器就会使用其运行时。

-- -------------------- ---- -------
-- -- ------- ------
-- ---------------- -- ---------- -
  ------------------------------------------ - ------ --- --
    ------------------ -- -
      -------------------- ------ --------
    -------------- -- -
      -------------------- ------ ------- -------
    ---
-

注册代码里的 sw.js 就是我们定义的 Service Worker 脚本,这里也可以通过作用域的方式来限制 Service Worker 的路径,提高效率和安全性。

Service Worker 脚本有以下两个生命周期事件:

  • install:当 Service Worker 第一次安装时触发的事件,通常用于缓存静态资源和其他必要的资源。
  • activate:当 Service Worker 激活时触发的事件,通常用于清理缓存、处理版本升级等。

下面是一个简单的 Service Worker 脚本示例:

-- -------------------- ---- -------
-- ------
----- ----------- - -
  ----
  --------------
  -----------------
  -------------
  -----------------
  -------------------
--

-- ----
-------------------------------- ----- -- -
  ----------------
    -----------------
      ----------- -- -
        -- ----
        ------ --------------------------
      --
  --
---

-- ----
--------------------------------- ----- -- -
  ----------------
    ----------------------------- -- -
      ------ ------------
        --------------------------- -- -
          -- --------
          ------ --------- --- -----
        ---------------- -- -
          ------ -------------------------
        --
      -
    --
  --
---

-- ---------
------------------------------ ----- -- -
  ------------------
    ---------------------------- -- -
      ------ ---------------------------------------- -- -
        -- ----------
        -- ---------- -
          ------ ---------
        -
        -- ---------------
        ------ ---------------------------------- -- -
          ------------------------ ------------------
          ------ ---------
        ---
      --
    --
  --
---

在这个脚本中,我们将 v1 版本的资源进行了缓存,并在缓存命中时返回缓存中的数据。如果缓存没有命中,则向网络发送请求,并将从网络获取到的资源放入缓存中。

Service Worker 高级技巧

清除旧版本的缓存

每次更新 Service Worker 代码时,都需要清除旧版本的缓存。这个问题可以通过在激活事件中实现:

-- -------------------- ---- -------
--------------------------------- ----- -- -
  ----------------
    ----------------------------- -- -
      ------ ------------
        --------------------------- -- -
          -- --------
          ------ --------- --- -----
        ---------------- -- -
          ------ -------------------------
        --
      --
    --
  --
---

绕过 Service Worker

如果需要在特定的情况下绕过 Service Worker,可以使用 fetch 事件来完成这个需求。例如,在访问特定 URL 时需要禁用缓存,可以使用以下代码:

-- -------------------- ---- -------
------------------------------ ----- -- -
  -- -------------------------------------------- -
    ------ ---------------------
  -
  -- ---- ------- ------ ----
  ------------------
    ---------------------------- -- -
      ------ ---------------------------------------- -- -
        -- ---------- -
          ------ ---------
        -
        ------ ---------------------------------- -- -
          ------------------------ ------------------
          ------ ---------
        ---
      --
    --
  --
---

如果请求 URL 包含 /disable-sw/,就直接使用 fetch 去获取。

更新资源缓存

有些资源是需要在更新后马上生效的,例如首页的新闻列表等。这时需要立即清除缓存并重新获取数据,可以这样来实现:

-- -------------------- ---- -------
-- ------
----- ------- - --- --------------------------------

-- -- ------- ------
-- ---------------- -- ---------- -
  ------------------------------------------ - ------ --- -------------------- -- -
    -------------------------------------------- -- -- -
      -- ----- ------- ------
      ----- --------- - ------------------------
      ----------------------------------------- -- -- -
        -- --- ------- ------ ----
        -- ---------------- --- ------------ -
          -- ------------------------------------ -
            -- ----- ------- ------
            --------------------- ----- ----------- ---
          -
        -
      ---
    ---
  ---
-

-- ------- ------- ------ ----
----------------------------------- ----- -- -
  -- ---------------- --- ------------ -
    -- ----- ------- ------------------
    ----- ------ - ---------------------------------
    ---------------- - -
      ---- ----------------------------------
      ---- ----------------
        ------- ----------------------------
        ------- ------------------------------
      --------
    ----------------------------------
    -------------------
    --------------------------------------------------------- -- -- -
      -- ------
      ------------------
    ---
    --------------------------------------------------------- -- -- -
      -- -----
      ----------------------------------
    ---
  -
---

-- ------
-------- ------------ -
  ----------------------------- -- -
    ------ ------------
      ------------------------ -- -
        ------ -------------------------
      --
    --
  ---
-

在这段代码中,我们使用 BroadcastChannel 来建立页面和 Service Worker 之间的通信通道,并通过监听 sw-update 事件来控制页面的更新和响应。

在 Service Worker 中可以使用以下代码让发送消息到页面:

在页面中可以通过 BroadcastChannelmessage 事件来接受并响应消息:

-- -------------------- ---- -------
----- ------- - --- --------------------------------
----------------------------------- ----- -- -
  -- ---------------- --- ------------ -
    -- ----- ------- ------------------
    ----- ------ - ---------------------------------
    ---------------- - -
      ---- ----------------------------------
      ---- ----------------
        ------- ----------------------------
        ------- ------------------------------
      --------
    ----------------------------------
    -------------------
    --------------------------------------------------------- -- -- -
      -- ------
      ------------------
    ---
    --------------------------------------------------------- -- -- -
      -- -----
      ----------------------------------
    ---
  -
---

通过这种方式,我们可以在没有新版本的缓存时的使用老的 Service Worker,同时可以在有新版本的时候立即更新从而避免缓存旧版数据的问题。

结论

在文章中,我们介绍了 PWA 中的 Service Worker 技术,并给出了相应的示例代码和指导,希望可以帮助大家更好地理解和应用 Service Worker 技术,从而构建出更好的 PWA 应用程序。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/6710aec26fbd6f3cf2f5b3be

纠错
反馈