也许你并不需要 Service Worker
You might not need a service worker

原始链接: https://www.jayfreestone.com/writing/you-might-not-need-a-service-worker/

这份摘要探讨了 Service Workers 的实际效用,指出尽管它们功能强大,但往往被过度用于本可通过更简单的原生方案解决的问题。 常见的陷阱包括因糟糕的缓存策略而导致用户陷入应用故障状态的“自毁行为”。作者评估了几个常见的应用场景: * **Slack 的瞬时启动:** 虽然令人印象深刻,但作者认为,使用内容哈希(content hashing)和不可变标头(immutable headers)的标准 HTTP 缓存是防止冗余资源下载更简单、更有效的方法。 * **版本偏差(Version skew):** 为防止 404 错误而缓存整个应用会导致资源包臃肿且效率低下。作者建议只需在服务器上保留旧资源更长时间即可,因为存储成本微不足道。 * **清单重写(Manifest rewriting):** 诸如 Mux 所使用的逻辑,理想情况下应在服务器端(例如在边缘计算节点)处理,而非在容易产生竞争条件的客户端进行。 * **Partytown/MSW:** 这些工具通常将 Service Workers 用作备选方案或开发模拟,而非核心架构需求。 最终,作者得出结论:除非明确需要离线支持、推送通知或后台同步,否则 Service Workers 很少是最佳解决方案。

Hacker News 最新 | 过往 | 评论 | 提问 | 展示 | 招聘 | 投稿 | 登录 你可能并不需要 Service Worker (jayfreestone.com) 5 分 | Fudgel | 2 小时前 | 隐藏 | 过往 | 收藏 | 讨论 | 帮助 指南 | 常见问题 | 列表 | API | 安全 | 法律 | 申请 YC | 联系 搜索:
相关文章

原文

An isometric browser route bypassing an idle service worker cache machine and connecting directly to server assets.

Neciu recently broke down some interesting use cases for service workers. I definitely felt ‘seen’ by this:

The two people in my survey who “tried one in 2019 and removed it” both told the same story with different details: a service worker with a bad cache strategy served a stale app to users, and the fix required shipping a killswitch worker and waiting days for clients to pick it up, because the broken worker controlled when updates were checked.

Back when service workers launched, I was an early adopter, and quickly foot-gunned myself in a similar scenario.

Let’s break down a few examples from the post (if you haven’t read it, please do so first!).

Use cases in the wild

Slack’s instant boot

The most compelling example in the post is Slack’s: caching the full asset set and rehydrating Redux state so that the UI can render before a single network request resolves.

The asset bit feels a touch overblown, though:

They observed that almost nothing in that asset set changes between boots.

The user who opens Slack on Tuesday morning downloads the same JavaScript they downloaded Monday morning.

An HTTP cache should be enough to alleviate this, and is far simpler. For unchanged assets, content hashing plus Cache-Control: public, max-age=31536000, immutable means they should get served directly from the cache.

What it won’t do is provide a network-free boot: you’d still need to fetch the HTML and any prerequisite data. I’d argue that this is more of a question of ‘do I need offline support?’ For Slack, sure, but for many apps, probably not.

If all you’re looking to do is avoid repeated downloads of the same assets, just hash them and leverage the native caching.

Keeping dead chunks alive across deploys

This is an interesting one. Some vendors, like Vercel, have ‘skew protection’, but most of us have run into this in the past: an old bundle on the client results in a 404 when the referenced asset no longer exists.

The more you ship, the more frequently this becomes a problem (if you practice true CI, you might be shipping hundreds of times a day).

Neciu’s solution here is to use a service worker to cache the app locally. However, this implies caching everything in the background:

{
  "version": "2026.06.04-1412",
  // Where does this end?
  "assets": ["/assets/index-c91d44.js", "/assets/Settings-c91d44.js"]
}jsonc

In my mind, this defeats the point of route/code splitting. Sure, you get a faster initial render, but it means every invalidation forces the client to refetch the entire app. For most apps I’ve worked on, this would result in a huge, mostly wasted payload. We can’t predict what components/pages the user will visit with any certainty, so in theory we’d need to pull down the contents of the entire manifest.

What if, instead, we just kept static assets around (for a grace period)? Instead of outright deleting them, let them live on in a bucket. With content-hashed filenames, a deploy never overwrites anything: Settings-a3f8b2.js and Settings-c91d44.js can coexist.

Since the service worker doesn’t run indefinitely in the background, the core refetching logic has to live in the main app anyway:

The page drives the polling instead, posting CHECK_VERSION on an interval and on visibilitychange, so a tab that comes back from a weekend in the background checks immediately.

So this doesn’t need a service worker, either.

Mux’s manifest rewriting

This is neat, but feels like it shouldn’t live on the client. The bug mentioned in the article is actually a symptom of the logic living client-side:

A video player starts fetching the moment it mounts, before a same-page worker can take control, so they had to register the worker on an index page and link onward to the player page.

Instead, move the rewrite server-side, where it’s more robust and easier to test. Only the manifest (a text file) needs rewriting, so there’s no concern about pulling a massive video through additional layers of infrastructure.

It’s even called out in the article:

…because edge runtimes like Cloudflare Workers implement the same fetch event API, they deployed the stitching worker to Cloudflare unchanged and got a working URL.

Partytown

A good example, although worth noting that the service-worker version is actually the fallback:

Partytown will use Atomics and SharedArrayBuffer when they’re available by the browser.

SharedArrayBuffer unfortunately only works under cross-origin isolation, and those headers tend to break third-party embeds. So in practice the service worker fallback gets used more than you’d expect, but it’s still more of an escape hatch.

Mock Service Worker

This depends on what you’re building, but with the move to server-driven rendering strategies and data loading, you’re probably using setupServer instead (which patches Node internals).

Only traditional SPAs will end up with a literal service worker, despite the library’s name.

So do you need a service worker?

There are a lot of cool things you can do with a service worker. There are also a few things only a service worker can do: offline support, push notifications, and background sync have no real alternative.

But outside of those, I’ve yet to run into a problem where a service worker was truly the best solution.

Have a great example? Let me know. I’ve been looking for a good excuse to revisit them.

联系我们 contact @ memedata.com