← 中文资源

简体中文版本

Service Worker 生命周期

Service Worker 按 scope 经历安装、等待、激活三个阶段:新版本只有在旧客户端全部关闭后才接管,这解释了更新为何“慢一个会话”。

阅读英文原文

概念定义

一个 service worker 控制一个 scope,同一 scope 同时只有一个活跃版本。部署更新时,字节不同的脚本触发新 worker 安装,但它必须等旧 worker 释放控制权。生命周期是浏览器在保护已打开页面不被会话中途换版本。

工作机制

注册取回脚本;install 执行预缓存;若已有 worker 控制着打开的客户端,新 worker 进入 waiting;该计数归零时 activate 触发,旧缓存通常在此清理。浏览器在导航与推送时检查脚本更新,并遵循 worker 脚本自身的缓存头。

使用场景

任何带预缓存的可部署应用都需要更新策略:发现 waiting worker 时提示用户、经同意后刷新;或给缓存做版本化并在 activate 清理。调试应使用 devtools 的更新循环,unregister 会掩盖真实世界行为。

常见误区

会话中途 skipWaiting 加 clients.claim 可能让新 worker 面对旧版本预缓存的懒加载分片。worker 脚本若被长缓存,更新检查会一直拿到旧字节。注册路径决定 scope,放在深层路径的 worker 会静默控制不到站点根。

代码示例

public class StringBuilderManipulation {

    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder(64);

        sb.append("Hello");
        sb.append(" ");
        sb.append("World");
        System.out.println("Built: " + sb);

        sb.insert(5, " Java");
        System.out.println("After insert: " + sb);

        sb.delete(5, 10);
        System.out.println("After delete: " + sb);

        sb.replace(0, 5, "Hi");
        System.out.println("After replace: " + sb);

        sb.reverse();
        System.out.println("Reversed: " + sb);

        String csv = String.join(", ",
            "Apple", "Banana", "Cherry", "Date");
        System.out.println("CSV: " + csv);

        String formatted = String.format(
            "Name: %s, Age: %d, Score: %.2f",
            "Alice", 30, 95.5
        );
        System.out.println(formatted);

        String stripped = "  padded  ".strip();
        System.out.println("Stripped: '" + stripped + "'");
    }
}