Rslib 构建时为何找不到 browser 命名空间?
结论
先在 tsconfig.json 的 compilerOptions.types 中显式加入 "firefox-webext-browser"。这个错误说明类型检查阶段无法解析 browser 命名空间,现有配置还不足以说明是 SWC 覆盖了 types。
Rslib 使用 SWC 转译 TypeScript。启用 dts: true 后,Rslib 会生成类型声明,并默认进行类型检查。日志中的 [tsc] 与声明生成阶段相符,应先检查该阶段是否加载了目标类型包。Rslib TypeScript 文档
显式加载类型包
在现有配置中增加 types,其他选项可以保留:
{
"compilerOptions": {
"lib": ["DOM", "ES2022"],
"jsx": "react-jsx",
"module": "es2022",
"skipLibCheck": true,
"isolatedModules": true,
"resolveJsonModule": true,
"moduleResolution": "bundler",
"useDefineForClassFields": true,
"rootDir": "./src",
"types": ["firefox-webext-browser"]
},
"include": ["src/**/*"]
}
这里填写 firefox-webext-browser,不带 @types/ 前缀。如果项目已有 types 列表,将它追加到列表中,并保留其他需要的类型条目。显式设置 types 后,未列出的类型包不会自动加入全局作用域。TypeScript types 文档
加载声明后,原代码可以继续使用:
export type MessageSender = browser.runtime.MessageSender;
@types/firefox-webext-browser 通过全局 declare namespace browser... 提供声明,需要让这个声明文件进入 TypeScript 编译程序。DefinitelyTyped 声明源码
为什么没有配置 types 也可能报错?
这与实际使用的 TypeScript 版本有关。官方文档说明,TypeScript 6.0 起 types 的默认值为 [];6.0 之前,默认会包含可见的 @types 包。原问题没有提供版本,因此不能仅凭缺少 types 就确定根因。TypeScript types 文档
如果使用较早版本,类型包已安装且可见,也没有其他配置限制类型加载,就需要继续检查实际构建环境,不能直接将问题归因于 SWC。
仍然失败时如何排查?
在执行 Rslib 构建的同一项目目录中,先确认依赖版本和安装情况:
npm ls @rslib/core typescript @types/firefox-webext-browser
如果目标项目尚未安装类型包,再安装:
npm install --save-dev @types/firefox-webext-browser
然后使用项目本地的 TypeScript 检查同一份配置:
npx tsc -p ./tsconfig.json --noEmit
npx tsc -p ./tsconfig.json --showConfig
npx tsc -p ./tsconfig.json --listFilesOnly
检查以下结果:
- 如果独立运行
tsc也出现 TS2503,先处理 TypeScript 的类型加载问题。 - 确认有效配置中的
types包含firefox-webext-browser。如果配置了自定义typeRoots,检查它是否限制了类型包的查找目录。 - 在文件列表中查找
@types/firefox-webext-browser/index.d.ts,确认声明是否实际进入编译程序。 - 如果独立运行
tsc通过,Rslib 仍然失败,再核对构建工作目录、实际读取的tsconfig.json和两者使用的 TypeScript 版本。--showConfig展示的是这次独立调用tsc的配置,不能单独证明 Rslib 内部使用了完全相同的配置。
自定义 typeRoots 会限制自动包含的类型目录,不建议在确认原因之前随意添加。TypeScript typeRoots 文档
哪些配置不能替代类型加载?
lib: ["DOM", "ES2022"] 提供相应的标准库声明,不能替代 Firefox WebExtensions 的类型包。skipLibCheck: true 也不会补上源码中缺失的 browser 命名空间。
加载 @types/firefox-webext-browser 只解决编译期类型问题,不会在运行时创建 browser 对象。运行代码仍需处于提供该 API 的环境中。
备注:内容仅供参考。
