Firefox 本地模式:localhost 再见了 ?

在电脑上双击打开一个 index.html,你会发现,网页里不少东西突然就不工作了。

Service Worker 注册不了,连放在同一个文件夹里的 JSON 文件,也没法通过 fetch() 正常读取。

非会员可免费阅读。

于是,你还是得走那套熟悉的流程:启动服务器。Firefox 153 新增的 Local Mode,是我见过第一个能让这一步变成可选项的功能。

就几个静态文件,为什么还得开着终端?

遇到这种情况,我的第一反应通常是运行 npx serve。

如果是在正式项目里,我会用 Vite 开发服务器;临时做个 HTML 小实验,有时就直接点一下 VS Code 里 Live Server 扩展的"Go Live"。

bash 复制代码
npx serve .
# 或者使用 Live Server

这些操作都不难。只是想在浏览器里看看一个静态文件夹,却要启动进程、占用端口,再多开一个大概率会忘记关闭的终端标签页,多少有点折腾。

举个实际点的例子:

假设你正在测试一个简单的商品页面,文件夹里有 index.html、products.json,以及一段负责加载商品详情的 JavaScript。

你用不上后端,也不需要数据库,只想看看页面能不能正确显示商品卡片。

可只要代码里用了 fetch('./products.json'),直接打开 HTML 文件就可能请求失败。结果,一个本来不需要服务器的页面,为了测试,还是得先启动服务器。

Firefox Local Mode 想省掉的,就是这点小麻烦。

问题出在 file:// 协议上。从磁盘直接打开的页面,并不会获得一个普通网页那样的源,也就是 origin。

在我的 Firefox 中,file:// 页面上的 location.origin 返回的是 null。接下来,凡是涉及源检查的功能,都会变得格外谨慎。

起初,我以为更大的障碍来自"安全上下文"限制。毕竟,异步 Clipboard API、摄像头访问、WebGPU 等 API,通常需要 HTTPS 或 localhost 环境才能使用。

但让我意外的是,在 Firefox 中,这个 file:// 页面的 isSecureContext 居然返回了 true。所以,至少在 Firefox 里,真正造成大部分麻烦的,是那个值为 null 的 origin。

Service Worker 的要求还要严格。Firefox 会直接拒绝它在 file:// 下注册,报错也很直白:"脚本 URL 使用的协议不是 http 或 https。"

一个很香的 AI 平台:GPT-5.6 低倍率且不降智 和 Claude Code 4.8 只要 0.25倍率,包含 image-2生图。重点是 首字请求都在 5s 内。入口:https://ai.aiyuhub.com

Firefox Local Mode 到底做了什么?

Firefox Local Mode 是一项开发者工具功能,可以把磁盘上的文件夹映射到一个自定义的 https:// 源。文件由 Firefox 自己提供,因此不用额外启动服务器进程,也不占用监听端口。

按照 Mozilla 文档的说明,它主要带来三个变化:

  • 只能在安全上下文中使用的 Web API,可以用本地文件进行测试。
  • 每条映射都有独立的 origin,因此各个项目拥有各自的存储空间和 Cookie。
  • 映射只在 Firefox 内部生效,其他程序和局域网中的其他设备都无法访问。

最后一点,和 npx serve 有明显区别。后者通常会同时显示本机地址和局域网地址,而 Local Mode 没有监听端口,自然也就没有一个可供其他程序或设备连接的入口。

我在 Firefox Developer Edition 159 中,用一个小型演示文件夹进行了测试:里面只有 index.html、旁边的 data.json,以及一个 Web Worker 脚本。这还算不上真正的项目,所以,下面的结果只代表我在一台 Windows 电脑、一个文件夹里的测试情况。

怎么创建映射?

打开 DevTools,进入设置面板。一条映射需要填写两项内容:origin 和本地文件夹路径。Mozilla 给出的示例,是把 https://firefox.localhost 映射到 /home/alex/app。

还有个更快的入口:保持 DevTools 打开,然后访问任意一个 file:// 地址,Firefox 就会弹出提示,提供两个按钮。

点击"Try it",会创建临时映射,关闭 DevTools 或 Firefox 后就会消失;点击"Add To Settings",则会保存为永久映射。

这个临时与永久分开的设计,比我预想中更实用。我打开的大部分本地 HTML 都是临时文件:一个复现 bug 的例子、一个 CSS 小想法,或者从 Stack Overflow 回答里拿来、还没完全确认是否靠谱的代码片段。点一下"Try it"就能测试,也不会留下越来越多的配置。

如果你习惯直接修改配置,也可以进入 about:config。每条映射都对应一组带编号的首选项,两个项目的配置大致如下:

text 复制代码
devtools.local-mode.mappings.0.origin    firefox.localhost
devtools.local-mode.mappings.0.path      /home/alex/app

devtools.local-mode.mappings.1.origin    demo.localhost
devtools.local-mode.mappings.1.path      /home/alex/demo
devtools.local-mode.mappings.1.disabled  true

disabled 是可选项。暂时不用某条映射,又不想删除时,加上它就很方便。

实测下来,哪些能用,哪些没跑通?

点击"Try it"后,我的演示页面重新加载,地址变成了 https://firefox.localhost/index.html。

这次,页面的 origin 是正常的 https://firefox.localhost,isSecureContext 也返回了 true。

fetch('data.json') 成功读到了旁边的文件,Web Worker 也顺利启动,并把消息发了回来。整个过程中,我没有另外运行服务器。

接着,我加了一个 Service Worker,结果安装失败:

text 复制代码
ServiceWorker script at https://firefox.localhost/sw.js for scope
https://firefox.localhost/ encountered an error during installation.

我的第一反应是:是不是 sw.js 写错了?可那个文件总共就一行代码。

于是,我在 127.0.0.1:443 上启动了一个简单的监听程序,再刷新页面。结果,Firefox 居然尝试连接这个真实端口,一共二十次。

我又刷新了两次,每次都是二十次。这个数字太规律了,不太像偶然出现的杂音。

页面自己的 fetch() 和 Web Worker 都能正常加载,因此,就我观察到的情况来看,Service Worker 脚本请求似乎绕过了 Local Mode,跑去连接一个并没有提供相应文件的端口。

我的猜测是,Local Mode 会拦截标签页发出的请求,但获取 Service Worker 脚本的请求,可能不属于这一类。Mozilla 文档没有明确说明是否支持 Service Worker,我也没找到相关的 Bugzilla 问题记录,所以不排除我漏掉了某项设置。不过,至少在 Firefox 159 上,我不会指望它一定能正常工作。

如果你正在开发渐进式 Web 应用,也就是 PWA,这一点就很重要。离线页面、文件缓存,以及断网后重新打开应用,都可能依赖 Service Worker。

每个项目一个 origin,可能才是更实用的地方

最吸引眼球的卖点是"不用启动服务器",但在我看来,每个项目拥有独立的 origin,反而更有价值。

源由协议、主机名和端口共同决定。Vite 默认会尝试在 localhost:5173 启动项目,所以,当项目 A 停止、项目 B 接着使用同一端口时,A 留下的 localStorage、Cookie,以及那个最容易惹麻烦的已注册 Service Worker,可能还待在同一个源下面。

如果你曾经打开一个新项目,浏览器却给你显示了另一个项目的缓存页面,通常就该怀疑旧的 Service Worker 了。最后,你还得打开 DevTools → Application,手动把它注销。

换成 Local Mode,https://shop.localhost 和 https://blog.localhost 就是两个不同的源,各自使用独立的存储空间和 Cookie,项目之间也就不会沿用这些旧数据。

光是这份隔离能力,就足以让我考虑使用它,哪怕那个文件夹用普通服务器也能正常打开。

但有个前提:DevTools 得一直开着

映射只有在 DevTools 打开时才会生效。面板一关,页面也就失去了对应的映射。

我猜这是有意为之,目的是让 Local Mode 保持开发工具的定位。不过,第一次使用时还是很容易踩坑:比如换个没有打开 DevTools 的窗口重新加载页面,然后纳闷,刚才还好好的,怎么突然全坏了?

那 localhost 服务器,还要不要留?

很多时候,还是得留。Local Mode 负责从磁盘加载文件,不会替你执行服务端程序。

  • 只要涉及后端、API 路由或服务端渲染,就仍然需要服务器。
  • Vite 的热模块替换,也就是 HMR,以及 TypeScript、JSX 转换,还有 import 'react' 这类裸模块导入的解析,都属于开发服务器的工作,Local Mode 不负责处理。
  • 它只在 Firefox 中生效。同一个页面要放到 Chrome 或 Safari 里检查,还是得启动平时使用的服务器。
  • 我的测试中,Service Worker 没有成功运行。因此,PWA 和离线功能的开发测试,暂时仍然需要 localhost 服务器。

它更适合那些小任务:纯 HTML/CSS/JS 文件夹、复现 bug 的页面、需要通过 fetch() 读取本地 JSON 或启动 Web Worker 的示例,以及那些你只想打开看看、不想再记端口号的演示。

我还不确定,它最后能不能取代我日常使用的 npx serve。但对于那些为了几个静态文件而临时启动服务器的场景,它确实有机会。

哪些人值得试一试?

如果你经常处理需要正常 origin 的静态文件,而且本来就在用 Firefox,可以先创建一条映射,看看少开一个终端标签页之后,自己会不会想念它。

建议给每个项目分配不同的 .localhost 域名,让存储空间保持隔离。至于涉及构建步骤、后端、Service Worker,或者需要在另一款浏览器里测试的项目,开发服务器还是继续留着。

测试时,我也遇到了这些问题

为什么有些浏览器 API 在 file:// 下会失败?

在我的 Firefox 测试中,直接从磁盘打开的页面,其 origin 为 null。因此,读取同一文件夹中文件的 fetch() 请求会被拦截,Firefox 将其报告为 CORS 错误;加载 Web Worker 脚本也会遇到安全限制。Service Worker 则直接拒绝使用 http、https 之外的协议。Firefox Local Mode 为文件提供了正常的 https:// 源,在我的测试中解决了 fetch 和 Web Worker 的问题,但没有解决 Service Worker 的问题。

没有 HTTPS,怎么在本地测试 Service Worker?

在 localhost 上启动一个普通 HTTP 服务器就可以。浏览器会将 http://localhost 视为安全上下文,因此不需要额外配置证书。不过,我测试的 Firefox Local Mode 没能完成这件事:在 Firefox 159 中,Service Worker 的脚本请求似乎绕过了映射,最终导致安装失败。

做前端测试,还需要 localhost 服务器吗?

如果是框架项目、带后端的项目,或者需要在其他浏览器中测试,答案仍然是需要。对于只在 Firefox 中查看的普通静态文件,Local Mode 可以承担这部分工作。

npx serve 还在我的命令历史里。做完那轮 Service Worker 测试后,我更确定,暂时不能把它扔掉。

但下一次,一个静态文件夹只是需要正常的 origin 时,我会先试试 Firefox Local Mode,再决定要不要打开新的终端。

相关推荐
晶捷软件1 小时前
从 IT 架构视角看 ERP 选型:用友、金蝶与鼎捷生态(含晶捷智能)的技术差异
架构·智能制造·erp·制造业信息化
深蓝AI1 小时前
总榜第一不等于最划算:Intelligence Index v5 换代后,模型选型要算的三笔账
程序员·架构
天远数科2 小时前
零信任架构实战:基于天远企业股权变更构建自动化商业银行对公授信存续期股权异动与资产抽逃预警网关
运维·人工智能·架构·自动化
AI你一生一世3 小时前
当“暂停“成为架构决策:从签证系统停摆看高可用设计的边界
架构·系统架构·流量控制·幂等性·高可用设计·优雅降级·状态一致性
米米商聊3 小时前
同名附件为什么被 Map 覆盖?重复键与一对多索引
前端·javascript
echome8884 小时前
Python 异常处理:try、else、finally 的正确搭配
开发语言·前端·python·异常处理·编程技巧
时间的情敌4 小时前
OpenLayers 实战|Vue3 + OpenLayers 完整工程案例(加载天地图、要素、弹窗、绘制、WFS)
前端·openlayers
陈随易4 小时前
下载神器!Motrix 停更三年后重写回归
前端·后端·程序员
前端的日常5 小时前
一个人+AI做情侣食谱小程序,0 费用的服务器
前端·后端