现代化前端规范:工具+代码
theme: channing-cyan
远算前端团队,主要分享一些WEBGL、Three.js等三维技术,团队主要做数字孪生相关的数字大屏,项目一般涉及仿真、后处理,以及三维可视化。
欢迎关注公众号 远算前端团队
工具
vscode
vscode 可以说是前端最流行的编辑器,其有丰富的插件系统。不同开发人员对编辑器设置不同,比如缩进是用空格还是 tab,缩进几个等等。如果多人开发同一个项目,必然会引起文件冲突,所以一个团队最好能统一编辑器。 参考:https://editorconfig.org,在项目根目录新建.editconfig文件
``` root = true
[*] charset = utf-8 indent_style = space indent_size = 2 end_of_line = lf insert_final_newline = true trim_trailing_whitespace = true
[*.md] insert_final_newline = false trim_trailing_whitespace = false ```
prettier
代码格式化工具,vscode 有很多格式化插件,像 formate、vetur 等,我们选择 prettier 作为团队格式化工具。 1、安装 prettier
yarn add prettier --save-dev
在项目根目录新建.prettierrc.js
module.exports = {
// 强制使用单引号
singleQuote: true,
// 字符串使用单引号
singleQuote: true,
// 大括号内的首尾需要空格
bracketSpacing: true,
// 末尾不需要逗号
trailingComma: 'none',
// 箭头函数参数括号
arrowParens: 'avoid',
// 在jsx中把'>' 是否单独放一行
jsxBracketSameLine: true,
// 使用默认的折行标准
proseWrap: 'preserve',
// 根据显示样式决定 html 要不要折行
htmlWhitespaceSensitivity: 'css',
// 换行符使用 crlf/lf/auto
endOfLine: 'auto'
};
2、配置 vscode 保存自动格式化, 第一步,打开 vscode 设置,搜索 format,勾选 OnPaste、OnSave,如下图
第二步,搜索,defaultformatter,设置默认格式化工具,选择 Prettier
3、可以在项目 package.json 里配置 format 脚本,
"format": "prettier --write --parser typescript \"(src|test)/**/*.ts\""
eslint
eslint 作为代码检测工具,支持 ts、tsx
1、安装 eslint
yarn add eslint --save-dev
2、安装 ts 解析器以及 ts 规则补充
yarn add @typescript-eslint/parser --save-dev
yarn add @typescript-eslint/eslint-plugin --save-dev
eslint 默认使用 Espree 进行解析,无法识别 ts 的一些语法,所以需要安装一个 ts 的解析器 @typescript-eslint/parser,用它来代替默认的解析器@typescript-eslint/eslint-plugin 作为 eslint 默认规则的补充,提供了一些额外的适用于 ts 语法的规则。
3、支持 tsx
yarn add eslint-plugin-react --save-dev
由于是 react 项目,所以还需要插件 eslint-plugin-react 来支持 .tsx
4、在项目根目录创建 .eslintrc.js 当运行 ESLint 的时候检查一个文件的时候,它会首先尝试读取该文件的目录下的配置文件,然后再一级一级往上查找,将所找到的配置合并起来,作为当前被检查文件的配置。
``` module.exports = { parser: '@typescript-eslint/parser', plugins: [ 'react', 'react-hooks', '@typescript-eslint/eslint-plugin', 'prettier' ], settings: { react: { version: 'detect' } }, rules: { 'prettier/prettier': 'error', 'no-debugger': 'error', // 取消函数参数需要重新赋值给另一个变量才能使用 'no-param-reassign': [0], // 取消 { a, b, c } 多个变量需要换行 'object-curly-newline': [0], // 禁用var,用let和const代替 'no-var': 2, // 开启强制单引号 quotes: [2, 'single'], // 强制全等( === 和 !==) eqeqeq: 2, // 语句强制分号结尾 semi: [2, 'always'], // 禁止出现未使用的变量 '@typescript-eslint/no-unused-vars': [2], // 箭头函数参数括号,一个参数时可省略括号 'arrow-parens': [2, 'as-needed'], // 箭头函数,箭头前后空格 'arrow-spacing': [2, { before: true, after: true }], // 禁止对象最后一项逗号 'comma-dangle': [2, 'never'], // 单行代码/字符串最大长度 'max-len': [2, { code: 120 }], // jsx缩进2个空格 'react/jsx-indent': [2, 2], // 文件末尾强制换行 'eol-last': 2,
// react配置
// 强制组件方法顺序
'react/sort-comp': [2],
// 结束标签,组件省略闭合标签,html不省略闭合标签
'react/self-closing-comp': [2, { component: true, html: false }],
// 检查 Hook 的规则,不允许在if for里面使用
'react-hooks/rules-of-hooks': [2],
// 检查 effect 的依赖
'react-hooks/exhaustive-deps': [2]
} }; ```
git-commit-message
验证 git 提交规则,创建 verify-commit-msg.js 文件
``` const chalk = require('chalk') const msgPath = process.env.GIT_PARAMS const msg = require('fs').readFileSync(msgPath, 'utf-8').trim()
const commitRE = /^(revert: )?(wip|release|feat|fix|polish|docs|style|refactor|perf|test|workflow|ci|chore|types|build)((.+))?: .{1,50}/
if (!commitRE.test(msg)) {
console.log()
console.error(
${chalk.bgRed.white(' ERROR ')} ${chalk.red(
invalid commit message format.)}\n\n
+
chalk.red(
Proper commit message format is required for automated changelog generation. Examples:\n\n
) +
${chalk.green(
feat(compiler): add 'comments' option)}\n
+
${chalk.green(
fix(v-model): handle events on blur (close #28))}\n\n
+
chalk.red(See .github/COMMIT_CONVENTION.md for more details.\n
)
)
process.exit(1)
}
```
代码提交规则
feat: 新功能
fix: 修复
docs: 文档变更
style: 代码格式(不影响代码运行的变动)
refactor: 重构(既不是增加feature,也不是修复bug)
perf: 性能优化
test: 增加测试
chore: 构建过程或辅助工具的变动
revert: 回退
build: 打包
代码
整个团队是用 umi 封装的脚手架,所有项目都是 React.js+Mobx+TypeScript,下面列出了基本规范。
React.js
命名
-
React 组件文件名使用 PascalCase 命名规则,并且以.tsx 后缀名。例如:AnotherComponent.tsx
-
如果 React 组件是一个单文件,以组件名作为文件名;如果是将 React 组件放在一个目录里,以组件名作为目录名,并且组件所在文件以 index.jsx 命名
``` src |-- components | |-- BadNamedComponent | |-- BadNamedComponent.jsx | |-- BadNamedComponent.css | |-- GoodNamedComponent | |-- ChildComponent.jsx | |-- ChildComponent.css | |-- index.jsx | |-- index.css | |-- AnotherComponent.jsx | |-- AnotherComponent.csssha
// ❌ import BadNamedComponent from '@/components/BadNamedComponent/BadNamedComponent';
// ❌ import GoodNamedComponent from '@/components/GoodNamedComponent/index';
// ✅ import GoodNamedComponent from '@/components/GoodNamedComponent';
// ✅ import AnotherComponent from '@/components/AnotherComponent';
- React 组件使用 PascalCase 方式命名,React 组件实例使用 camelCase 方式命名
// ❌ import someComponent from './SomeComponent';
// ✅ import SomeComponent from './SomeComponent';
// ❌
const AnotherComponent =
// ✅
const anotherComponent =
- 不推荐 使用高阶组件。如果必需使用,以 with 前缀命名高阶组件
```
// ❌
export default function wrapForm(WrappedComponent) {
return function FormWrapper(props) {
return
// ✅
export default function withForm(WrappedComponent) {
return function WithForm(props) {
return
- 高阶组件需要添加 displayName 属性方便调试, displayName 属性的格式为:装饰器函数名称加上圆括号 () 包裹的 WrappedComponent 的 displayName 或者 name 属性,如下所示
```
// ❌
export default function withForm(WrappedComponent) {
function WithForm(props) {
return
return WithForm; }
// ✅
export default function withForm(WrappedComponent) {
function WithForm(props) {
return
const wrappedComponentName = WrappedComponent.displayName || WrappedComponent.name || 'Component';
WithForm.displayName = withForm(${wrappedComponentName})
;
return WithForm;
}
```
- props 使用 camelCase 方式命名
```
// ❌
// ✅
- 不要使用下划线作为变量名的前缀
``` function SomeComponent() { // ❌ const _handleSubmit = useCallback((params) => { submitWith(params); }, []);
// ✅ const handleSubmit = useCallback((params) => { submitWith(params); }, []);
return (