前端规范可以这样做🚀🚀🚀

188 阅读6分钟

背景

目前所在业务线的前端 js 代码居多,且没什么规范,效率实在是太低了,蚌埠不住了,是时候改一改了

前言

程序开发规范,是软件工程中确保代码质量和团队协作效率的重要一环。通过规范,提升软件产品的稳定性和可靠性,降低维护成本,同时也有助于团队成员间的沟通交流和知识传承。

规范的优缺点

优点:

  1. 保障代码交付质量
  2. 降低沟通成本、阅读成本、理解成本
  3. 降低重构/迁移成本

缺点:

  1. 对团队成员的自觉性要求较高
  2. 对团队成员的技术水平有一定的要求

规范可分为

  1. 可控规范:可通过一些lint工具规范化
  2. 不可控规范:无法通过工具检测到的,eg:变量名,文件名,设计模式

规范方向

  1. 文件(夹)划分规范
  2. 文件(夹)命名规范
  3. git规范:commitlint
  4. lint规范:eslint,prettier,stylelint
  5. 代码规范
  6. ts规范

看个现状

改造前

img

改造后(还有优化空间,就打个样,是不是清晰了很多)

imgimg

状态/类型的写法(每个类型用到的地方都要写一遍注释)

image-20241031110727532.png

推行TS

官网对它的定义是:A Static Type Checker(静态类型检查器)

TypeScript is also a programming language that preserves the runtime behavior of JavaScript. TypeScript never changes the runtime behavior of JavaScript code.


译:TypeScript 也是一种保留了 JavaScript 运行时行为的编程语言。TypeScript 永远不会改变 JavaScript 代码的运行时行为

也就是说,即使 TypeScript 认为代码存在类型错误,也保证 js 以相同的方式运行。

定位

我把 ts 定位为代码规范的基础辅助工具,使用 ts 旨在提高开发效率和代码质量。

目的

  1. 类型提示

借助 IDE 工具的提示功能,更好更快的写代码

  1. 安全编程

当调整类型时,ts 通过类型报错将代码问题从运行时前置到编译时,大大降低 bug 率

  1. 规范代码

强类型的定义能够更好的规范代码逻辑,在大型项目中,规范比灵活更重要

  1. 降低阅读、维护、拓展成本

字段类型的定义,让开发人员能更高效的识别、修改、溯源

  1. 提高渐进式重构的安全性和效率

在代码重构阶段,类型检查能极大地保障代码的安全迁移调整

  1. 工具链基石

众多工具通过类型定义将第三方库联系起来,极大地降低了工具开发成本

开发视角的区别

js:聚焦于功能的实现,弱化了类型定义和入参设计

ts:聚焦于程序的设计,加强了类型定义和入参设计

TS学习推荐文章

juejin.cn/post/687211…

文件夹分类

src
├───📁 api/                 
│   └───📁 common/             # 维度跟 router 保持一致
│       ├───📄 index.ts
│       └───📄 type.ts
├───📁 assets/
│   ├───📁 images/
│   └───📁 styles/
├───📁 components/                 
│   ├───📁 base/                  # 公共基础组件
│   │   └───📁 LayoutPro/           # 文件名以大驼峰命名
│   │       ├───📄 index.scss
│   │       └───📄 index.tsx    
│   └───📁 business/              # 公共业务组件
│       └───📁 OrgSelect/           # 文件名以大驼峰命名
│           ├───📄 index.scss
│           └───📄 index.tsx
│
├───📁 constants/
├───📁 hooks/
│   └───📄 useTableRequest.ts   # hook以use开头,小驼峰命名
├───📁 mock/
├───📁 pages/
│   └───📁 Home/                # 维度跟 router 保持一致,文件名跟组件一致:大驼峰
│       ├───📄 index.scss
│       └───📄 index.tsx
├───📁 router/                  # 以左侧一级菜单维度拆分
│   ├───📄 custom.ts
│   ├───📄 shopping.ts
│   └───📄 index.ts
├───📁 stores/
├───📁 types/                   # 全局 ts
└───📁 utils/                   # 文件以功能命名,eg:password.ts,day.ts, card.ts

代码规范

我们定义了一些命名规则来区分常规命名和统一认知

ts

  1. interface:大写 i 开头,大驼峰命名,eg:IProps
  2. type:大写 t 开头,大驼峰命名,eg:TPages
  3. enum:大写 e 开头,大驼峰命名,eg:EStatus
  4. 状态/类型的定义须用枚举定义,eg:EPageType, EOrderStatus
  5. 通常情况下使用 interface 定义类型,interface 不满足的情况下再使用 type
  6. type文件不写 js 代码
  7. 尽可能不写 any 类型

命名

  1. 常量名命名:全大写,下划线间隔
  2. 组件参数接口命名:以Props为后缀,eg:ITableProps
  3. 监听事件以命名:以handle为前缀,eg:handleClick
  4. 请求接口命名:小驼峰命名,以Api为后缀,eg:getListApi
  5. 请求接口参数/返回值命名:大驼峰命名,参数以Req为后缀,返回值以Res为后缀,eg:IGetListReq,IGetListRes
  6. 变量名尽可能的知名达意,eg:type ❌,pageType✅

代码

  1. 禁止使用嵌套的三元表达式
  2. 组件代码不允许超过 500 行(原本想定不超过300行的,考虑到成员水平,最终定为500行)
  3. 当参数大于3个时,须改造成对象传参(这一点在团队内分歧较大,因为成员的开发习惯是先写,参数不够了再加,而不是一开始就尽可能的考虑全面,所以加了后面这段话)除非函数的功能足够内聚和颗粒化,且参数含义清晰、参数结构简单稳定,可以保持使用单独参数。
  4. 不写class类组件
  5. 推荐代码层级:数据 -> 接口 -> 方法 -> 副作用 -> DOM(any: 看不见我,看不见我,走位~ 走位~)

image-20241031111418306.png

css

  1. className全小写,以“_”连接
  2. 公共组件className以“组件名_”为前缀,不使用嵌套写法(方便覆盖样式)
  3. 尽可能不写内联样式,保障dom干净度

lint库选择

eslint,prettier:alloy

stylelint:stylelint-config-standard

为什么选择 alloy 做 lint 库,主要有以下几个原因:

  1. 理念:秉承着专业的事交给专业的库来做,alloy 将 eslint 和 prettier 区分开,各自负责相应的工作
  2. 即时:通过 GitHub Actions 即时更新版本,紧跟最新 eslint 版本,至于项目中什么时候更新,那决定权在自己手中
  3. 文档:可以通过 alloy 在线网站文档,随时查询规则
  4. 迁移:技术永远在迭代,今天是 eslint,明天是 oxlint,在后续工程化持续迭代的情况下,如何降低迁移的摩擦成本是一大考量,在保障代码规范的情况下,定义最少的规则,是最小的成本

详情可查看:github.com/AlloyTeam/e…,特别是“设计理念”下的“详细说明”

填坑

以上我们定义了不少规范,从lint规则、文件划分、命名规则等多个角度切入,规范如何落地也带了以下几个问题:

  1. 如何切入
  2. 如何降低规范上手成本
  3. 如何保障规范成效

解决办法:

  1. 挑选部分功能较少且较常维护的项目为试点项目,培养组员规范意识,后续再全面落实
  2. 因为我们全员用的都是 vscode,所以借助vscode的 snippets 能力,提供代码片段、页面模板等功能,在代码编程维度上降低组员对命名规则的上手成本,提高开发效率。这边推荐一个在线生成 snippets 代码的网站
  3. 在 code review 环节上前期加强对规范的审查意识,相互督促,在大家都有规范意识后,就可以着重 CR 代码逻辑和设计思路了