26 KiB
OXC 迁移计划
本文档记录将项目中可替代的工具链逐步迁移到 oxc 生态的计划。
说明:本文档已按当前仓库状态校准。第一阶段已完成大部分工作,第二阶段的 formatter 迁移也已大部分落地。
当前现状
当前仓库的 lint / format 体系已经从“纯 ESLint + Prettier”演进为 “oxlint + ESLint 共存,oxfmt 替换 Prettier”。
当前与 lint / format 直接相关的核心依赖包括:
eslint^10.0.3oxlint^1.55.0oxfmt^0.40.0eslint-plugin-oxlint^1.55.0@typescript-eslint/parser^8.57.0@typescript-eslint/eslint-plugin^8.57.0eslint-plugin-unicorn^63.0.0eslint-plugin-unused-imports^4.4.1eslint-plugin-n^17.24.0eslint-plugin-perfectionist^5.6.0eslint-plugin-vue^10.8.0eslint-plugin-better-tailwindcss^4.3.2eslint-plugin-jsonc^3.1.2eslint-plugin-yml^3.3.1eslint-plugin-command^3.5.2eslint-plugin-pnpm^1.6.0@eslint-community/eslint-plugin-eslint-comments^4.7.1vue-eslint-parser^10.4.0yaml-eslint-parser^2.0.0globals^17.4.0esbuild^0.27.4html-minifier-terser^7.2.0
以下依赖已不再存在于当前仓库的 lint / format 链路中:
eslint-plugin-import-xeslint-plugin-regexpeslint-plugin-jsdoceslint-plugin-no-only-tests@vitest/eslint-plugineslint-plugin-prettierstylelint-prettierprettier
第一阶段:引入 oxlint,与 ESLint 共存
目标:将通用 JS/TS lint 规则交给 oxlint,ESLint 仅保留 oxlint 无法覆盖的特殊规则,减少依赖数量并提升 lint 速度。
1.1 安装 oxlint
pnpm add -Dw oxlint
1.2 已迁出或已移除的 ESLint 插件
以下插件与规则已经完成迁移,或者已从当前仓库移除:
| 插件 | 当前状态 | 说明 |
|---|---|---|
eslint-plugin-regexp |
已移除 | 由 oxlint 内建能力承接 |
eslint-plugin-jsdoc |
已移除 | 由 oxlint 内建能力承接 |
eslint-plugin-no-only-tests |
已移除 | 测试规则已迁到 oxlint / vitest 分类 |
eslint-plugin-import-x |
已移除 | import 规则已集中迁入 @vben/oxlint-config |
@vitest/eslint-plugin |
已移除 | Vitest 规则已迁入 @vben/oxlint-config |
eslint-plugin-prettier |
已移除 | formatter 已切换到 oxfmt |
eslint-plugin-better-tailwindcss |
已迁出 ESLint | 仍保留依赖,但已通过 oxlint jsPlugins 运行 |
@typescript-eslint/eslint-plugin |
仍需保留 | 还有一批 TS 规则未迁移 |
@typescript-eslint/parser |
仍需保留 | ESLint 侧 TS / Vue 规则仍依赖它 |
eslint-plugin-unicorn |
仍需保留 | ESLint 侧仍使用其 recommended 规则补充 |
eslint-plugin-unused-imports |
仍需保留 | no-unused-imports 仍由 ESLint 负责 |
eslint-plugin-n |
仍需保留 | 多条 Node 规则在 oxlint 中暂无等价承接 |
eslint-plugin-perfectionist |
仍需保留 | 排序规则策略不同,不建议强迁 |
@eslint-community/eslint-plugin-eslint-comments |
仍需保留 | 当前尚未迁移 |
1.3 当前仍需保留在 ESLint 侧的插件 / 能力
以下插件或能力当前仍需继续由 ESLint 处理:
| 插件 / 能力 | 原因 |
|---|---|
eslint-plugin-vue + vue-eslint-parser |
Vue SFC template lint,oxlint Vue 支持尚未完善 |
@typescript-eslint/eslint-plugin + @typescript-eslint/parser |
仍有一批 TS strict / type-aware 规则保留在 ESLint 侧 |
eslint-plugin-unused-imports |
no-unused-imports 仍由 ESLint 负责 |
eslint-plugin-n |
多条 Node 规则尚无等价承接 |
eslint-plugin-perfectionist |
当前仍负责排序策略 |
eslint-plugin-jsonc + eslint-plugin-yml + yaml-eslint-parser |
JSON / YAML 文件 lint 仍在 ESLint 侧 |
eslint-plugin-pnpm |
pnpm workspace 规则,oxlint 无对应 |
eslint-plugin-command |
魔法注释命令,oxlint 无对应 |
@eslint-community/eslint-plugin-eslint-comments |
当前尚未迁移 |
1.4 配置 oxlint
当前实现已经调整为与 ESLint 一致的 workspace 包组织方式:
- 根目录使用 oxlint.config.ts 作为薄入口
- 实际规则配置位于
internal/lint-configs/oxlint-config - ESLint 兼容层通过
eslint-plugin-oxlint直接消费@vben/oxlint-config导出的配置对象,确保 oxlint 与 ESLint 共用同一份规则源
示例结构:
// oxlint.config.ts
import { defineConfig } from '@vben/oxlint-config';
export default defineConfig();
// internal/lint-configs/oxlint-config/src/index.ts
import { defineConfig as defineOxlintConfig } from 'oxlint';
import { mergeOxlintConfigs, oxlintConfig } from './configs';
export function defineConfig(config = {}) {
const { extends: extendedConfigs = [], ...restConfig } = config;
return defineOxlintConfig(
mergeOxlintConfigs(oxlintConfig, ...extendedConfigs, restConfig),
);
}
不再使用根目录 .oxlintrc.json。
1.5 当前已完成项
截至当前仓库状态,第一阶段与其配套的 formatter 迁移已完成以下工作:
- 根
lint已统一委托给vsh lint - 保留
lint:oxc、lint:oxc:type-aware、lint:eslint、lint:style作为独立入口 lefthook已接入oxfmt、oxlint --fix、eslint --cache --fix、stylelint --fix- 已新增
@vben/oxlint-config,并将 oxlint 规则集中到internal/lint-configs/oxlint-config - 已新增
@vben/oxfmt-config,并使用根级oxfmt.config.ts作为格式化配置入口 eslint-plugin-oxlint已接入@vben/eslint-config- 已移除
eslint-plugin-jsdoc、eslint-plugin-regexp、eslint-plugin-no-only-tests import与vitest规则已迁入 oxlint,相关 ESLint 插件已移除better-tailwindcss已迁移到@vben/oxlint-config的jsPlugins方案unicorn插件已在 oxlint 侧显式启用,并补齐仓库内所需的 override- Prettier 相关根配置与 ESLint / Stylelint 集成已移除
internal/node-utils已改为调用oxfmt
1.6 当前 oxlint 基线策略
当前 @vben/oxlint-config 采用“先收敛噪音,再逐步接管规则”的策略:
- 启用
correctness和suspicious - 显式启用
import、node、oxc、typescript、unicorn、vitest、vue插件 - 通过
jsPlugins在 oxlint 侧承接better-tailwindcss - 对当前仓库内高噪音且不准备立即批量整改的规则先显式关闭
- 通过
overrides为.d.ts、测试文件、脚本目录等特殊场景保留例外配置 overrides.files已避免继续使用 ESLint 风格的 extglob,改为显式文件后缀列表
1.7 当前已迁入 oxlint 的规则
以下规则已在当前仓库的 @vben/oxlint-config 中落地:
JavaScript / core
eqeqeqno-alertno-array-constructorno-callerno-case-declarationsno-debuggerno-evalno-iteratorno-new-wrappersno-shadow-restricted-namesno-unused-expressionsprefer-const- 以及一批额外的 core 规则,例如
no-console、no-template-curly-in-string、prefer-template、object-shorthand
import
import/consistent-type-specifier-styleimport/firstimport/no-duplicatesimport/no-mutable-exportsimport/no-named-defaultimport/no-self-importimport/no-webpack-loader-syntax
TypeScript
typescript/ban-ts-commenttypescript/no-non-null-assertiontypescript/no-var-requirestypescript/triple-slash-reference
当前仓库已开始为 type-aware 规则预留位置,但
no-floating-promises、await-thenable等高噪音规则仍显式关闭,等待后续逐步接管。
Vitest
vitest/consistent-test-itvitest/no-focused-testsvitest/no-identical-titlevitest/no-import-node-testvitest/prefer-hooks-in-ordervitest/prefer-lowercase-title
Node
node/no-exports-assignnode/no-new-requirenode/no-path-concat
Unicorn
unicorn/no-process-exitunicorn/prefer-module
Tailwind CSS
better-tailwindcss/enforce-consistent-class-order
better-tailwindcss/enforce-consistent-line-wrapping与better-tailwindcss/no-unknown-classes当前仍因噪音 / 与 formatter 冲突而关闭。
Vue
vue/prefer-import-from-vue
1.8 暂时仍需保留在 ESLint 的部分
以下内容当前不建议从 ESLint 侧移除:
- Vue SFC / template 主体规则
perfectionistjsonc/ymlpnpmcommandeslint-commentsunused-importsnode.ts中尚未被 oxlint 覆盖的规则typescript.ts中暂不适合直接迁移的 strict / type-aware 规则
其中 Vue 相关规则尤其需要保留,至少包括:
vue/block-ordervue/component-name-in-template-casingvue/component-options-name-casingvue/custom-event-name-casingvue/define-macros-ordervue/no-unused-refsvue/no-useless-v-bindvue/require-default-propvue/require-explicit-emitsvue/v-on-event-hyphenationvue/prefer-separate-static-classvue/prefer-template
1.9 推荐的下一步执行顺序
为降低回归风险,建议按当前真实代码结构推进:
- 验证
oxcCompat()是否正确关闭 ESLint 重复规则 - 继续清理
eslint-config/src/configs/javascript.ts中已被 oxlint 明确覆盖的低风险规则 - 继续从
eslint-config/src/configs/typescript.ts向@vben/oxlint-config下沉规则,并结合lint:oxc:type-aware逐步启用 type-aware 规则 - 评估
eslint-config/src/configs/unicorn.ts中剩余规则是否值得继续保留 - 保留并持续观察
eslint-config/src/configs/node.ts、vue.ts、perfectionist.ts、jsonc.ts、yaml.ts、pnpm.ts、command.ts - 最后再评估是否要重新启用 tailwind 的 wrapping / unknown classes 规则
每迁移一组后都执行:
pnpm run lint:oxc
pnpm run lint:eslint
pnpm run lint
1.10 当前 scripts
// package.json
{
"scripts": {
"format": "vsh lint --format",
"lint": "vsh lint",
"lint:oxc": "oxlint .",
"lint:oxc:type-aware": "oxlint . --type-aware",
"lint:eslint": "eslint . --cache",
"lint:style": "stylelint \"**/*.{vue,css,less,scss}\" --cache",
},
}
1.11 当前 lefthook
当前 pre-commit 已包含如下链路:
pre-commit:
parallel: true
commands:
code-workspace:
run: pnpm vsh code-workspace --auto-commit
lint-md:
run: pnpm oxfmt {staged_files}
glob: '*.md'
lint-vue:
run: pnpm oxfmt {staged_files} && pnpm oxlint --fix {staged_files} && pnpm eslint --cache --fix {staged_files} && pnpm stylelint --fix --allow-empty-input {staged_files}
glob: '*.vue'
lint-js:
run: pnpm oxfmt {staged_files} && pnpm oxlint --fix {staged_files} && pnpm eslint --cache --fix {staged_files}
glob: '*.{js,jsx,ts,tsx}'
lint-style:
run: pnpm oxfmt {staged_files} && pnpm stylelint --fix --allow-empty-input {staged_files}
glob: '*.{scss,less,styl,html,vue,css}'
lint-package:
run: pnpm oxfmt {staged_files}
glob: 'package.json'
lint-json:
run: pnpm oxfmt {staged_files}
glob: '{!(package)*.json,*.code-snippets,.!(browserslist)*rc}'
1.12 验证步骤
- 全量运行
pnpm run lint:oxc,记录 oxlint 报告 - 对比当前 ESLint 规则覆盖情况,调整 oxlint 配置使两者对齐
- 逐个移除可替代的 ESLint 插件或规则组,每次移除后运行完整 lint 验证
- CI 中同时运行 oxlint 和 ESLint,确保双重覆盖期间无回归
1.13 待修复问题与改进项
以下问题按当前仓库状态重新整理。
[高] unicorn 插件启用后要同时收敛默认规则与 override
这个问题已经修复,但需要保留经验:
plugins一旦显式声明,必须手动包含unicorn- 启用后不只会打开我们手写的
unicorn/no-process-exit、unicorn/prefer-module - 还会带出 oxlint 默认启用的一部分
unicorn规则,需要按仓库现状显式关闭噪音项 - OXC
overrides.files不要继续使用?([cm])[jt]s?(x)这类 ESLint 风格的 extglob
[高] 使用 @oxlint/migrate 仅做审计,不直接落地配置
官方提供了 @oxlint/migrate 工具,可自动读取 ESLint flat config 生成对应 oxlint 配置。
对于当前仓库,@oxlint/migrate 更适合做“审计工具”,不适合直接生成或合并为最终配置,原因是:
- 当前仓库已经不是简单的
.oxlintrc.json形态,而是 workspace 包 + 模块化configs/* @vben/oxlint-config依赖自定义mergeOxlintConfigs(...)来保证settings、ignorePatterns、jsPlugins正确合并- Tailwind 规则依赖手写
jsPlugins和settings - 现有迁移流程还包含 ESLint 兼容层
eslint-plugin-oxlint
更合理的用法是:
npx @oxlint/migrate --details
不建议直接使用 --merge 覆盖当前仓库的真实配置结构。
[中] mergeOxlintConfigs 函数重复定义
这个问题已经修复。ESLint 侧的 oxlint.ts 已直接导入 @vben/oxlint-config 的 mergeOxlintConfigs,并在传入 buildFromOxlintConfig() 前剥离 extends:
import { mergeOxlintConfigs, oxlintConfig } from '@vben/oxlint-config';
import oxlint from 'eslint-plugin-oxlint';
export async function oxcCompat(): Promise<Linter.Config[]> {
const { extends: _extends, ...config } = mergeOxlintConfigs(oxlintConfig);
return oxlint.buildFromOxlintConfig(
config as Parameters<typeof oxlint.buildFromOxlintConfig>[0],
);
}
[中] 验证 oxcCompat() 是否正确关闭 ESLint 重复规则
ESLint 侧 javascript.ts 仍有较多规则,而其中很多已被 oxlint 的 correctness / suspicious category 覆盖。
eslint-plugin-oxlint 的 buildFromOxlintConfig() 理论上会自动关闭 ESLint 中被 oxlint 覆盖的规则。仍需验证 oxcCompat() 确实生效。如果正常工作,则 ESLint 侧无需手动清理这批重复规则。
建议验证方法:
# 临时在 oxlint 中启用一个 ESLint 也有的规则(如 no-debugger)
# 确认 ESLint 不再重复报告该规则
[中] eslint-plugin-import-x 已从当前仓库移除
eslint-plugin-import-x 相关迁移已经落地,当前仓库不再保留该依赖,import 规则集中定义在 internal/lint-configs/oxlint-config/src/configs/import.ts。
当前未再单独保留 import/newline-after-import。如未来仍需这类纯风格规则,应单独评估是否值得重新引入。
[中] eslint-plugin-n 仍不能完全移除
当前 ESLint 侧 node.ts 仍保留以下规则,尚未被 oxlint 接管:
| 规则 | 备注 |
|---|---|
n/handle-callback-err |
oxlint 未支持 |
n/no-deprecated-api |
oxlint 未支持 |
n/no-extraneous-import |
有自定义 allowModules,oxlint 未支持 |
n/no-unsupported-features/es-syntax |
oxlint 未支持 |
n/prefer-global/buffer |
oxlint 未支持 |
n/prefer-global/process |
oxlint 未支持 |
n/process-exit-as-throw |
oxlint 未支持 |
结论:eslint-plugin-n 当前仍需保留在 ESLint 侧。
[低] 已增加 lint:oxc:type-aware 入口,后续逐步启用规则
当前根 package.json 已提供:
pnpm run lint:oxc:type-aware
当前 @vben/oxlint-config 已显式保留一批关闭状态的 type-aware 规则,例如:
typescript/no-floating-promisestypescript/await-thenabletypescript/no-base-to-stringtypescript/no-unnecessary-type-assertion
后续建议基于实际报告量逐条开启,而不是一次性打开全部 type-aware 规则。
[低] --replace-eslint-comments 批量转换注释
代码中存在的 // eslint-disable 注释虽然 oxlint 兼容,但在第四阶段移除 ESLint 后会变得语义不清。官方迁移工具提供了批量转换选项:
npx @oxlint/migrate --replace-eslint-comments
建议在第一阶段完成后或第四阶段开始前执行。
[低] jsPlugins 已在仓库中使用,后续可继续减少 ESLint 依赖
当前仓库已经通过 jsPlugins 在 oxlint 侧接入 eslint-plugin-better-tailwindcss。对于 eslint-plugin-pnpm、eslint-plugin-command 等 oxlint 不内置的插件,未来仍可评估采用同样方式进一步减少对 ESLint 的依赖:
{
"jsPlugins": ["eslint-plugin-pnpm"],
"rules": {
"pnpm/some-rule": "warn"
}
}
第二阶段:oxfmt 替换 Prettier(大部分已完成)
当前状态:第二阶段的大部分工作已经落地,下面记录的是“当前仓库真实状态”和仍需继续验证的事项,而不是最初的待办清单。
参考文档:oxfmt CLI | Config Reference
2.1 当前 formatter 触点全景
| 位置 | 当前状态 | 说明 |
|---|---|---|
internal/lint-configs/oxfmt-config/ |
已完成 | 新增 @vben/oxfmt-config workspace 包 |
oxfmt.config.ts |
已完成 | 根级 formatter 配置入口,负责追加 ignorePatterns |
.prettierrc.mjs |
已移除 | 不再作为根入口 |
.prettierignore |
已移除 | 忽略模式已迁入 oxfmt.config.ts |
eslint-config/src/configs/prettier.ts |
已移除 | ESLint 不再集成 Prettier |
eslint-config/src/index.ts |
已完成 | 已无 prettier() 调用 |
eslint-config/package.json |
已完成 | 已移除 eslint-plugin-prettier 依赖 |
stylelint-config/index.mjs |
已完成 | 已移除 stylelint-prettier 插件和规则 |
stylelint-config/package.json |
已完成 | 已移除 prettier / stylelint-prettier 依赖 |
internal/node-utils/src/formatter.ts |
已完成 | 格式化工具已改为调用 oxfmt |
scripts/vsh/src/lint/index.ts |
已完成 | 已改为调用 oxfmt |
lefthook.yml |
已完成 | 已统一切换为 pnpm oxfmt |
pnpm-workspace.yaml catalog |
已完成 | 已移除 prettier、eslint-plugin-prettier、stylelint-prettier,并新增 oxfmt |
package.json 根 |
已完成 | 已依赖 @vben/oxfmt-config 与 oxfmt |
vben-admin.code-workspace |
已完成 | 已更新 workspace 引用 |
2.2 当前实际配置
当前仓库并未使用 .oxfmtrc.json,而是采用 “共享包 + 根入口” 的组织方式。
共享配置位于 internal/lint-configs/oxfmt-config/src/index.ts:
import { defineConfig as defineOxfmtConfig } from 'oxfmt';
const oxfmtConfig = defineOxfmtConfig({
printWidth: 80,
proseWrap: 'never',
semi: true,
singleQuote: true,
sortPackageJson: false,
trailingComma: 'all',
});
根级入口位于 oxfmt.config.ts:
import { defineConfig } from '@vben/oxfmt-config';
export default defineConfig({
ignorePatterns: [
'dist',
'dev-dist',
'.local',
'.claude',
'.agent',
'.agents',
'.codex',
'.output.js',
'node_modules',
'.nvmrc',
'coverage',
'CODEOWNERS',
'.nitro',
'.output',
'**/*.svg',
'**/*.sh',
'public',
'.npmrc',
'*-lock.yaml',
'skills-lock.json',
],
});
需要注意两点:
- 当前 formatter 的
printWidth明确设为80 .editorconfig的max_line_length仍为100
也就是说,当前仓库实际上采用的是“oxfmt 显式配置优先于 .editorconfig”的策略,这一点需要在后续验证中保持一致。
2.3 @vben/oxfmt-config workspace 包
当前包结构与其他 lint-config 包保持一致:
internal/lint-configs/oxfmt-config/
package.json
src/index.ts
{
"name": "@vben/oxfmt-config",
"version": "5.6.0",
"private": true,
"type": "module",
"files": ["dist"],
"main": "./dist/index.mjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs"
}
},
"dependencies": {
"oxfmt": "catalog:"
}
}
这个包当前承担三件事:
- 集中管理
oxfmt版本依赖 - 导出共享格式化配置对象
- 供根级
oxfmt.config.ts和其他程序化场景复用
2.4 已完成的替换范围
| 原方案 | 当前状态 |
|---|---|
prettier |
已移除,当前统一使用 oxfmt |
eslint-plugin-prettier |
已移除 |
stylelint-prettier |
已移除 |
@vben/prettier-config |
已替换为 @vben/oxfmt-config |
2.5 已完成的操作
以下动作已在当前仓库完成:
- 创建
@vben/oxfmt-configworkspace 包 - 新增根级
oxfmt.config.ts - 将
scripts/vsh/src/lint/index.ts切换到oxfmt - 将
lefthook.yml切换到pnpm oxfmt - 删除 ESLint 中的 Prettier 集成
- 删除 Stylelint 中的 Prettier 集成
- 将
internal/node-utils中的格式化能力切换到oxfmt - 删除
.prettierrc.mjs、.prettierignore和旧的@vben/prettier-config - 更新根
package.json、pnpm-workspace.yaml、vben-admin.code-workspace
2.6 下一步只保留验证项
第二阶段当前不再需要按“迁移步骤”执行,剩余工作主要是验证和收口:
- 重新全量运行
pnpm run lint,确认vsh lint当前默认行为与预期一致 - 明确
oxfmt.config.ts是否作为 CLI 与编辑器共同入口;如团队工具链存在兼容性差异,再决定是否需要补.oxfmtrc.json - 决定
printWidth: 80与.editorconfig的max_line_length = 100是否继续并存 - 评估是否启用 oxfmt 的额外能力,例如
sortImports、sortTailwindcss
2.7 oxfmt 额外能力评估
oxfmt 提供了 Prettier 没有的扩展特性,可选启用:
| 特性 | 说明 | 当前状态 / 建议 |
|---|---|---|
sortImports |
import 语句排序,灵感来自 eslint-plugin-perfectionist/sort-imports |
可评估是否替代 ESLint 侧部分排序职责 |
sortTailwindcss |
替代 prettier-plugin-tailwindcss |
当前仓库仍优先使用 oxlint jsPlugins 方案 |
sortPackageJson |
自动排序 package.json 字段 |
当前共享配置显式设为 false |
insertFinalNewline |
文件末尾添加换行 | 与 .editorconfig 的 insert_final_newline=true 一致 |
2.8 文件类型覆盖说明
oxfmt 对不同文件类型的处理方式:
| 文件类型 | 格式化方式 |
|---|---|
| JS / TS / JSX / TSX | oxfmt 原生格式化 |
| Vue SFC | oxfmt 原生格式化(<script> / <template>) |
| TOML | oxfmt 原生格式化(via taplo) |
| CSS / SCSS / Less | 内部委托 Prettier |
| HTML | 内部委托 Prettier |
| YAML / Markdown / GraphQL | 内部委托 Prettier |
重要:CSS 等非 JS/TS 文件仍然通过 oxfmt 内部委托 Prettier 处理,因此
oxfmt一个命令即可覆盖主要文件类型;仓库中不需要再单独安装prettier。
2.9 当前风险与注意事项
- 配置入口一致性:当前实际入口是
oxfmt.config.ts,需确认 CLI、编辑器、CI 是否都按这份配置执行 - 行宽来源不一致:
oxfmt显式printWidth: 80,.editorconfig为100,需要明确这是有意保留还是待统一 - 格式化差异:首次重新全量格式化时,仍可能出现与历史 Prettier 输出不同的 diff
- 扩展能力取舍:
sortImports、sortTailwindcss是否启用会直接影响 ESLint / oxlint 的职责边界 - IDE 配置:团队成员仍需统一使用 oxfmt 对应扩展或 LSP(
oxfmt --lsp)
第三阶段:Vite / Rolldown 自动集成 oxc
前提:Vite 通过 Rolldown 自动集成 oxc 能力后,以下依赖将被自然替代,无需手动操作。
| 当前依赖 | 替代方式 |
|---|---|
esbuild ^0.27.4 |
Rolldown 内置 oxc-transform / oxc-parser |
html-minifier-terser ^7.2.0 |
oxc-minifier(或 Rolldown 内置 minify) |
3.1 操作步骤
- 跟踪 Vite / Rolldown 版本更新,确认 oxc 集成进度
- 升级 Vite 到集成 Rolldown 的版本后,移除显式的
esbuild依赖 - 验证构建产物体积和功能无回归
- 评估
html-minifier-terser是否可被 Rolldown 内置能力替代
第四阶段:完全移除 ESLint(远期)
前提:oxlint 完全支持 Vue SFC 模板 lint 及所有当前保留插件的功能。
4.1 替换范围
| 当前依赖 | 替代方案 |
|---|---|
eslint |
移除 |
eslint-plugin-vue + vue-eslint-parser |
oxlint Vue 支持 |
eslint-plugin-better-tailwindcss |
oxlint tailwindcss 支持或其他方案 |
eslint-plugin-jsonc / eslint-plugin-yml |
oxlint 或独立 linter |
eslint-config-turbo |
移除 |
eslint-plugin-pnpm |
oxlint 或独立检查 |
eslint-plugin-command |
oxlint 或移除 |
@vben/eslint-config |
改写为 @vben/oxlint-config 或移除 |
4.2 操作步骤
- 持续跟踪 oxlint 的 Vue / JSON / YAML 支持进展
- 当 oxlint 规则覆盖度满足要求时,全面切换
- 移除
internal/lint-configs/eslint-config/及所有 ESLint 相关依赖 - 更新 CI 和
lefthook配置
迁移风险与注意事项
- 规则对齐:oxlint 的规则命名和行为可能与 ESLint 插件不完全一致,需逐条验证
- Vue SFC 支持:oxlint 对
<template>的 lint 能力仍是最大瓶颈,第一阶段务必保留eslint-plugin-vue - CI 稳定性:共存期间两套工具可能对同一问题重复报告,需通过配置互相排除
- 团队习惯:IDE 插件需要同步配置 oxlint / oxfmt 对应扩展
- 版本锁定:oxc 生态仍在快速迭代,建议锁定 minor 版本,升级时做全量验证
预期收益
| 指标 | 预期改善 |
|---|---|
| lint 速度 | 通用规则部分显著提升 |
| 依赖数量 | 第一阶段已明显减少,最终可继续下降 |
| 安装体积 | 显著减少(ESLint 插件依赖树庞大) |
| CI 时间 | lint 阶段耗时大幅缩短 |
| 维护成本 | 减少 ESLint / Prettier 插件兼容性问题 |