Craft Agents ESLint自定义规则实践:no-localstorage等规则如何防止架构腐化
2026/9/15 20:19:35 网站建设 项目流程

Craft Agents ESLint自定义规则实践:no-localstorage等规则如何防止架构腐化

【免费下载链接】craft-agents-oss项目地址: https://gitcode.com/GitHub_Trending/cr/craft-agents-oss

Craft Agents 是一款开源的 AI Agent 协作桌面应用。它的 Electron 客户端内置了一整套 ESLint 自定义规则(如 no-localstorage、no-hardcoded-z-index),用机器可执行的检查来替代口头约定,从根源上防止大型前端项目的架构腐化。本文将带你逐个看懂这些规则的设计思路与落地方式。

为什么需要 ESLint 自定义规则?

通用的 ESLint 规则只能发现语法层面的问题,而"架构腐化"往往来自更隐蔽的坏习惯:

  • 有人随手用localStorage存了个配置,设置就散落在浏览器沙箱里;
  • 有人直接写死navigator.platform判断系统,跨平台兼容性悄悄埋雷;
  • 有人硬编码zIndex: 9999,层级系统彻底失控。

Craft Agents 的做法是:把团队的架构约定写成自定义 ESLint 规则,让违规代码在保存时就被拦截。规则集中放在 apps/electron/eslint-rules/ 目录,统一注册到 eslint.config.mjs。

规则一:no-localstorage —— 统一持久化出口

这是最典型的"防腐化"规则。no-localstorage.cjs 会拦截所有localStorage.getItem()window.localStorage等写法,并给出明确指引:

请把设置存到~/.craft-agent/preferences.json,通过window.electronAPI.readPreferences/writePreferences读写。

文件头部的注释把设计动机写得明明白白:基于文件的配置可迁移、可手动编辑、集中管理、便于调试。该规则还做了精细的 AST 判断——既拦截成员表达式访问,也拦截把localStorage直接当参数传递的写法,同时放过纯类型引用,避免误报。

它背后的偏好 API 实现在 packages/shared/src/config/preferences.ts,规则报错信息会直接指向这个文件,开发者"看到报错就知道去哪修"。

规则二:no-direct-navigation-state —— 收敛导航状态

no-direct-navigation-state.cjs 只针对AppShell.tsx一个文件:禁止在点击回调里直接调用setSidebarMode(),必须走navigate(routes.xxx())

这样能保证三件事:URL 与深度链接一致、历史记录支持前进后退、进入新视图自动选中第一项。规则内部还处理了 ESLint 9 移除context.getAncestors()的兼容问题,通过sourceCode.getAncestors()白名单放行事件监听器内部的合法调用。

规则三:跨平台规则 —— 消灭隐性兼容 Bug

  • no-direct-platform-check.cjs:禁止直接读navigator.platform,强制使用@/lib/platform导出的isMac / isWindows / isLinux / PATH_SEP,并对"规则真相源"platform.ts本身豁免。
  • no-hardcoded-path-separator.cjs:捕获filePath.startsWith(dir + '/')这类在 Windows 上必然出错的写法,引导使用pathStartsWith()工具函数。

这两条规则的共同点是:错误信息不只要报"错了",还要报"应该怎么改、去哪个模块改"

规则四:样式与交互一致性规则

UI 层的腐化往往最直观。Electron 应用中还配置了两条样式规则:

  • craft-styles/no-hardcoded-z-index(no-hardcoded-z-index.cjs):拦截zIndex: 400这类字面量,只允许 CSS 变量 token(如var(--z-floating-menu, 400))或命名常量。
  • craft-styles/no-nonstandard-shadows(no-nonstandard-shadows.cjs):只放行配置中列出的shadow-minimalshadow-modal-small等白名单阴影类,保证视觉质感统一。

UI 共享包 packages/ui/eslint-rules/ 里还有更细粒度的no-floating-z-tokens-in-island.cjs,专门约束"标注岛"组件必须使用--z-island专属 token,防止浮层层级互相打架。

架构边界的守护者:no-restricted-imports

在 eslint.config.mjs 中,除了自定义规则,还利用内置的no-restricted-imports划出了后端抽象边界:主进程代码禁止直接import具体的 Agent 提供方 SDK(如 claude-agent、pi-agent),必须经由@craft-agent/shared/agent/backend的统一抽象层。

这等于用 ESLint 强制了"依赖倒置"——未来更换或新增 Agent 后端时,上层代码一行都不用改。类似地,craft-links/no-direct-file-open(no-direct-file-open.cjs)禁止渲染进程直接调用openFile(),确保文件打开一律经过链接拦截器,从而支持应用内预览。

规则如何生效:配置即策略

所有规则在 eslint.config.mjs 中以 flat config 格式注册到craft-agentcraft-platformcraft-styles等命名空间插件下,并按严重级别分档:

规则级别守护的架构约定
no-direct-navigation-stateerror导航走统一路由
no-localstoragewarn持久化走文件配置
no-direct-platform-checkerror平台检测单一出口
no-hardcoded-path-separatorwarn跨平台路径安全
no-hardcoded-z-indexerror层级 token 化
no-nonstandard-shadowserror(带白名单)阴影样式统一

值得一提的是,配置中还保留了受控例外清单:少量未完成迁移的文件被显式列出并关闭阴影规则,迁移完成后即可移除。这种"默认严格、例外显式化"的策略,比一刀切更容易在真实项目中落地。

给项目的启示

Craft Agents 的实践给出了一套可复用的"防腐化"方法论:

  1. 约定要可执行:写进代码评审的口头约定,不如一条 100 行的自定义规则;
  2. 报错即指引:错误信息里直接给出正确写法和目标模块路径(规则源码中随处可见 "Use xxx instead");
  3. 按模块分层治理:packages/shared/eslint-rules/ 的no-inline-source-auth-check与 Electron 侧规则复用同一份逻辑,保证共享包与客户端遵循同一套架构原则;
  4. 例外要显式化:白名单和例外文件都写在配置里,迁移进度一目了然;
  5. 配套单测:如 no-hardcoded-z-index.test.ts 为规则本身编写测试,确保检查逻辑不失效。

对新手来说,这套机制的学习成本很低——你只需要运行一次 lint,就能顺着报错信息读懂整个项目的架构约定。这正是自定义 ESLint 规则最有价值的地方:它不只是查错的工具,更是团队架构知识的活文档

总结

Craft Agents 用 no-localstorage、no-direct-navigation-state、no-hardcoded-z-index 等十余条自定义 ESLint 规则,把"统一持久化、统一导航、统一层级、抽象后端"等架构原则固化进了开发流程。规则源码集中、错误信息友好、例外显式可控,这套实践对任何正在长大的前端项目都有很强的参考价值。

【免费下载链接】craft-agents-oss项目地址: https://gitcode.com/GitHub_Trending/cr/craft-agents-oss

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询