Dify 前端静态检查体系:基于 Vite+ 的 vp check、Oxlint、类型感知 Lint 与 ESLint 非代码回退 Dify 前端静态检查体系基于 Vite 的 vp check、Oxlint、类型感知 Lint 与 ESLint 非代码回退【免费下载链接】difyBuild Agentic workflows, RAG pipelines, with rich AI model and tool support on one collaborative workspace. Deploy on cloud, VPC, or self-hosted, so teams move from prototype to production without rebuilding the stack.项目地址: https://gitcode.com/GitHub_Trending/di/difyDify 仓库的前端静态检查由 Vite 的vp check命令统一驱动它把 Oxfmt 格式化、Oxlint 代码质量规则和 TypeScript 7 原生编译器诊断合并在同一条流水线中根命令再追加 ESLint 对非代码文件的兜底检查。本文围绕 静态检查指南 展开结合 lint.config.ts、vite.config.ts、eslint.config.mjs 等真实配置源码讲清每条pnpm命令背后的作用域划分、规则基线、自动修复工作流与迁移取舍帮助你在贡献 Dify 前端代码时建立与 CI 完全一致的本地检查能力。核心命令全仓库检查与自动修复在仓库根目录运行完整静态检查pnpm check在运行同样检查前先应用安全修复pnpm check:fixCI 与本地开发共用同一份根 vite.config.ts 配置保证两侧检查结果一致。这两个脚本在根 package.json 中的实际定义为{ check: vp check pnpm lint:eslint, check:fix: pnpm lint:eslint:fix vp check --fix, lint:oxlint: vp lint, lint:eslint: eslint --concurrencyauto, lint:eslint:fix: eslint --fix --concurrencyauto }从源码结构看pnpm check是一个两段式命令vp check负责代码文件JS/JSX/TS/TSX 等的格式化、Oxlint 规则与类型诊断随后pnpm lint:eslint对非代码文件做兜底校验。check:fix则先修复 ESLint 可处理的非代码问题再执行vp check --fix把可自动修复的问题一次性处理掉。缩小检查范围路径参数与类型检查的作用域格式化和 lint 可以传入具体路径来缩小范围但类型检查始终是仓库级别的vp check web/app/components packages/dify-ui/src/button vp check --fix web/app/components packages/dify-ui/src/button这意味着即使你只改了一个组件目录vp check仍会完整跑一遍全仓库的类型检查。这一设计避免局部修改破坏全局类型契约的问题但也要接受全量类型检查带来的耗时。页面级无障碍诊断lint:a11y 与 --deps 依赖模式针对 Web 包的 JSX 无障碍规则可以用lint:a11y对选定文件或目录单独执行。包含括号等 shell 元字符的路径要加引号pnpm --dir web lint:a11y app/(commonLayout)/app/(appDetailLayout)/layout.tsx使用依赖模式可以解析入口文件的传递性本地导入包括路径别名、re-export 和动态 import再对得到的 JSX/TSX 文件做 lintpnpm --dir web lint:a11y --deps app/(commonLayout)/app/(appDetailLayout)/layout.tsx这条命令在 web/package.json 中映射到node ./scripts/lint-a11y.mjs。查看 web/scripts/lint-a11y.mjs 的实现可以确认其工作原理脚本从vite-plus中定位捆绑的oxlint包取其bin/oxlint可执行文件参数解析区分--deps标志与目标路径web前缀的相对路径会解析到仓库根目录其余相对路径解析到web/目录--deps模式下调用 TypeScript 的resolveModuleName基于web/tsconfig.json的编译器选项含路径别名递归解析入口文件的导入跳过外部库导入与.d.ts声明文件过滤出.jsx/.tsx源文件最终以oxlint -c web/scripts/a11y/oxlint.config.ts files启动检查工作目录为web/。而 web/scripts/a11y/oxlint.config.ts 直接复用主基线导出的webJsxA11yRulesimport { webJsxA11yRules } from ../../../lint.config.ts export default { categories: { correctness: off }, plugins: [jsx-a11y], rules: webJsxA11yRules, }这正是文档强调页面级诊断是本地工具仓库级无障碍规则基线仍由lint.config.ts持有并被常规vp check强制执行的原因页面脚本只是把 lint.config.ts 中导出的同一份webJsxA11yRules覆盖alt-text、aria-*、no-autofocus、no-static-element-interactions等 30 余条jsx-a11y规则单独拿出来按页运行两份配置天然不会漂移。非代码文件的 ESLint 回退JSON、YAML、TOML、MarkdownOxlint 插件无法提供自定义 parser 和文件语言因此 JSON、JSONC、JSON5、YAML、TOML、Markdown 交由 ESLint 处理。单独运行回退检查pnpm lint:eslint package.json pnpm-workspace.yaml web/docs pnpm lint:eslint:fix package.json pnpm-workspace.yaml web/docseslint.config.mjs 展示了这套回退配置的完整形态项目作用域globalIgnores先排除一切文件再重新放行cli/、e2e/、packages/、sdks/nodejs-client/、web/及根目录package.json、pnpm-workspace.yaml、eslint.config.mjs、lint.config.ts、vite.config.ts代码文件全局忽略**/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx}被整体 ignore注释写明代码文件仅由 Oxlint 处理这是迁移取舍的核心边界按文件类型挂载语言插件JSON/JSON5/JSONC 用jsonc/x语言与eslint-plugin-jsoncYAML 用yml/yamlTOML 用toml/tomlMarkdown 用markdown/gfm配合markdown-preferences与md插件有业务语义的规则tsconfig文件的compilerOptions键序强制按 eslint.config.mjs 中 120 余项固定顺序排序pnpm-workspace.yaml用eslint-plugin-pnpm强制shellEmulator: true、trustPolicy: no-downgrade并校验 catalogweb/i18n/**/*.json挂载本地dify插件校验 i18n 占位符一致性、扁平 key 与多余 key。规则基线lint.config.ts 与 vite.config.ts 的 lint 块主要规则基线位于 lint.config.ts通过根 vite.config.ts 的lint字段接入export default defineConfig({ lint: lintConfig, // ... })从 lint.config.ts 的主配置可以看到几个关键设计点显式规则快照配置注释明确说明这是迁移前生效的 ESLint 配置的 Oxlint 等价物规则逐条显式声明避免上游 preset 的变更静默改变 lint 基线。策略是优先使用 Oxlint 原生规则兼容的 ESLint 规则通过 Oxlint 的jsPlugins机制运行。文件头部注释强调不要整体导入上游 preset新规则要有意启用并先审查存量违规。插件分层plugins声明原生 Oxlint 插件import、jsdoc、jsx-a11y、node、react、typescript、unicorn、vitestjsPlugins按规则命名空间排序加载 JS 插件包括tanstack/eslint-plugin-query、eslint-plugin-antfu、eslint-plugin-perfectionist、eslint-plugin-regexp等并注册了本地插件dify指向./web/plugins/eslint/index.js实现dify/prefer-tailwind-icons这类项目专属规则。关键 optionslint.config.tsoptions: { reportUnusedDisableDirectives: warn, respectEslintDisableDirectives: false, typeAware: true, typeCheck: true, },其中respectEslintDisableDirectives: false是文档特别强调的一点ESLint 注释无法掩盖 Oxlint 的诊断。因此抑制注释必须各归各主——lint.config.ts中的代码规则用oxlint-disableeslint.config.mjs中的非代码规则才用eslint-disable。 4.忽略范围ignorePatterns排除了api/**、docs/**、dify-agent/**、docker/**等非前端目录、**/*.d.{ts,cts,mts}声明文件以及packages/contracts/**生成的契约包该包目前只有 Oxfmt 这一道质量关卡。 5.按目录的 overridesweb 目录下额外启用no-barrel-files、TanStack Query 系列规则与 React 规则web/**/*.tsx应用webJsxA11yRulesStorybook 文件应用 storybook 插件规则web 源码还通过no-restricted-imports禁止直接引入next/image、next/font、base-ui/react、floating-ui/*等模块强制走/next封装与langgenius/dify-ui组件原语。可选的 Tailwind 规范类检查Tailwind 规范类清理是可选的——加载该 JS 插件会带来明显的 lint 启动开销默认的pnpm check不加载它。需要时用pnpm lint:tailwind # 检查 web/ 与 packages/dify-ui/ pnpm lint:tailwind:fix # 应用安全替换对照根 package.json这两个脚本实际是TAILWIND_CANONICAL_CLASSEStrue vp lint web packages/dify-ui TAILWIND_CANONICAL_CLASSEStrue vp lint --fix web packages/dify-uilint.config.ts 通过读取环境变量TAILWIND_CANONICAL_CLASSES条件注入eslint-plugin-better-tailwindcss插件和better-tailwindcss/enforce-canonical-classes规则warn 级别collapse: false、logical: false并在 settings 中为其指定cwd: web/、入口样式表web/app/styles/globals.css、16px 根字号——这与 vite.config.ts 中 Oxfmt 的sortTailwindcss配置使用同一份样式表与 16px 根字号保证格式化排序与规范类检查对类名合法性的判断一致。自动修复工作流编辑器与提交钩子自动修复分三层全部复用同一套 Vite 组合检查编辑器配置 Oxc 与 ESLint 编辑器扩展在保存时分别应用各自的修复。提交钩子commit hook 运行vp staged。从根 vite.config.ts 的staged配置可以看到委托关系staged: { [lintFiles]: checkFix, // *.{js,cjs,mjs,jsx,ts,cts,mts,tsx} → vp check --fix [eslintFiles]: [eslintFix, formatFix], // *.{json,jsonc,json5,md,yml,yaml,toml} → eslint --fix vp fmt [formatOnlyFiles]: formatFix, // *.{mdx,css,scss,less,html,vue,svelte,gql,graphql,hbs,handlebars} → vp fmt .vite-hooks/*: sh -n, },即暂存的代码文件交给vp check --fix含 ESLint 非代码回退暂存的 Markdown/CSS 等纯格式文件只跑vp fmt。 3.注意提交前务必审查自动修复结果。JS 插件被允许提供 fix其修复行为不一定与 Oxlint 原生规则完全一致。类型感知 Lint 与独立类型检查根配置同时开启了typeAware与typeCheck因此vp check既运行类型感知规则也通过TypeScript 7 原生编译器仓库的typescript/native依赖见根 package.json 与 web/package.json跑完整类型诊断。Web 包仍单独运行既有的 TSSLint 规则集pnpm --dir web lint:tss该命令在 web/package.json 中定义为tsslint --project tsconfig.json其 devDependencies 依赖tsslint/cli、tsslint/compat-eslint、tsslint/config。类型检查建议也覆盖编辑器体验所有已打开文件应能看到编辑器的 TypeScript 提示。提交或推送前运行完整静态检查pnpm check存量错误基线oxlint-suppressions.json 与批量抑制存量的 Oxlint error 诊断记录在根目录的oxlint-suppressions.json基线中该文件同时出现在 vite.config.ts 的generatedIgnores里不会被格式化/检查误伤。Oxlint 只会报告超出该按文件规则基线的新增 errorESLint 没有这类批量抑制基线warning 保持可见且不会让常规 lint 命令失败。批量抑制标志在当前捆绑的 Oxlint 版本中可用但从vp lint --help中被隐藏。要在仓库根目录运行使所有包共用同一份基线pnpm lint:oxlint --suppress-all # 记录当前所有 error 为基线 pnpm lint:oxlint --prune-suppressions # 清理已不存在的基线条目一个已知局限Oxc 编辑器扩展尚未应用批量抑制基线因此编辑器可能仍显示 CLI 已抑制的问题——以 CLI 结果为准。已知迁移缺口与取舍ESLint 被有意限制在非代码文件上其余限制与已接受的迁移取舍如下摘自 静态检查指南领域当前状态仅代码的兜底规则ESLint 全局忽略所有代码文件。六条核心兜底规则、JS 的dot-notation及其他仅代码 ESLint 检查只以注释形式列出而非可执行配置见 eslint.config.mjs 的迁移取舍注释。声明文件Oxlint 排除声明文件且 ESLint 不再处理代码原先的 223 规则声明文件快照和 CLI 声明导入限制均不再强制执行。生成的契约包两个 linter 与 Vite 类型检查都忽略packages/contracts/**Oxfmt 是该包唯一暂存质量步骤。非 JavaScript 格式Oxlint 插件无法提供自定义 parser 或文件语言ESLint 覆盖 JSON、JSONC、YAML、TOML、Markdown 的语义规则Oxfmt 负责其格式化。Markdown 代码块ESLint 校验 Markdown 文档本身但围栏内的 JavaScript/TypeScript 块不再经过原重叠 preset该事项被搁置而非复制 Oxlint 规则集。override 作用域设置三条 Dify UI Tailwind 规则随 ESLint 代码路径一并禁用Oxlint 仍全局应用 web 的react-x.additionalStateHooks设置见 lint.config.ts 的正则/^use\w*State(?:s)?|useAtom$/u因为它无法把设置限定到某个 override。Oxlint disable 严重度Oxlint 只接受根级reportUnusedDisableDirectives当前保持warn原先 Dify UI 专属的 ESLinterror严重度不再应用于代码文件。配套约定再强调一次抑制注释只能属于一个 linter。代码规则lint.config.ts用oxlint-disable非代码规则eslint.config.mjs用eslint-disable。由于respectEslintDisableDirectives被显式设为falseESLint 注释对 Oxlint 诊断无效。引入新插件或新规则的流程文档给出的引入顺序值得固化为团队习惯优先 Oxlint 原生规则。若没有等价物先在代表性文件上验证该规则能否通过 Oxlint JS 插件正常运行。记录而非回填Oxlint 无法覆盖的代码规则应记录为迁移缺口而不是加进 ESLint——ESLint 配置保留给 Oxlint 无法解析的非代码语言。不引入 Antfu ESLint 配置作为依赖也不启用 Oxlint 已覆盖的规则新增规则要有意识地启用并先审查存量违规。运行环境前提根 package.json 声明packageManager为pnpm11.25.0Node 要求^24.20.0devEngines指定 24.20.0 且onFail: download安装依赖时 pnpm 会按声明准备运行时prepare脚本会执行vp config即 Vite 的初始化钩子pnpm install后自动运行前端检查只针对前端包web/、packages/、cli/、e2e/、sdks/nodejs-client/等Python 侧的api/、dify-agent/均被 lint.config.ts 的ignorePatterns排除两套代码库互不干扰。掌握以上链路后你可以在提交前用pnpm check得到与 CI 完全一致的判定用vp check paths做快速局部验证用lint:a11y --deps对新页面做范围化的无障碍体检并通过oxlint-suppressions.json基线机制让存量问题不阻塞增量改进。【免费下载链接】difyBuild Agentic workflows, RAG pipelines, with rich AI model and tool support on one collaborative workspace. Deploy on cloud, VPC, or self-hosted, so teams move from prototype to production without rebuilding the stack.项目地址: https://gitcode.com/GitHub_Trending/di/dify创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考