浮头导航网

专注编程技术分享的开发者社区

项目很少出现“技术债”?我总结了 5 个前端工程的基本约束

不是说因为我们写得多牛,而是我们从第一天就立了 5 个基本工程约束,这些规则不是高深技术,而是工程底线。坚持这几个点,不一定能写出完美代码,但至少能避免那种“越写越乱、越维护越痛苦”的局面。


1. 所有逻辑必须可测试 —— 哪怕只是基本的 mock

“写业务不用写单测吧?”

我们早期的确也没有测试,但我们有个共识: “可测性”是模块合格的基础能力

例如一个 API 请求函数:

//  直接在组件里调用
const fetchUser = async () => {
const res = await axios.get('/api/user')
setState(res.data)
}

我们会主动抽出:

//  utils/api/user.ts
export async function fetchUser() {
const res = await request.get('/api/user')
return res.data
}

组件中调用:

const load = async () => {
const user = await fetchUser()
setState(user)
}

哪怕这个模块你暂时没写测试,也可以未来 mock。不是写不写测试的问题,是结构上必须可测。


2. 所有配置和工具链都必须文档化 & 脚手架化

配置复杂是技术债的第一大来源。

我们内部所有 Vite、ESLint、TSConfig、Stylelint、commitlint、husky 的配置,全部在一个 template/config 仓库里,并通过 create-project CLI 自动生成。

新建项目流程:

npx @our-team/create-project my-app

就能生成带全套约束的工程结构。

每次有新成员,只需要一句话:

“请从 CLI 拉起工程模板,手动搭项目我们不维护。”

我们甚至把 .editorconfig、.prettierignore、.vscode/settings.json 也包进去。


3. 拒绝“一次性”的逻辑代码

我们总结过一个现象:

项目中 90% 的“技术债”,其实不是写得差,而是“写了个一次性的东西,结果被复用起来了”。

例如写一个上传组件,临时加了个 hook:

useEffect(() => {
document.body.style.overflow = 'hidden'
return () => {
document.body.style.overflow = ''
}
}, [])

这个代码在某个场景 OK,后来别人复制过去也用了它,但页面结构不同,结果出现滚动异常。

我们现在的做法是:一切不是“组件通用”的逻辑,必须写注释说明场景适用条件。

甚至工具函数开头会写:

/** * 仅适用于弹窗场景中,用于锁死背景滚动 * 不适用于嵌套 iframe 或 shadow DOM 中 */

防止“拿来就用”的行为。


4. 不允许多人维护的页面使用匿名函数 / 闭包乱穿

我们有条硬性规定:

所有 team-shared 页面(如 layout、dashboard、全局 hook)不允许存在闭包调用状态更新函数,必须封装成独立方法。

这是我们以前踩过的一个坑:

const [count, setCount] = useState(0)
useEffect(() => {
const timer = setInterval(() => {
setCount(count + 1) // 这个 count 其实永远是 0
}, 1000)
}, [])

重构后:

useEffect(() => {
const timer = setInterval(increment, 1000)
return () => clearInterval(timer)
}, [])
function increment() {
setCount(prev => prev + 1)
}

不仅闭包安全,而且容易测试、易于代码搜索。

这也是我们不允许“匿名箭头函数当核心业务函数”的原因之一:可维护性远比可写性重要。


5. 所有可复用组件都必须写 usage demo

我们早期封装了一堆组件,但文档没人写,最后大家都懒得用,干脆自己手撸。形成了大量重复组件。

后来的约束是:

  • 每个 components/ 下的组件目录,都必须包含 __demo__/index.tsx
  • 内部项目自建 Storybook,开发时自动引入展示
  • 提交 CI 时,若组件没有 __demo__,CI 报错

这样强制你思考组件边界、props 设计、可控状态,并且顺带解决了一部分测试问题。

例如:

/components
/UserCard
index.tsx
style.scss
__demo__
index.tsx ← 示例文件,必须有

最后的话

我们不是靠“约定”或“大家自觉”来避免技术债,而是靠结构性约束 + 工具自动化来抵御它。

只要你让“混乱”这件事发生一次,下次它就会被复制。

我们总结的经验是: “能自动化的就不要靠人记住,能写进 CLI 的就别写进 README。”

这样,你就不会等到 3 个月后才说:

“唉,这一坨代码也太难维护了吧。”

你们也有这样的感受吗?

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言