# 项目应用
# 忧虑
你是不是总是在抱怨项目组的各方面不统一,不好维护,千奇百怪?
你是不是每次提交代码的时候总要拉某某人过来看下各种冲突?
你是不是每次merge代码的时候总要话很长的时间去解决不同格式的代码冲突?
你是不是有时候为了解决一个bug好几天没睡好,最终定位的问题也许是一个分号、或是书写规范? 人人都在恐慌,人人都在责怪他人,但殊不知,换了好几个项目都是类似,想过为什么吗?
# 分析现状
在实际的项目开发过程中,每一位开发者不可能完全按照前端开发的规范来。前面规范手册里面就有说过,前端开发规范固然重要,但是不应该以浪费实用性
或者大量开发时间
作为代价;有的时候公司也不会给你那么多时间和精力做项目开发规范,毕竟很多老板认为最快时间把产品做出来才是真理。所以,这就是有些开发者虽然知道这些大厂的规范,但是很难落实的原因!
# 如何解决
# 1、前期做好约束
工程代码前期的框框架架很重要,很大一部分决定了工程后期迭代和维护的标准,雷同的多,参考的也就多了。
如像一些工程目录命名规范,只需要工程架构的人在前期做好约束,严格按照一套规范来,后面迭代过程中,开发者自然按你的格式命名,不必太过在意;
如像ng、vue或者react项目开发过程中,开发组长提前写好demo组件,并要求组员就此做规范,也是能快速规范工程的有效方法之一;
代码注释的规范及其重要,很大程度的影响工程的维护成本。所以注释规范需做好,如场景判断
if(a>10)
应写注释,能让维护者知道10代表什么;
# 2、统一才是最好的规范
规范中类似html的基本语法 如加上DOCTYPE
、E兼容模式和视网膜模式、标签缩进2格、属性使用" "
等等,我们都不必太过在意,因为很多编辑器的插件都支持一键生成,项目组内部只需统一一键生成的插件即可
,项目组内部对于html的规范重点是标签语义化
、如何减少标签的嵌套
等。
同理可得,对于css、js,或者是根据你所做项目而定的ts、jsx、tsx等等的文件,都可以内项目组内部制定一套统一的格式刷插件。比如我的react项目组就统一使用VS Code的2款格式刷插件
Prettier - Code formatter : 代码格式化插件,主要针对工程中的JavaScript / TypeScript / CSS
Prettier Now : 支持语言比较全面的代码格式化插件,主要是支持jsx /tsx ,还有sass / less等
在比如,我们项目组内部还统一规范了代码缩进和文件头,规范代码缩进是为了提交或merge代码的时候能提高效率,加文件header和最近修改记录能快速定位问题和处理问题的人。需要了解更多VS COde项目实战内容请参考
{
// 设置格式化缩进2格
"prettier.tabWidth": 4,
"vetur.format.defaultFormatter.html": "prettier",
// 创建和更新代码的头部信息作者
"fileheader.Author": "yuqing",
"fileheader.LastModifiedBy": "yuqing",
}
这时候有的人会说,其实XXX插件比你的这2个还好。说实话,一点问题都没有。但是,我这里强调的不是插件的好坏,我强调的是统一
二字。
# 写给我的项目组
前端项目组推荐使用VS Code编辑器,很轻量级,也挺好上手!不熟悉的可参考我整理文档(都给你们准备好了)请参考强大的VS Code
# 1、统一格式刷插件
Prettier - Code formatter : 代码格式化插件,主要针对工程中的JavaScript / TypeScript / CSS
Prettier Now : 支持语言比较全面的代码格式化插件,主要是支持jsx /tsx ,还有sass / less等
react项目、js原生项目有这2款插件就够了,其他工程的仅供参考。老项目维护前先格式化一遍,再开始维护;代码提交之前一定要格式化一遍(最好吧格式化快捷键当
control + s
按)。规范了格式刷,实际项目中能省不少麻烦,没有用VS Code的请自行研究编辑器格式化插件。
# 2、更好的管理代码
- 代码统一缩进2格;
统一缩进能给代码提交、分支合并等减少很多麻烦
{
// 设置格式化缩进2格
"tabWidth": 2,
"vetur.format.defaultFormatter.html": "prettier"
}
- 每个文件头部生成如下信息(文件创建者和最后修改者、及相关时间)强大的VS Code中有插件介绍,插件名称:
fileheader
。
这样做的好处是能很清楚每个文件的创建者、修改者,遇到问题或者代码交接能很快定位到人,记得每个文件Describe一下说明文件用意!
- git代码管理
下载好用的git代码管理插件,下拉代码对比一下,merge代码对比一下,代码提交前对比一下。
# 3、如何安装插件
一般情况下直接在VS Code里面搜索到对应的插件下载即可,但我的项目组有自己的开发云桌面,访问不了外网,这种情况下插件安装就只能用离线安装
或者 有网安装再拷贝了
,离线安装请自行百度或者google安装教程。
这里推荐本地安装好再拷贝到云桌面
,本地安装好的自定义插件路径如下(默认安装路径,自己有手动修改的按修改后的查找)
// windows系统
C:\Users\用户名\.vscode\extensions
// mac os系统
/Users/用户名/.vscode/extensions
VS Code自定义插件都在 .vscode
隐藏路径的 extensions
文件夹下面,本地安装好后把 extensions
文件夹拷贝到云桌面相应路径,然后重启编辑器即可。
# eslint接入方式
prettier + eslint
vue/react/typescript 都能适用
# 使用
前提编辑器安装好Prettier
和ESLint
https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode
https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint
- 安装
yarn add @tsign/eslint-config-esign -D
- package.json 下新增配置:
- TS 应用
"eslintConfig": {
"extends": "@tsign/eslint-config-esign/ts"
}
- 普通应用
"eslintConfig": {
"extends": "@tsign/eslint-config-esign/common"
}
- jest
"eslintConfig": {
"extends": "@tsign/eslint-config-esign/jest"
}
当然你可以引用多个,比如:
"eslintConfig": {
"extends": ["@tsign/eslint-config-esign/common", "@tsign/eslint-config-esign/jest"]
}
注意: 引入 ts 之后就没必要引入 common 了,ts 包含了 common 的内容。
- 新增
.prettierrc
文件
{
"semi": false,
"singleQuote": true,
"jsxSingleQuote": false,
"tabWidth": 2,
"printWidth": 140,
"trailingComma": "es5",
"bracketSpacing": true,
"jsxBracketSameLine": false
}
- vscode 配置
{
// 这几项开启后会两次格式化
// eslint.enable禁用时, 开启能使用prettier进行格式化
// eslint.enable开启时, 关闭使用eslint来进行格式化
"editor.formatOnPaste": false,
"editor.formatOnSave": false,
"editor.formatOnType": false,
// eslint
"eslint.enable": true,
"eslint.alwaysShowStatus": true,
"eslint.packageManager": "yarn",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"html",
"vue"
]
}
# 规范
# 附:git-hooks 配置
- yarn add yorkie lint-staged -D
- packages.json
"gitHooks": {
"pre-commit": "lint-staged",
"post-commit": "git update-index --again",
"commit-msg": "node config/verifyCommitMsg.js" //改成自己的路径
},
"lint-staged": {
"src/**/*.{vue,js,jsx,ts,tsx}": [
"eslint --max-warnings=0 --fix",
"git add"
]
},
# verifyCommitMsg.js
const chalk = require('chalk') // eslint-disable-line
const msgPath = process.env.GIT_PARAMS
const msg = require('fs')
.readFileSync(msgPath, 'utf-8')
.trim()
console.log(msg, 'msg')
const commitRE = /^(v\d+\.\d+\.\d+(-(alpha|beta|rc.\d+))?)|((revert: )?(feat|fix|docs|style|refactor|perf|test|workflow|ci|chore|types)(\(.+\))?!?: .{1,50})/
if (msg.indexOf('Merge branch') === 0) {
return
}
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`) +
chalk.red(` You can also use ${chalk.cyan(`npm run commit`)} to interactively generate a commit message.\n`)
)
process.exit(1)
}
# 提交信息规范
# Git Commit Message Convention
This is adapted from Angular's commit convention.
# TL;DR:
Messages must be matched by the following regex:
;/^(revert: )?(feat|fix|docs|style|refactor|perf|test|workflow|ci|chore|types)(\(.+\))?: .{1,50}/
# Examples
Appears under "Features" header, compiler
subheader:
feat(compiler): add 'comments' option
Appears under "Bug Fixes" header, v-model
subheader, with a link to issue #28:
fix(v-model): handle events on blur
close #28
Appears under "Performance Improvements" header, and under "Breaking Changes" with the breaking change explanation:
perf(core): improve vdom diffing by removing 'foo' option
BREAKING CHANGE: The 'foo' option has been removed.
The following commit and commit 667ecc1
do not appear in the changelog if they are under the same release. If not, the revert commit appears under the "Reverts" header.
revert: feat(compiler): add 'comments' option
This reverts commit 667ecc1654a317a13331b17617d973392f415f02.
# Full Message Format
A commit message consists of a header, body and footer. The header has a type, scope and subject:
<type>(<scope>): <subject> // 注意 冒号后面有一个空格
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
type 是提交类型(必填) scope 指提交影响范围(可选) subject 指提交内容简略描述(必填)
The header is mandatory and the scope of the header is optional.
A !
MAY be appended prior to the :
in the type/scope prefix, to further draw attention to breaking changes. BREAKING CHANGE:
description MUST also be included in the body or footer, along with the !
in the prefix.
# Revert
If the commit reverts a previous commit, it should begin with revert:
, followed by the header of the reverted commit. In the body it should say: This reverts commit <hash>.
, where the hash is the SHA of the commit being reverted.
# Type
- feat:新功能(feature)
- fix:修补 bug
- docs:文档(documentation)
- style: 格式(不影响代码运行的变动)
- refactor:重构(即不是新增功能,也不是修改 bug 的代码变动)
- test:增加测试
- chore:构建过程或辅助工具的变动
If the prefix is feat
, fix
or perf
, it will appear in the changelog. However if there is any BREAKING CHANGE, the commit will always appear in the changelog.
Other prefixes are up to your discretion. Suggested prefixes are docs
, chore
, style
, refactor
, and test
for non-changelog related tasks.
# Scope
The scope could be anything specifying place of the commit change. For example core
, compiler
, ssr
, v-model
, transition
etc...
# Subject
The subject contains succinct description of the change:
- use the imperative, present tense: "change" not "changed" nor "changes"
- don't capitalize first letter
- no dot (.) at the end
# Body
Just as in the subject, use the imperative, present tense: "change" not "changed" nor "changes". The body should include the motivation for the change and contrast this with previous behavior.
# Footer
The footer should contain any information about Breaking Changes and is also the place to reference GitHub issues that this commit Closes.
Breaking Changes should start with the word BREAKING CHANGE:
with a space or two newlines. The rest of the commit message is then used for this.