灏天阁

认识前端规范

· Yin灏

代码规范(格式化规范)

推荐使用 prettier,它内置了一套格式化的规则,具体配置:

  1. 安装依赖
npm install --save-dev --save-exact prettier
# or
yarn add --dev --exact prettier
  1. 创建一个空配置文件,让编辑器和其他工具知道你正在使用 Prettier:
echo {}> .prettierrc.json
  1. 创建一个.prettierignore文件,让 Prettier CLI 和编辑器知道哪些文件不能格式化
# Ignore artifacts:
dist
build
  1. 安装 Prettier-Code Formater 插件(Vs code)

设置模块中,搜索 format On Save,勾上这个就可以了

这样 Ctrl + S 保存代码时,插件就会帮助我们自动格式化了。

提交代码的如何格式化?

这时候就需要在 git commit 的阶段自动将提交的代码进行格式化,这里我们借助工具 husky,它主要可以帮助我们在 git 阶段检查提交消息、运行测试、检查代码等。官网

npm install --save-dev husky lint-staged
npx husky install
npm set-script prepare "husky install"
npx husky add .husky/pre-commit "npx lint-staged"
# or
yarn add --dev husky lint-staged
npx husky install
npm set-script prepare "husky install"
npx husky add .husky/pre-commit "npx lint-staged"
  • 将以下内容添加到 package.json 中:

当执行 git commit 阶段前,先执行 lint-staged,lint-staged 中的内容就是对暂存区的文件执行格式化的命令。

{
  "lint-staged": {
    "**/*": "prettier --write --ignore-unknown"
  }
}

若使用的是脚手架工具搭建的项目,会自带 eslint 配置(eslintConfig)。prettier 和 eslint 会有一些配置上的冲突,这个时候需要安装eslint-config-prettier以使 ESLint 和 Prettier 相互配合,安装完后在.eslintrc 中配置(以 Create-React-App 为例):

  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest",
      "prettier"
    ]
  },

这样就可以用"prettier" 的部分规则覆盖前面的规则,进行正常工作。

代码规范之 JS/TS 规范

JS/TS 主流的大致有这几种:

比较推荐使用 Airbnb JavaScript Style Guide,几乎覆盖了 JavaScript 的每一项特性。

具体配置:

1). 安装依赖

npm install eslint --save-dev
# or
yarn add eslint --dev

2). 生成配置文件

npm init @eslint/config
# or
yarn create @eslint/config

跟着终端中的提示,照自身需求一步步选择即可。

有了具体的规范后,我们同样需要使用工具去约束:通过在 git commit 阶段校验,若不通过则取消提交。
在 package.json 中的 lint-staged

  "lint-staged": {
    "**/*": "prettier --write --ignore-unknown", //格式化
    "src/*": "eslint --ext .js,.ts,.tsx"  //进行eslint校验
  },

注意: 这里如果选用的 ts,则会默认使用@typescript-eslint/parser 解析器,官方为了追求更快的解析速度,并不会对.ts 文件中的类型进行检查,只会做语法检测。

若需对类型进行检测,需要在 extends 中加上

module.exports = {
  root: true,
  parser: "@typescript-eslint/parser",
  parserOptions: {
    tsconfigRootDir: __dirname,
    project: ["./tsconfig.json"],
  },
  plugins: ["@typescript-eslint"],
  extends: [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:@typescript-eslint/recommended-requiring-type-checking",
  ],
};

但是一些基本的类型依然检测不出来,这里还有另一种方式:在 pre commit 中执行 yarn run tsc (对项目中 ts 文件进行类型检测,默认会读取根目录中的 tsconfig.json 配置。)因为这种方法会全量检测,所以不适用大项目

代码规范之 CSS 规范

CSS 检查代码规范使用 stylelint 插件,规范则推荐使用stylelint-config-standard

1). 安装

npm install --save-dev stylelint stylelint-config-standard

2). 在项目的根目录中创建一个配置文件 stylelintrc.json

{
  "extends": "stylelint-config-standard"
}

若出现 prettier 冲突则

冲突详解

3). 解决与 prettier 配置的冲突:

npm install --save-dev stylelint-config-prettier

4). 将下面配置复制到 stylelintrc.json

{
  "extends": ["stylelint-config-standard", "stylelint-config-prettier"]
}

5). 在 git commit 阶段进行检测:

 "lint-staged": {
    "**/*": "prettier --write --ignore-unknown", //格式化
    "src/**.{js,jsx,ts,tsx}": "eslint --ext .js,.jsx,.ts,.tsx", //对js文件检测
    "**/*.{less,css}": "stylelint --fix" //对css文件进行检测
  },

其他自定义规范

(1)命名规范

// 👎 :
let rText = 'willen';

// 👍 无需对每个变量都写注释,从名字上就看懂
let firstName = 'jackie';

// 👎 从命名无法知道返回值类型
function showTableList() {....} // // 无法辨别函数意图,返回的是一个数组,还是一个对象,还是true or false?

// 👍 明确函数意图,对于返回true or false的函数,最好以should/is/can/has开头
function shouldShowTableList() {...}
function isEmpty() {...}
function canCreateDocuments() {...}
function hasLicense() {...}
function sendInformaionToUser(user) {.... } //动词开头,函数意图就很明显

(2)写注释

在每个文件的顶部明确说明该组件做什么,可以针对业务,写些开发流程;有没有业务理解难点等等,对业务特殊函数/变量也需要写注释

(3)变量兜底 (es6 的链式)

// 👎 对于从接口获取的变量值,没有兜底
const { dataList } = getApiRequest();
dataList.map((s) => s.id); //没有考虑data异常的情况,代码一跑就爆炸

// 👍 对于从接口获取的变量值,做好兜底
const { dataList = [] } = getApiRequest();
dataList.map((s) => s?.id); //没有考虑data异常的情况,代码一跑就爆炸

(4)优先使用函数式编程

// 👎 使用for循环编程
for (i = 6; i <= 100; i++) {
  a[i] = a[i] + 1;
}

// 👍 使用函数式编程
let b = a.map((item) => ++item);

(5)辅助函数必须是纯函数

// 👎 不要让功能函数的输出变化无常
function plusAbc(a, b, c) {
  // 这个函数的输出会变化,因为api返回的值一旦改变,同样输入函数的a,b,c的值,但函数返回的结果却不一定相同。
  var c = getDataApi();
  return a + b + c;
}

// 👍 功能函数使用纯函数,输入一致,输出结果永远唯一
function plusAbc(a, b, c) {
  // 同样输入函数的a,b,c的值,但函数返回的结果永远相同。
  return a + b + c;
}

(6)关于 props 参数传递

  • 传递较深的场景我推荐直接使用 context,对于 props 中的内容和上下文通过 TS 来解决。
  • 尽量减少参数的数量,开发前可以先想想,要使用这个组件,需要哪些参数能在任何地方使用,在进行开发 参数的数量越多,重新渲染的理由就越多。

(7)组件/函数导入导出

// 👍 在文件头部导入,顺序依次为: 第三方库 > 公共组件/方法 > 非公共部分组件/方法
import React, { FC, useCallback, useContext, useEffect } from "react";
import { cloneDeep } from "lodash-es";
import Header from "@components/header";
import Content from "./Content";

// 👍 在底部导出
export { Content, Header };
export default Component;

待补充…

项目文件结构规范

- src 开发目录
      - pages 视图
          - module-a 模块A
            - components 私有组件
              - ComA.tsx
              - ComB.tsx
            - index.module.less
            - index.tsx
            - Content.tsx
          - module-b 模块B
      - components 公共组件
        - cardFilter
          - index.tsx
          - index.module.less
          - cardFilterModal.tsx //其他子组件
          - useGetCardFilterInfo.hooks.ts
      - routers 路由文件
      - store redux中的数据
      - utils 这里是以utils为后缀
        - a.utils.ts
        - b.utils.ts
      - hooks 这里是以hooks为后缀
        - useXXX.ts
        - useXXX.ts
      - assets 静态资源文件
      - api api请求,这里是以api为后缀
      	- API.d  类型说明文件
        - Dao.ts
        - Service.ts
      -

Git commit 规范

git commit 规范主要可以帮助开发人员在 code review 期间更容易理解提交的内容.这会产生更具可读性的消息,在查看项目历史时更容易理解这些消息。

每个提交消息都包含一个subject、一个body和一个footer (中间使用空行分割),标头具有特殊格式,包括type(类型)scope (范围)subject(主题)

<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>

type主要有以下几种类型:

  • feat: 一个新特性
  • fix: 修复 bug
  • docs: 文档修改
  • style: 不影响代码含义的更改(空格、格式、缺少分号等)
  • refactor: 代码重构
  • perf: 优化性能
  • test: 测试用例修改
  • chore: 对构建过程或辅助工具和库的更改,例如文档生成
  • build: 变更项目构建或外部依赖(例如 scopes: webpack、gulp、npm 等)
  • ci:更改持续集成软件的配置文件和 package 中的 scripts 命令,例如 scopes: Travis, Circle 等

scope: 范围可以是指定提交更改位置的任何内容。例如在业务项目中可以依据菜单或者功能模块划分,如果是组件库开发,则可以依据组件划分。

subject: 主题包含对更改的简洁描述:

  • 使用陈述语句
  • 第一个字母不要大写
  • 末尾没有点 (.)

body: commit 具体修改内容, 可以分为多行,应该包括改变的动机,并与以前的行为进行对比。

footer: 一些备注, 通常是修复的 bug 的链接。

有了规范后,我们需要通过工具去约束:commitlint.这会在每次 git commit 前检查 commit message 是否符合规范,如果不符合,则会提交失败

具体配置:

# 安装 commitlint cli 和 conventional config
npm install --save-dev @commitlint/{config-conventional,cli}
# Windows:
npm install --save-dev @commitlint/config-conventional @commitlint/cli

#配置要使用的 commitlint 规则
"module.exports = {extends: [
'@commitlint/config-conventional'
]}" > commitlint.config.js

#加入到husky中:
npx husky add .husky/commit-msg 'npx --no -- commitlint --edit "$1"'
#or
yarn husky add .husky/commit-msg 'yarn commitlint --edit $1'

更多详情见官网:github.com

总结

统一规范保证团队成员工作流程的一致性,从而减少沟通成本,提高开发效率。

参考资料

commit 规范

从零到一建立前端规范

- Book Lists -