年前的最后一个礼拜,由于所负责项目的暂停版本排期,于是乎有几天的空闲的时间,就想着把项目的代码质量搞上去。背景是,半年前我开始负责这个项目的前端开发,发现当时代码质量不理想。加之团队内部也着手把代码规范这件事落实下来。于是乎,就有了这个系列的文章。

我打算从三个方面对代码规范需要做的事情进行总结,后续有新的想法会继续更新。

  1. 代码质量-1 使用自动化工具提高代码质量
  2. 代码质量-2 制订代码规范
  3. 代码质量-3 code review

使用自动化工具提高代码质量

技术栈:

  • Vue 2.6.10
  • Vue-Router 3.0.6
  • Vuex 3.1.0·
  • @vue/cli-service 4.4.4
  • webpack 4.0.0

本文主要介绍,如何使用 ESLint + Prettier + Husky + Lint-staged 在开发过程中保证代码质量

1. ESLint

ESLint是一个可检查并修复JavaScript代码的工具

1.1 安装依赖

以下依赖会在项目创建阶段,自己选择安装

1
2
3
4
eslint
babel-eslint
eslint-plugin-vue
@vue/cli-plugin-eslint

1.2 配置ESLint

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
module.exports = {
root: true,
parserOptions: {
parser: 'babel-eslint',
sourceType: 'module'
},
env: {
browser: true,
node: true,
es6: true,
},
extends: ['plugin:vue/recommended', 'eslint:recommended'],

// add your custom rules here
//it is base on https://github.com/vuejs/eslint-config-vue
rules: {
"vue/max-attributes-per-line": [2, {
"singleline": 10,
"multiline": {
"max": 1,
"allowFirstLine": false
}
}],
"vue/singleline-html-element-content-newline": "off",
"vue/multiline-html-element-content-newline":"off",
"vue/name-property-casing": ["error", "PascalCase"],
"vue/no-v-html": "off",
'accessor-pairs': 2,
'arrow-spacing': [2, {
'before': true,
'after': true
}],
'block-spacing': [2, 'always'],
'brace-style': [2, '1tbs', {
'allowSingleLine': true
}],
'camelcase': [0, {
'properties': 'always'
}],
'comma-dangle': [2, 'never'],
'comma-spacing': [2, {
'before': false,
'after': true
}],
'comma-style': [2, 'last'],
'constructor-super': 2,
'curly': [2, 'multi-line'],
'dot-location': [2, 'property'],
'eol-last': 2,
'eqeqeq': ["error", "always", {"null": "ignore"}],
'generator-star-spacing': [2, {
'before': true,
'after': true
}],
'handle-callback-err': [2, '^(err|error)$'],
'indent': [2, 2, {
'SwitchCase': 1
}],
'jsx-quotes': [2, 'prefer-single'],
'key-spacing': [2, {
'beforeColon': false,
'afterColon': true
}],
'keyword-spacing': [2, {
'before': true,
'after': true
}],
'new-cap': [2, {
'newIsCap': true,
'capIsNew': false
}],
'new-parens': 2,
'no-array-constructor': 2,
'no-caller': 2,
'no-console': 'off',
'no-class-assign': 2,
'no-cond-assign': 2,
'no-const-assign': 2,
'no-control-regex': 0,
'no-delete-var': 2,
'no-dupe-args': 2,
'no-dupe-class-members': 2,
'no-dupe-keys': 2,
'no-duplicate-case': 2,
'no-empty-character-class': 2,
'no-empty-pattern': 2,
'no-eval': 2,
'no-ex-assign': 2,
'no-extend-native': 2,
'no-extra-bind': 2,
'no-extra-boolean-cast': 2,
'no-extra-parens': [2, 'functions'],
'no-fallthrough': 2,
'no-floating-decimal': 2,
'no-func-assign': 2,
'no-implied-eval': 2,
'no-inner-declarations': [2, 'functions'],
'no-invalid-regexp': 2,
'no-irregular-whitespace': 2,
'no-iterator': 2,
'no-label-var': 2,
'no-labels': [2, {
'allowLoop': false,
'allowSwitch': false
}],
'no-lone-blocks': 2,
'no-mixed-spaces-and-tabs': 2,
'no-multi-spaces': 2,
'no-multi-str': 2,
'no-multiple-empty-lines': [2, {
'max': 1
}],
'no-native-reassign': 2,
'no-negated-in-lhs': 2,
'no-new-object': 2,
'no-new-require': 2,
'no-new-symbol': 2,
'no-new-wrappers': 2,
'no-obj-calls': 2,
'no-octal': 2,
'no-octal-escape': 2,
'no-path-concat': 2,
'no-proto': 2,
'no-redeclare': 2,
'no-regex-spaces': 2,
'no-return-assign': [2, 'except-parens'],
'no-self-assign': 2,
'no-self-compare': 2,
'no-sequences': 2,
'no-shadow-restricted-names': 2,
'no-spaced-func': 2,
'no-sparse-arrays': 2,
'no-this-before-super': 2,
'no-throw-literal': 2,
'no-trailing-spaces': 2,
'no-undef': 2,
'no-undef-init': 2,
'no-unexpected-multiline': 2,
'no-unmodified-loop-condition': 2,
'no-unneeded-ternary': [2, {
'defaultAssignment': false
}],
'no-unreachable': 2,
'no-unsafe-finally': 2,
'no-unused-vars': [2, {
'vars': 'all',
'args': 'none'
}],
'no-useless-call': 2,
'no-useless-computed-key': 2,
'no-useless-constructor': 2,
'no-useless-escape': 0,
'no-whitespace-before-property': 2,
'no-with': 2,
'one-var': [2, {
'initialized': 'never'
}],
'operator-linebreak': [2, 'after', {
'overrides': {
'?': 'before',
':': 'before'
}
}],
'padded-blocks': [2, 'never'],
'quotes': [2, 'single', {
'avoidEscape': true,
'allowTemplateLiterals': true
}],
'semi': [2, 'always'],
'semi-spacing': [2, {
'before': false,
'after': true
}],
'space-before-blocks': [2, 'always'],
'space-before-function-paren': [2, 'never'],
'space-in-parens': [2, 'never'],
'space-infix-ops': 2,
'space-unary-ops': [2, {
'words': true,
'nonwords': false
}],
'spaced-comment': [2, 'always', {
'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ',']
}],
'template-curly-spacing': [2, 'never'],
'use-isnan': 2,
'valid-typeof': 2,
'wrap-iife': [2, 'any'],
'yield-star-spacing': [2, 'both'],
'yoda': [2, 'never'],
'prefer-const': 2,
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
'object-curly-spacing': [2, 'always', {
objectsInObjects: false
}],
'array-bracket-spacing': [2, 'never']
}
}

1.3 添加 .eslintignore 到根目录

忽略 lint 的文件

1
2
node_modules
dist

2. Prettier

Prettier是一个代码格式化工具,可以让我们在开发过程中快速格式化代码。

2.1 安装Prettier

1
npm install --save-dev --save-exact prettier

2.2 生成一个空的配置文件

1
2
# 生成空的配置文件
echo {}> .prettierrc.json

2.3 创建一个 .prettierignore 文件

1
2
3
4
5
6
# Ignore artifacts:
build
coverage

# Ignore all HTML files:
*.html

3. Husky

Husky是一个 Git 的钩子,可以在我们进行 commit 或者 push 等操作时,运行一些其它命令(比如 npm run lint

3.1. 安装 Husky

1
npm npm install husky -D

3.2. 添加 scripts

1
2
3
4
5
6
7
8
9
# 1. 在 package.json 文件中添加 scripts 
"scripts": {
# ...
"prepare": "husky install"
# ...
}

# 2. 运行命令
npm run prepare

3.3. 添加 hook

注意:这里的 npm test 就是你最终要运行的钩子命令,一般就是 npm run lint ,新版本的 vue cli 使用的是 @vue/cli,对应的 lint 命令为 vue-cli-service lint,在执行前请运行 npx browserslist@latest --update-db 来更新 browserslist 配置。

1
2
npx husky add .husky/pre-commit "npm test" # npm test ==> npm run lint
git add .husky/pre-commit

3.4. 添加一个 commit

1
2
git commit -m "Keep calm and commit"
# `npm test` will run every time you commit

最终 husky 会在根目录下生成一个 .husky/ 文件夹,里面就是对应的配置

4. Lint-staged

Lint-staged可以让我们只校验添加到 git 暂存区中的代码,不会对当前项目所有代码进行Lint,节省了不少时间。

4.1. 安装 lint-staged

1
npx mrm@2 lint-staged

4.2. 运行完毕

  • 会在 .husky/pre-commit 文件中添加一行 npx lint-staged
  • 会在 package.json 文件中添加一行配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // 这是默认配置
    "lint-staged": {
    "*.{js,vue}": "eslint --cache --fix",
    "*.{js,css,md}": "prettier --write"
    },

    // 建议改成
    "lint-staged": {
    "src/**/*.{js,vue}": [
    "npm run lint"
    ],
    "*.{js,css,md}": "prettier --write"
    },