Skip to content

13 - 开发规范

ESLint 配置

.eslintrc.js

项目继承 taro/react 规则集,但大量规则被关闭,代码风格较宽松:

js
module.exports = {
  extends: ['taro/react'],
  ignorePatterns: ['**/*.scss', '.cz-config.js'],
  rules: {
    'import/no-commonjs': 'off',
    'import/no-named-as-default': 'off',
    'import/no-duplicates': 'off',
    'no-unused-vars': 'off',
    'no-var': 'off',
    'no-shadow': 'off',
    'no-undef': 'off',
    'no-use-before-define': 'off',
    'no-restricted-globals': ['error', 'isFinite'],  // 唯一报错规则
    'react/react-in-jsx-scope': 'off',
    'react/sort-comp': 'off',
    'react-hooks/exhaustive-deps': 'off',
    'react-hooks/rules-of-hooks': 'off',
    'react/no-direct-mutation-state': 'off',
    'react/jsx-key': 'off',
    'react/jsx-filename-extension': [1, { extensions: ['.js', '.jsx', '.tsx'] }]
  },
  globals: {
    TARO_APP: false,
    wx: false
  }
}

.eslintignore

忽略以下文件/目录:

node_modules
dist
src/utils/qqmap-wx-jssdk.js        # 腾讯地图 SDK
src/utils/cos/                      # 腾讯云 COS SDK
src/components/sp-html/mp-html/     # 富文本组件
src/components/wxParse/             # 旧版富文本
**/*.scss
package-lock.json
.DS_Store

Prettier 配置

.prettierrc

json
{
  "trailingComma": "none",
  "semi": false,
  "singleQuote": true,
  "jsxSingleQuote": true,
  "arrowParens": "always",
  "printWidth": 100,
  "tabWidth": 2,
  "quoteProps": "preserve",
  "endOfLine": "auto"
}
规则说明
semifalse不使用分号
singleQuotetrue单引号
jsxSingleQuotetrueJSX 中也用单引号
trailingComma"none"无尾逗号
arrowParens"always"箭头函数参数始终加括号
printWidth100最大行宽 100 字符
tabWidth2缩进 2 空格
endOfLine"auto"自动检测换行符

.prettierignore

/src/utils/cos/*

Husky + lint-staged

Git Hooks

Hook文件执行内容
pre-commit.husky/pre-commitnpx lint-staged
commit-msg.husky/commit-msgnpx commitlint --edit $1

lint-staged 配置

来自 package.json

json
"lint-staged": {
  "*.{js,jsx}": [
    "eslint --fix --ignore-path .eslintignore",
    "prettier --write"
  ],
  "*.scss": [
    "prettier --write"
  ]
}
  • .js / .jsx 文件:先 ESLint 修复,再 Prettier 格式化
  • .scss 文件:仅 Prettier 格式化

提交规范

Commitlint — TBID 格式

项目使用自定义的 TBID(Teambition Issue ID)提交消息格式

[TBID:PROJECT-123] type(scope): subject

正则验证:/^\[TBID:([A-Za-z0-9]+-\d+)\]\s(?:(\w+)(?:\(([^)]*)\))?(?::|\s)\s*)?(.+)$/

commitlint.config.js

规则级别说明
tbid-header2 (error)必须以 [TBID:PROJECT-123] 开头
type-enum2 (error)类型必须在枚举内
type-case2 (error)类型必须小写
type-empty0 (off)类型可选
subject-empty2 (error)subject 不能为空
header-max-length0 (off)header 长度不限

允许的提交类型

feat, feature, bug, fix, ui, docs, style, perf, release, deploy,
refactor, test, chore, revert, merge, build, ci, workflow

系统提交豁免

以下提交消息格式自动豁免 TBID 检查:

  • Merge pull request
  • Merge branch
  • Merge tag
  • Revert
  • fixup / squash
  • Merged PR
  • Merge remote-tracking branch
  • Automatic merge
  • Auto-merged

commitlint-tbid-plugin.js

自定义插件验证逻辑:

js
module.exports = {
  rules: {
    'tbid-header': (parsed, when = 'always') => {
      const matches = typeof parsed.header === 'string' &&
        /^\[TBID:[A-Za-z0-9]+-\d+\]\s.+/.test(parsed.header)
      return [
        matches,
        'commit message must start with [TBID:PROJECT-123] description'
      ]
    }
  }
}

Commitizen 交互式提交

使用 cz-customizable 适配器,提供交互式提交流程:

bash
npm run commit

.cz-config.js 定义 15 种提交类型,交互流程:

  1. 选择提交类型(feature/fix/docs/...)
  2. 输入修改范围(可选)
  3. 简要描述(必填,最长 72 字符)
  4. 跳过 body 和 footer

Babel 配置

js
// babel.config.js
module.exports = {
  presets: [
    ['taro', {
      framework: 'react',
      ts: true
    }]
  ]
}
  • 使用 babel-preset-taro 预设
  • 框架:React
  • 启用 TypeScript 支持

jsconfig.json 路径别名

json
{
  "exclude": ["node_modules", "dist"],
  "compilerOptions": {
    "baseUrl": ".",
    "paths": { "@/*": ["./src/*"] },
    "experimentalDecorators": true
  }
}

代码风格要点

不使用分号

js
// ✅ 正确
const a = 1
const b = () => {}

// ❌ 错误
const a = 1;
const b = () => {};

单引号

js
// ✅ 正确
import { useState } from 'react'
const name = 'ecshopx'

// ❌ 错误
import { useState } from "react"
const name = "ecshopx"

箭头函数参数加括号

js
// ✅ 正确
const fn = (x) => x + 1
const fn2 = () => {}

// ❌ 错误
const fn = x => x + 1

JSX 使用单引号

jsx
// ✅ 正确
<View className='container'>
  <Text children='hello' />
</View>

// ❌ 错误
<View className="container">
  <Text children="hello" />
</View>

npm registry 配置

项目 .npmrc 配置了混合 registry:

  • 淘宝镜像 registry.npmmirror.com:加速公共包安装
  • shopex 私有 registry reg.ishopex.cn:获取内部包

代码复用规范

组件复用

js
// 从统一入口导入
import { SpButton, SpGoodsItem } from '@/components'

// 不建议从具体路径导入(除非按需优化)
import SpButton from '@/components/sp-button'

API 模块复用

js
// 主包模块 — 从 index 导入
import { cart, item, member } from '@/api'

// 分包专用模块 — 直接从模块导入
import communityApi from '@/api/community'

Hooks 复用

js
import { useLogin, usePayment, usePage } from '@/hooks'

HOC 复用

js
import { withLogin, withPager, withPageWrapper } from '@/hocs'

工具函数复用

js
import { isWeixin, formatPriceToHundred, navigateTo, getCurrentRoute } from '@/utils'

新增页面检查清单

  • [ ] 在 app.config.js 对应分包注册路由
  • [ ] 创建 index.config.js 设置页面标题和配置
  • [ ] 如果是分包 API,不在 src/api/index.js 导出
  • [ ] 如果需要登录检查,添加到 needLoginPageType 或使用 withLogin HOC
  • [ ] 样式文件使用全局变量($edge-size$font-size 等),不硬编码
  • [ ] 提交消息使用 [TBID:xxx] type: subject 格式
  • [ ] 如果页面可能被路由拦截,检查 routeIntercept.js

版本管理

Node 版本

  • 要求:Node.js 16.16.0
  • Docker 基础镜像reg.ishopex.cn/base-images/node-python3:16.16.0-alpine3.16

依赖版本

  • Taro:3.6.25(所有 @tarojs 包统一版本)
  • webpack:5.78.0
  • React:18.x
  • 项目版本:4.9.1

分支命名(Multica 项目)

功能需求:feature/[TBID]
Bug 修复:bug/[TBID]

[TBID] 使用 Teambition 任务号、issue ID 或用户明确提供的任务标识。