网页这东西看着像「一篇文章」,其实是一堆外部请求拼起来的。样式在一个 CSS 里,图片在另一个域名上,字体走 CDN,正文还可能是 JS 渲染出来的。所以浏览器自带的「网页另存为」存下来,得到的是一个 html 加一个同名文件夹——文件夹一挪、一改名、一压缩,图片全断。
更麻烦的是分享。那个文件夹压成 zip 发出去,对面解压路径一变,样式表照样 404。想留存的证据、教程、报错现场,过两年就只剩一堆破图。
SingleFile 解决的就是这一步:它把当前页面的 HTML、CSS、图片、字体、框架内容全部抓下来,用 data: URI 内联进一个 HTML 文件。存完只有一个 .html,双击就开,断网也完整。AGPL-3.0,v1.31.5,扩展本体解包 5.12MB。
我拿自建的演示站实测:首页 11 个请求、136,753 字节,存档 55.6 毫秒,产物 180,050 字节,残留外链 0;文章页 7 个请求、48,563 字节,存档 47.5 毫秒,产物 88,121 字节,外链同样 0。把产物用 file:// 打开并拦掉所有 http(s) 请求,联网请求 0 次,图片 8/8 与 4/4 全部解码,JS 报错 0。
有个前提得先说清楚:它出的是 MV2 扩展,Chrome 内核 148 以后装载不上。哪几类人不适合,后面单列。
它和「另存为」差在哪
浏览器自带保存、打印成 PDF、在线剪藏,三条路都有硬伤:
- 网页另存为:一个 html 加一个资源目录,必须成对存在,移动即坏
- 打印成 PDF:版式固定成纸面,链接失效、正文不可选中、代码不能复制
- 在线剪藏:内容传到别人服务器上,服务一停笔记就没了
SingleFile 走的是第四条:把整个页面序列化成一个自包含的 HTML。区别在于三点:
- 单文件:产物是 1 个 .html,邮件附件、网盘、微信都塞得进去
- 可搜索:还是 HTML,Ctrl+F 能搜,链接能点,代码块能复制
- 原样保留结构:页面 DOM 保留,只是把外部资源换成内联,暗色、响应式布局都还在
代价是体积。图片转成 base64 会膨胀约三分之一,实测首页 1.32 倍、文章页 1.81 倍。
我的测试环境
- Windows:Windows 11,Playwright 自带 Chromium 156.0.8078.4,Node 22.22.2
- Linux:CentOS Stream 9(kernel 5.14.0-626.el9.x86_64),node 22.22.2 linux-x64
- 被测页面:自建静态演示站,含外链 CSS/JS、JPEG 与 SVG 图片、懒加载图与内联图标
- 存档方式:用扩展自带的
lib/single-file.js(与扩展运行时同一份)注入页面后调getPageData() - 验证方式:断网拦请求后统计联网次数、图片解码数、JS 与 console 报错
两个平台的源码包 sha256 都是 1313bea2…1f91d3,是同一份。
装载:两条路
商店安装最省事。Firefox 和 Chrome 都能直接搜到,装完工具栏多一个图标,点一下存当前页,长按能选「存全部标签页」。
离线包适合装不了商店的机器——内网、公司电脑、不想登录账号的环境。包里的扩展目录是 Firefox 的 MV2 构建,加载方式:
- 地址栏进
about:debugging#/runtime/this-firefox - 点「临时载入附加组件」
- 选扩展目录里的
manifest.json
Firefox 上这样装完能直接用,重启浏览器会掉,重新载入一次即可。Chrome 系不要试,原因写在后面的坑里。
从源码构建也是两条命令
想要自己编译一份,Windows 和 Linux 的命令完全一样:
npm ci
npx rollup -c rollup.config.jsWindows 侧 npm ci 拉 101 个包用了 5.11 秒,rollup 出了 19 个 lib/*.js 用 18.14 秒。Linux 侧冷缓存慢一些:npm ci 78 秒、rollup 42 秒,合计 120 秒。
关键结论是产物可复现:把 19 个文件逐个和发行包里同名文件比 sha256,18 个完全一致;唯一的差异是 single-file-extension-background.js(构建 118,440 字节 / 发行包 118,563 字节,差 123 字节),原因是打包时会注入一个签名服务的 API key,源码里留的是 WOLEET_API_KEY_PLACEHOLDER。
跨平台更彻底:Linux 构建的 19 个文件与 Windows 构建 19/19 sha256 全同(single-file.js = 984156e5…20a6af)。这个项目构建产物与平台无关。
实测数据
同一套页面,两个维度分别记:
- 首页存档:源页 11 个请求 / 136,753 字节 → 存档 55.6 毫秒 → 180,050 字节
- 文章页存档:源页 7 个请求 / 48,563 字节 → 存档 47.5 毫秒 → 88,121 字节
- 体积膨胀:首页 1.32 倍,文章页 1.81 倍
- 内联
data:URI:首页 10 个,文章页 5 个 - 残留外链(src/href 还指向 http(s)):首页 0,文章页 0
- 断网打开:实际联网请求 0 次,页面请求总数 1(只有文档本身)
- 图片解码:首页 8/8,文章页 4/4
- 报错:JS 报错 0,console error 0,4xx/5xx 0
- 构建耗时:Windows 5.11 秒 + 18.14 秒;Linux 78 秒 + 42 秒
- 打包体积:成品包 2.27MB
存档产物头部会写一行注释:Page saved with SingleFile / url: … / saved date: …,出处和时间都在里面,当证据用很方便。
存档前后长什么样
先看源站,存档前的对照基线:

同一个页面,存档后用 file:// 断网打开:

肉眼看不出区别——导航、卡片、渐变、圆角、字号全在。往下一屏滚动,图片也一样。
文章页的对照更明显,源页有表格、代码块和懒加载图:


表格线、代码块底色、行内代码的等宽字体都保留了。截图里那些图片是真实解码出来的,不是占位框。
手机端也验了一遍(390 宽、DSR 2):


响应式没被破坏,因为存档保留的是原 DOM 和原媒体查询,不是把页面拍成一张图。
一个真实的坑:Chrome 载入不了
我原想把扩展装进 Chromium 截几张弹窗图,用 --load-extension 起浏览器,三个版本挨个试:
Chromium 148.0.7778.96 --load-extension 加载数 = 0
Chromium 151.0.7922.34 加载数 = 0
Chromium 156.0.8078.4 加载数 = 0进 chrome://extensions 一看,一个扩展都没有,而且不报错,也没有 no-load-error。不报错才是最坑的地方——你以为加载成功了,结果点图标没反应,翻日志也翻不出东西。
原因是这个包 manifest_version 是 2,Chrome 从 137 起移除了 --load-extension,148 之后对 MV2 更是静默不加载。所以:
- 想用 Chrome / Edge:走商店版,别用离线包
- 想用离线包:走 Firefox,
about:debugging临时载入
所以本文没有扩展弹窗和设置页的截图——那是包的形态限制,不是我漏截。上面所有存档产物都是用包里自带的引擎跑出来的,引擎文件和扩展运行时是同一份。
第二个坑在服务器侧:在面板终端里 nohup bash build.sh & 跑到 79 秒时 npm 报 signal SIGHUP,整条构建被弃。面板的 Web 终端会挂断后台任务,得用 setsid 脱离会话才稳。
存档文件怎么用
产物就是一个普通 HTML,用法有四种:
- 双击:默认浏览器打开,断网也行
- 拖进浏览器:拖到任意标签页即可
- 发给人:单个文件,微信、邮箱、网盘都能传
- 归档:扔进笔记库或 NAS,十年后还能打开,因为它不依赖任何外部资源
存多个标签页时,长按工具栏图标选「保存全部标签页」,会生成一个 zip,里面是逐页的单个 HTML。
这几类人适合,这几类不适合
适合:
- 要留存网页证据、教程、报错现场的人
- 写文档、做笔记,需要把在线资料落成本地文件的人
- 内网、离线环境的机器,装不了商店版扩展
- 想把一堆文章打包带走、又不想丢排版的人
不适合:
- 只用 Chrome 且不愿意装商店版的人。离线包是 MV2,Chromium 148 起静默不加载
- 要存视频流的人。它抓的是页面资源,不处理流媒体
- 需要保留「活链接」的人。存档是完全离线的静态副本,页面更新不会同步
- 追求最小体积的人。base64 内联必然膨胀,图片多的页面能到 1.8 倍
常见问题
{collapse-item label="为什么有的页面存下来图片是空的?"}A:懒加载的图要滚动到视口才会加载。存档前先从头滚到底,让图片都进入过视口再存。{/collapse-item}
{collapse-item label="能存需要登录的页面吗?"}A:能。它抓的是当前已渲染的 DOM,登录态下的内容是完整的,存完断网也能看。{/collapse-item}
{collapse-item label="存档后还能编辑吗?"}A:能,那就是个 HTML 文件。用任何编辑器打开改文字都行,内联样式不会跑。{/collapse-item}
{collapse-item label="Firefox 临时载入的扩展重启就没了?"}A:这是临时附加组件的设计,重启浏览器即卸载。常用的话建议走商店版,或者自己签名一个 xpi。{/collapse-item}
{collapse-item label="体积膨胀能压下来吗?"}A:能。选项里可以关掉图片内联、改成只保留 HTML+CSS,代价是图片会重新变成外链。{/collapse-item}
源码获取
建议先转存到自己网盘再下载。手机上打开链接点右下角「保存到网盘」,回头在夸克 App 的「我的网盘」里下载。