Skip to main content
用一份配置文件同时设置浏览器默认值、命令行为与打包器自定义。 在团队间共享浏览器默认值、命令选项和构建设置。不再反复输入 CLI 参数。Extension.js 会从项目根目录读取 extension.config.js(或 .mjs / .cjs),并把设置应用到所有命令与打包器。

工作原理

在项目根目录(通常和 package.json 同级) 添加 extension.config.js。 支持的文件名:
  • extension.config.js
  • extension.config.mjs
  • extension.config.cjs
顶层键:

类型安全的配置

Extension.js 从 extension 包中导出 FileConfig 类型,让编辑器可以对你的配置进行自动补全与类型检查。用 JSDoc 的 @type 标签标注导出即可 —— 它在 extension.config.js、.mjs 与 .cjs 中都能工作,且无需构建步骤:

配置文件的环境加载

extension.config.* 在 Node 中运行,应通过 process.env.* 读取值。
  • 在求值 extension.config.* 之前,Extension.js 会按从弱到强的顺序预加载 env 文件:.env.defaults、.env、.env.local、.env.development。每个存在的文件都会加载,而 shell 导出的变量始终优先。
  • 它会先检查项目目录。
  • 在 monorepo 中,如果 Extension.js 在项目本地没找到任何 .env* 文件,会回退到最近的 workspace 根目录。workspace 根目录是包含 pnpm-workspace.yaml 的目录。
  • 在配置文件中,优先使用内置的 env 预加载,而不是导入 dotenv。

浏览器配置

每个目标需要不同的浏览器默认值?使用 browser:
支持的浏览器键包括:chrome、edge、firefox、chromium、chromium-based、gecko-based、firefox-based。 常用的浏览器字段:
  • profile、persistProfile
  • preferences
  • browserFlags、excludeBrowserFlags
  • chromiumBinary、geckoBinary
  • extensions(仅加载的附属扩展)

浏览器目标能力

命令配置

用 commands 为每个命令定义默认值:
说明:
  • extensions、transpilePackages 与 perfBudgets 在每个命令上都按从弱到强分层:顶层,然后是 browser.<vendor>,然后是 commands.<cmd>,最后是 CLI flag。
  • define 在同样的层上逐键合并:顶层,然后是 browser.<vendor>,然后是 dev、start 和 build 上的 commands.<cmd>。
  • folders 从不逐键合并。browser.<vendor>.folders 替换顶层对象,dev、start 和 build 上的 commands.<cmd>.folders 则同时替换这两者。
  • commands.build.browser、commands.start.browser 与 commands.preview.browser 决定这些命令的目标浏览器。--browser flag 仍然优先。
  • start 命令在内部会先运行 build,然后 preview。Extension.js 会应用 commands.start 中的设置,包括 profile、browserFlags、startingUrl 等浏览器启动选项。你也可以把构建相关的设置放进 commands.build。

命令通用能力

build 命令能力

dev 命令能力

日志能力

编译期常量

用 define 把常量内联进每个 bundle。Extension.js 会把每个值序列化为 JSON,所以字符串、数字、布尔值和普通对象都可以:
你的代码把 __APP_VERSION__ 当作一个裸标识符来读取,构建会把它替换成对应的值。在 TypeScript 项目里,每个键还会在生成的 extension-env.d.ts 中得到一条环境声明,所以 __APP_VERSION__ 会按 string 通过类型检查。

特殊文件夹的位置

用 folders 移动某个特殊文件夹,或者把它关掉。路径从项目根目录解析:
  • 移动后的 scripts 或 pages 文件夹必须保留原名。Extension.js 不会读取 src/injected 这样的路径。
  • false 会关掉这个文件夹。Extension.js 不再把其中的文件编译成入口,也不再复制 public 文件夹。
    • 被关掉的 scripts 文件夹里、由你的代码点名的脚本(例如在 chrome.scripting.executeScript({files}) 中)仍然会发布。Extension.js 会像编译其他文件夹里的脚本一样编译它,不加内容脚本包装。
    • 被关掉的 public 文件夹里的任何内容都不会发布,/icon.png 这样的根路径也不再指向那里。如果 manifest 仍然点名那里的文件,构建会失败并逐一列出这些文件。如果页面或样式表引用了那里的文件,构建会为每处引用打印一条警告。请重新打开这个文件夹,或者把文件移出 public/。
  • 移动后的文件夹与默认文件夹的行为完全一致。移动后的 scripts 文件夹里的脚本会得到内容脚本包装,并在 dev 中原地重载。移动后的 pages 文件夹里的页面会构建到同样的 pages/ 输出。页面、样式表或 manifest 用同样的根路径(例如 /logo.png)就能访问移动后的 public 文件夹里的文件。
  • 当 public 指定了路径时,Extension.js 只从那个文件夹复制。
  • browser.<vendor>.folders 会整体替换顶层对象,commands.<cmd>.folders 则同时替换这两者。两者都不会逐键合并。

Rspack 配置

需要更高级的打包器自定义?用 config 给生成的 Rspack 配置打补丁。这个示例需要 4.1.31 之后的版本:在那之前,config 里的 config.module.rules 是 undefined,而 configResolved 才是能看到规则的钩子:
config 也可以是一个对象,Extension.js 会把它合并到生成的配置之上。 config 在 Extension.js 挂上它的 loader 规则之前运行。要读取或修改最终的配置,请使用 configResolved。它在每次 dev、build 或 start 运行中只执行一次,就在第一次编译之前,并收到已挂上所有 loader 规则的 Rspack 配置:
这个钩子可以修改 module、resolve、resolveLoader、node、optimization.minimize、optimization.minimizer,以及 Rspack 在构建开始时才读取的 output 选项,例如文件名和 environment。可以就地修改它们,也可以返回一个新的配置对象。这个钩子可以是异步的,什么都不返回的钩子会让配置保持原样。 到这时 Rspack 已经消费了其余所有键。这包括 entry、plugins、context、mode、target、devtool、externals、experiments 和 performance 这类键,minimize 与 minimizer 之外的所有 optimization 键,以及这些 output 键:path、module、library、enabledLibraryTypes、chunkFormat、chunkLoading、enabledChunkLoadingTypes、wasmLoading、enabledWasmLoadingTypes、workerChunkLoading、workerWasmLoading、workerPublicPath、pathinfo、sourceMapFilename、devtoolModuleFilenameTemplate、devtoolFallbackModuleFilenameTemplate、devtoolNamespace、bundlerInfo。对其中任何一个的修改,包括深入到值内部的修改,Extension.js 都会撤销,并打印一条按路径列出每个键的警告。请在 config 里设置它们。

钩子上下文

两个钩子都会收到第二个参数,用来说明本次运行。它带有 browser(目标浏览器,与 --browser 的写法一致)、mode(development、production 或 none)和 command(dev、build、start 或 preview)。用它为某一个浏览器修改打包器,而不必读取 process.argv。下面的例子让 Firefox 的商店构建保持可读,方便审核:
extension 包为这个参数导出了 ConfigHookContext 类型。只接收一个参数的钩子仍然可以正常工作。

为某一个浏览器保留一组 locale

商店接受的语言可能少于你的 _locales 文件夹所包含的语言。Extension.js 会为每个浏览器复制整个文件夹。要为某一个浏览器只发布其中一部分,请从 config 推入一个插件,删除其他 locale 的资源:
有了这个文件,extension build --browser=edge 只会发布 _locales/en 和 _locales/de。其他所有浏览器仍保留整个文件夹。过滤器必须保留 default_locale 所指的文件夹。当它删除了那个文件夹时,构建会失败,并在错误中指出该 locale。

完整示例

最佳实践

  • 把浏览器特定的值放进 browser:让命令定义专注于工作流,而不是浏览器内部细节。
  • 有意识地使用顶层默认值:把共享的 extensions / transpilePackages 放在根级,只在必要时覆盖。
  • 优先使用 chromiumBinary/geckoBinary 这类命名:与当前命令与类型接口一致。
  • 保持 config 钩子最小化:只添加 Extension.js 一等公民选项未覆盖的内容。

下一步