首页 / WXT 浏览器扩展框架教程 / 迁移到 WXT:从 Plasmo / CRXJS / 原生

WXT 浏览器扩展框架教程

迁移到 WXT:从 Plasmo / CRXJS / 原生

本教程共 45 篇 · 第 44 篇 · 更新于 2026-08-13 · 约 4 分钟阅读

WXT迁移PlasmoCRXJS原生开发MV3

本节目标:给已经用别的方案写扩展的读者一条稳妥的搬家路线。先讲官方推荐的迁移总法,再分别给 Plasmo、CRXJS、vite-plugin-web-extension 和原生 MV3 的具体步骤。

迁移总法:先建新壳,再逐文件搬

官方反复强调一个总原则:不要原地改造,先新建一个 vanilla 项目,再一文件一文件地并进来

cd path/to/your/project
pnpm dlx wxt@latest init example-wxt --template vanilla

这样做的理由很实在:WXT 的项目骨架(§04 讲过目录约定)是验证过的正确结构,你只管往里搬代码,而不是同时调试「结构对不对」和「代码对不对」两件事。每个项目都不一样,没有万能脚本,但有一个统一终点:

迁移完成的标准:wxt dev 跑得起来,wxt build 产物能加载,且最终 manifest.json 的权限和原版完全一致。

通用清单:所有迁移都要过一遍

不管从哪来,这些事都要做:

  1. 安装 wxt 依赖。
  2. 让项目的 tsconfig.json 继承 .wxt/tsconfig.json(见 §29)。
  3. 更新 package.json 的 scripts 改用 wxt 命令,并加上 "postinstall": "wxt prepare"
  4. 把入口点搬进 entrypoints/ 目录。
  5. 把静态资源放进 assets/public/
  6. manifest.json 的内容搬进 wxt.config.ts
  7. 把自定义的导入语法改造成 Vite 兼容写法。
  8. 给 JS 入口点补上默认导出(defineBackground / defineContentScript / defineUnlistedScript)。
  9. 把代码里的 chrome 全局改成 browser(§20 讲过两者的关系)。
  10. ⚠️ 对比新旧 manifest.json,确保权限与 host 权限一字不差。
Warning

扩展已在商店上线的话,权限变化会导致用户端扩展被自动禁用。提交前用 Google 官方的 extension-update-testing-tool 做一次更新测试,确认没有新增权限。

从 Plasmo 迁移

Plasmo 和 WXT 同为框架,搬家算是「平移」:

  1. 安装 wxt
  2. 入口点搬进 entrypoints/。JS 入口把原来用命名导出写的配置并入 WXT 的默认导出;HTML 入口不能直接放 JSX/Vue/Svelte 文件,要建一个 HTML 文件手动挂载应用(官方模板有 React/Vue/Svelte 三个示例)。
  3. public/ 里的资源原样搬走。
  4. 内容脚本 UI 改用 createShadowRootUi / createIframeUi / createIntegratedUi 系列(§15,老教程里的 createContentScriptUi 是旧名)。
  5. 把 Plasmo 的自定义导入解析改成 Vite 的标准导入。
  6. 通过 URL 导入远程代码在 WXT 不支持(0.21 起 url: 导入已移除,§45 有讲),改用 npm 包或本地化文件。
  7. Plasmo 的 --tag 构建标签换成 WXT 的构建模式 --mode(§26)。
  8. ⚠️ 对比新旧生产版 manifest,不一致就回头调入口和配置。

从 CRXJS 迁移

CRXJS 是 Vite 插件,核心差异一句话:CRXJS 从 manifest 决定构建什么,WXT 从 entrypoints/ 目录决定构建什么。理解这点,剩下的就是机械操作:

  1. 入口点搬进 entrypoints/,改成 WXT 风格(TS 文件带默认导出)。
  2. 把入口点专属配置(内容脚本的 matchesrun_at 等)从 manifest 挪进入口文件。
  3. 把 manifest 剩余配置(权限等)挪进 wxt.config.ts
  4. 前期建议先禁用自动导入(§29 讲了开关),搬完再开。
  5. 更新 package.json scripts,务必加上 "postinstall": "wxt prepare"
  6. 删除 vite.config.ts,插件挪进 wxt.config.tsvite 字段;用前端框架就装对应 WXT 模块(§24)。
  7. 继承 .wxt/tsconfig.json,路径别名配到 wxt.config.ts(§29)。
  8. ⚠️ 对比新旧 manifest,权限不变才算完成。

官方给了一个完整迁移实例:GitHub 上的 “Better Line Counts” 仓库有 CRXJS → WXT 的单 commit 迁移记录,值得对照着看。

从 vite-plugin-web-extension 迁移

同为 Vite 系,路径更短:装 wxt → 入口点改成带默认导出的 WXT 风格 → scripts 换成 wxt 并加 postinstall → manifest 搬进 wxt.config.tsvite.config.ts 里的自定义配置搬进 wxt.config.ts → 对比 manifest。

从原生 MV3 迁移

没有框架包袱,反而最接近通用清单:入口文件拆进 entrypoints/ 并按入口类型包上 defineXxx 壳、manifest 整体搬进 wxt.config.ts、构建脚本换成 wxt build。你的业务代码(页面、工具函数、状态逻辑)基本原样保留,框架只接管「怎么构建」这一层。

保持封装不换的原则

迁移容易上头,顺手把所有东西「现代化」一遍。官方对 storage 封装有明确建议:迁移时先原样保留(storage.md 原文:「If you’re migrating to WXT and already have a storage wrapper, keep using it」)。消息协议层同理——保留既有封装,跑通迁移后再按 §17、§18 逐步换成 @webext-core/messagingwxt/storage,这是社区常见做法。一次只动一件事,出问题才好定位。

小结

  • 迁移总法:先建 vanilla 新壳,再按清单一步步搬,每步都能独立验证。
  • 从 Plasmo / CRXJS / 原生 MV3 各有对应步骤,url: 导入等旧特性已移除。
  • 一次只动一件事;storage / 消息的既有封装先保留,跑通再换。