工作原理
Extension.js 按以下顺序选择 profile 模式:- 当
profile: false或EXTENSION_USE_SYSTEM_PROFILE=true时,使用系统 profile 模式 - 显式的
profile路径(如果提供) - 受管理的 profile 模式(默认)
- 默认是临时(ephemeral)
- 当
persistProfile: true或keepProfileChanges: true时则保持持久
--profile 的取值如何被读取
CLI 以字符串形式传递 flag 的值,因此 Extension.js 会先做归一化:
--profile=false(或配置中的profile: false)表示使用浏览器自己的默认 profile。--profile=true表示受管理的默认值,等同于不设置这个选项。- 其他任何字符串都会被当作显式的 profile 路径。
--profile 路径是相对于项目(编译上下文)解析的,而不是相对于你 shell 的工作目录。这样一来,依次运行不同项目时就不会都塌缩到同一个共享 profile 上。
Firefox 及其他 Gecko 浏览器上的系统 profile 模式
Extension.js 通过远程调试把附加组件安装进 Gecko 浏览器,而浏览器自己的 profile 默认关闭远程调试。因此在使用--profile=false、profile: false 或 EXTENSION_USE_SYSTEM_PROFILE=true 时,dev、start 和 preview 会在浏览器启动之前停下,不会有任何东西以你日常使用的 profile 打开。这适用于 CLI 启动的每一个 Gecko 目标:firefox、waterfox、librewolf、zen、floorp 和 gecko-based。
这三个命令都会输出一段说明,指出该设置的来源以及两条出路。浏览器名称随你的目标而变,SET BY 行会列出每一个生效的来源(--profile=false、profile: false in extension.config.js 或 EXTENSION_USE_SYSTEM_PROFILE=true):
extension dev 会让开发服务器继续运行并监听,ready.json 处于 error(代码 browser_launch_failed,browserLaunchFailedCode: "E_FLAG_NOT_SUPPORTED_HERE")。extension start 和 extension preview 以退出码 1 结束。使用 --output json 时,每个命令都会以 E_FLAG_NOT_SUPPORTED_HERE 和 status: "usage" 失败。
早期版本会以你自己的 profile 启动浏览器,但其中没有加载任何东西。要得到可用的会话,请选择这段说明中给出的两条出路之一:
- 去掉
--profile=false(以及profile: false或EXTENSION_USE_SYSTEM_PROFILE),让 Extension.js 管理 profile 并安装附加组件。加上persistProfile: true可以在多次运行之间保留登录和状态,也可以用copyFromProfile从已有 profile 为受管理 profile 播种。 - 传入
--profile=<path>,用你自己的 profile 目录启动。Extension.js 会把附加组件安装进去。
profile 能力
用 copyFromProfile 播种
copyFromProfile 会在启动前把源目录复制进受管理的 profile。只有当目标是全新的(也就是不存在或为空)时才会复制。因此持久化的 profile 只会被播种一次,你之后的改动能在每次运行之间存活下来。
profile 模式
Extension.js 会在以下位置创建受管理的 profile:
dist/extension-js/profiles/<browser>-profile/<...>
dist/extension-js/profiles/<browser>-profile/dev
brave-magenta-heron。这个名字每次运行都是随机的,所以不要把它硬编码。要知道某次运行用的是哪个 profile,请读取该会话 ready.json 中的 profilePath 字段。
在 extension.config.* 中配置
CLI 用法
直接使用显式的 profile 路径:start 与 preview 上用法类似。
生命周期说明
- Extension.js 为每次运行创建一个临时的受管理 profile。
- Extension.js 在多次运行之间复用持久的受管理 profile(
dev)。 - 每个临时 profile 都带有一个
.extension-js-managed-profile标记文件。浏览器退出时,Extension.js 只删除带有该标记的目录,因此被保留的 profile 和显式指定的 profile 永远不会被回收。 - Extension.js 还会在下一次启动时清扫陈旧的带标记 profile。可通过
EXTENSION_TMP_PROFILE_MAX_AGE_HOURS控制最大保留时长(默认 12 小时)。 - 每次启动 Firefox 时,Extension.js 都会删除该 profile 的
startupCache目录。否则被固定或持久化的 profile 可能在整次 dev 重启之后仍然提供陈旧的扩展代码。
被锁定的 Chromium profile
在 Chromium 启动之前,Extension.js 会读取该 profile 的SingletonLock 产物。如果锁指向一个已经死亡的进程或另一台主机,它就是陈旧的。Extension.js 会删除陈旧的 SingletonLock、SingletonSocket 和 SingletonCookie 文件,然后正常启动。如果持有它的进程在本机仍然存活,启动则会中止。会话的 ready.json 会被打上 profile_locked 错误码,因此机器消费方永远不需要解析错误语句。
隐私
受管理的 profile 是一份完整的浏览器 profile。它保存着你在那个浏览器会话里所做的一切留下的 cookie、历史记录和登录数据。Extension.js 会在dist/extension-js 中写入一次带 * 规则的 .gitignore,因此 profile 和会话状态永远不会进入 git。不要提交或分发这个目录。
最佳实践
- 基线测试用受管理临时 profile:减少隐藏状态,降低不稳定复现的概率。
- 长时间调试会话用
persistProfile:在多次运行之间保留 auth / 会话 / devtools 状态。 - 按浏览器家族保持各自的自定义 profile:避免跨浏览器互相污染。
- 有意识地使用系统 profile 模式:适合在 Chromium 家族浏览器上复现问题,但隔离性不如受管理 profile。Extension.js 会拒绝在这种模式下启动 Gecko 浏览器。
下一步
- 进一步了解 浏览器 preferences。
- 进一步了解 浏览器 flag。

