@zakatop/fastsw

中文文档
1.0.0发布于 2026/11/03MITES Module零依赖

very fast service worker powered web proxy

原始使用文档
文档目录11 节
  1. Quick start
  2. 1. Serve the files
  3. 2. Add a frontend
  4. 3. Point it at a Wisp server
  5. API
  6. Fastsw.createFrame(arg?, options?) → Frame
  7. Other helpers
  8. Where things live
  9. Configuration
  10. Troubleshooting
  11. Files

FastSW

A service-worker web proxy. Pages are fetched with libcurl.js over a Wisp server, rewritten (HTML, CSS, and JS through an embedded acorn AST pass), and handed back to the browser from the service worker.

  • one file to load in your page (fastsw.min.js), plus libcurl_full.js next to it
  • Fastsw.createFrame() puts a proxied page in an <iframe> you control
  • location / top / parent are replaced inside proxied pages, so they can't navigate or frame-bust their way out
  • cookies, storage, IndexedDB and postMessage are kept separate per proxied site

Quick start

1. Serve the files

// server.js
import express from "express";
import { fastswPath } from "fastsw";

const app = express();
app.use("/fastsw/", express.static(fastswPath)); // fastsw.min.js, fastsw.all.js, libcurl_full.js
app.use(express.static("public"));               // your own frontend
app.listen(3000);
npm i ./fastsw-1.0.0.tgz express
node server.js

require("fastsw") works too. Any static host works as long as the three files end up in one folder (see Where things live).

2. Add a frontend

<!-- public/index.html -->
<form id="form"><input id="url" placeholder="Search or enter a URL"><button>Go</button></form>
<div id="view" style="height:90vh"></div>

<script src="/fastsw/fastsw.min.js"></script>
<script>
  const frame = Fastsw.createFrame({ container: document.getElementById("view") });
  document.getElementById("form").onsubmit = (e) => {
    e.preventDefault();
    frame.go(document.getElementById("url").value);
  };
</script>

createFrame registers the service worker for you. See example__frontend.html for a complete page with back / forward / reload buttons.

3. Point it at a Wisp server

The default is set in the CONFIG object at the top of fastsw.all.js (wisp: "wss://…/wisp/"). Set it to your own Wisp server, or to null to use /wisp/ on the same host.

API

All of it lives on window.Fastsw.

Fastsw.createFrame(arg?, options?) → Frame

arg can be a URL or search text, an existing <iframe>, or an options object.

optionmeaning
urlpage to open straight away
frameuse this <iframe> instead of creating one
containerelement to append the new iframe to
searchsearch URL used for non-URL input, %s is the query (DuckDuckGo)
attrsextra attributes for the iframe
className, styleapplied to the iframe
const f = Fastsw.createFrame("https://example.com", { container: document.body });

f.go("wikipedia.org");   // URL, bare domain, or search text
f.back();  f.forward();  f.reload();
f.url;                   // the REAL address of the page shown, never /fastsw/service/...
f.title;
f.ready;                 // promise: service worker registered and active
f.element;               // the <iframe>
f.destroy();

f.addEventListener("navigate",  (e) => console.log(e.detail.url)); // every load
f.addEventListener("urlchange", (e) => console.log(e.detail.url)); // also pushState / hash changes

Other helpers

callwhat it does
Fastsw.register({ scope })register the service worker; resolves with the registration
Fastsw.go(input, opts)navigate the current window (or opts.target) to the proxied page
Fastsw.encode(url)the /fastsw/service/<url> form of a URL
Fastsw.Framethe class behind createFrame
Fastsw.CONFIGthe active configuration (read-only in practice)

Where things live

Everything is worked out from the folder that fastsw.*.js is served from, so you can mount it anywhere. Served at /fastsw/:

thingURL
service worker scope/fastsw/
proxied pages/fastsw/service/<url>
in-page runtime/fastsw/client.js
libcurl (static)/fastsw/libcurl_full.js
debug page/fastsw/debug

A service worker can only claim scopes at or below its own script's folder, which is why FastSW never registers for /. If you mount the folder somewhere that isn't called fastsw (say /static/), a fastsw/ folder is added below it: scope /static/fastsw/, and libcurl stays next to the script at /static/libcurl_full.js.

Want the full / scope? Send Service-Worker-Allowed: / for the script and call Fastsw.register({ scope: "/" }).

Configuration

CONFIG sits at the top of fastsw.all.js:

keydefaultnotes
wispwss://zakaon.top/wisp/your Wisp server; null = same host, /wisp/
libcurlJS<script folder>/libcurl_full.jsstatic file; set it to host libcurl somewhere else
pageWebSockettruesend page WebSockets through Wisp too
bypass[]paths on your own host the worker must never touch
scope, prefix, clientPath, debugPathderivedchange scope through Fastsw.register, the rest follow the folder

Troubleshooting

Failed to register a ServiceWorker … not under the max scope allowed: the script's folder doesn't contain the scope you asked for. Don't pass scope: "/" unless the host sends Service-Worker-Allowed: /.

"FastSW could not load /…/libcurl_full.js": the file isn't next to the script. Open that URL directly; it should download about 2 MB of JavaScript, not an HTML page. Then unregister the worker and reload.

Something on a page breaks. Two tools:

  • open /fastsw/debug on your proxy origin for the worker's recent requests (headers, status, cookies; add ?f=<text> to filter). Secrets are redacted.
  • localStorage.__fastswDebug = "1" and reload, for extra console logging from inside proxied pages.

WebSocket lifecycle is always logged as [fastsw] websocket … lines, including the libcurl error code if a handshake fails.

Files

filepurpose
dist/fastsw.jseverything, minified (load this one)
dist/fastsw.all.jsthe same, readable
dist/libcurl_full.jslibcurl.js with its WASM bundled in
fastsw.helper.js / .cjsfastswPath for Node, ESM and CommonJS

版本与发布记录

@zakatop/fastsw 共发布 2 个版本,首次发布于 2026/11/03;过去 12 个月发布了 2 个版本。

版本发布日期距今
1.0.0latest2026/11/03今天
0.0.0-stage2026/11/03今天

关于 @zakatop/fastsw 的常见问题

@zakatop/fastsw 是什么?

非常快的service worker驱动的web代理

如何安装 @zakatop/fastsw?

在项目目录运行 npm install @zakatop/fastsw,或使用 pnpm add / yarn add / bun add。

@zakatop/fastsw 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/zakatop__fastsw 是否存在。

@zakatop/fastsw 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@zakatop/fastsw 可以商用吗?

@zakatop/fastsw 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@zakatop/fastsw 还在维护吗?

最新版本 1.0.0 发布于 2026/11/03(今天);至今共发布 2 个版本,其中过去 12 个月发布了 2 个;首次发布于 2026/11/03。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。