需求背景
现状
最近新接手一个小程序项目,不管是从项目目录结构划分还是代码层面,整体看起来一个字:乱!!!下面描述的情况随处可见,还有很多未列举的。
// 1-申明了变量却未使用
const util = require('xxx')
// 2-对于后续无修改的变量,还是用var/let申明的
let device = 'iPhone 12'
// 3-后端返回的type, 建议用===对后端输出的数据类型做强类型校验
// 下面的写法后端返回1 or '1'都会走TODO,后端输出不太严谨
if(type == 1) { // TODO }
// 4-单引号、双引号不确定-> 代码样式感
var device = 'iPhone 12'
var version = "v4.5.0.20220524"
预期目标
-
提升代码一致性、可读性
-
提升代码洁癖
基础实践
技术总指南: eslint + prettier + husky + lint-staged
-
- 项目根目录package.json中新增如下配置
"devDependencies": {
"@babel/core": "^7.16.7",
"@babel/eslint-parser": "^7.16.5",
"eslint": "^8.5.0",
"eslint-plugin-prettier": "^4.0.0",
"prettier": "^2.5.1"
}
-
- 安装依赖
npm install
-
- 项目根目录下新建.eslintrc.js文件(注意: 文件名是.eslintrc.js而不是eslintrc.js)
module.exports = {
root: true,
env: {
es6: true,
browser: true,
node: true,
},
parser: '@babel/eslint-parser',
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
ecmaFeatures: {
// lambda表达式
arrowFunctions: true,
// 解构赋值
destructuring: true,
// class
classes: true,
},
},
globals: {
wx: true,
App: true,
Page: true,
getCurrentPages: true,
getApp: true,
Component: true,
requirePlugin: true,
requireMiniProgram: true,
},
rules: {},
}
-
- 项目根目录下新建.eslintignore文件, 该文件主要用来配置哪些目录or页面可跳过eslint的校验(忽略路径是相对项目根目录路径而言的)。
node_modules
-
- 新建.prettierrc.js文件, 该文件是关于prettier相关配置。
module.exports = {
}
-
- 新建.babel.config, 暂时未发现什么用。
module.exports = {
presets: [],
plugins: [],
}
-
- package.json中新增lint脚本命令, 避免每次都需要手动输入很长的一段执行命令
"scripts": {
"lint": "eslint --ext .js ./"
}
-
- 配置完成,进入测试阶段,如下为测试文件。
// 测试文件代码-test.js
const testFn = function () {
let name = 'test'
let age = 20
let userinfo = {}
userinfo.name = name
userinfo.age = age
}
testFn()
-
- 执行测试脚本
npm run lint
-
- 运行效果,报错了。
咦,看图好像所有的报错信息都一样Error:
报错信息: Parsing error: No Babel config file detected for /user/xxx/. Either disable config file checking with requireConfigFile: false, or configure Babel so thar it can find the config files.
解决方案: 在.eslintrc.js文件中新增如下配置。
parserOptions: {
requireConfigFile: false
}
-
- 再次执行测试脚本,看效果。
咦,竟然0 errors,明显跟预期不符合。
问题所在: .eslintrc.js文件中rules规则字段未配置。
-
- .eslintrc.js文件中新增rules规则配置
rules: {
'prefer-const': 1, // 要求使用 const 声明那些声明后不再被修改的变量
}
-
- 再次执行测试脚本,看效果。
根据error or warning信息,找到对应的文件去做修改即可。
至此,你已经成功了一半了,继续加油哦。
进阶实践
通常在刚开始搭建项目的时候没考虑这么多,随着项目团队人员的增加&需求变多,规范化的前端工作流很有必要,很多是对旧项目接入eslint,用上面的基础方案会面临一些问题:
- 旧项目导出可见var/let申明的常量,比如上面那条规则可能就有几千个error(吓得立马删规则跑路),能否实现增量更新呢 (即若对全工程的文件进行扫描&&之前的前段工程并未主动代码规则的检测,很大可能出现成百上千个error,基本上是崩溃的。因此要及时止损,只对当前add的文件进行检测,历史代码可以切换到新分支进行修复后合并)
在接手的旧项目中引入eslint后,报错信息足足2000多条,简直难以想象(因涉及到公司很多代码就不附图了)
下图为个人的一个小程序旧项目引入eslint后,报错信息也有几百条,费劲哦:
-
每次都需要人工执行npm run lint太繁琐了、不科学。
**Husky + lint-stage能够帮我们解决上述问题。
**husky是一个为git客户端增加hook的工具。用于对Git暂存区中的文件执行代码检测,结合husky用到pre-commit这个hook,在执行commit之前,可以运行一些自定义操作。
实现原理剖析:
- 待提交的代码git add添加到暂存区
-
- 完成对增量代码的检查、进入stage区的文件进行扫描即可
-
执行git commit
-
husky注册在git pre-commit的钩子函数被调用,执行lint-staged
-
lint-staged取得所有被提交的文件依次执行写好的任务(Eslint && Prettier)
-
若有错误则停止任务同时打印错误信息;等待修复后再commit
-
若无错误则成功commit,可push到远程;
接下来我们看看要怎么样需求才能被实现呢?
-
- 安装husky && lint-staged
npm install -D husky lint-staged
-
- package.json中新增相关配置
But需要注意的是:pre-commit钩子虽可在执行git commit的时候触发 → 比如lint检查、单元测试、代码美化等操作但是要保证速度不要太慢,不然每次commit很久也是不好的体验。
- package.json中新增相关配置
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.js": [
"eslint",
"prettier --write",
"git add"
]
}
-
- 测试git bash or sourceTree提交(测试代码用的如上的test.js)
咦,好像没生效啊,直接提交成功了:
问题所在: husky跟pre-commit未建立关联。
-
- 在终端输入如下命令
该命令会在.husky文件夹下新建.pre-commit文件, 你需要留意是否有生成。
npx husky add .husky/pre-commit "npx lint-staged"
-
- 再次验证查看效果: ok的
- 再次验证查看效果: ok的
至此,其实就已经满足了整个符合eslint规范的代码才允许被提交,构建了统一的工作流。但其实还遗留了两个问题:
-
若每次提交的文件过大,eslint的时间是成正比增加的,那能否在我们编码的时候就暴露问题呢?
-
eslint rules配置千千万,怎么选择适合团队的rules规则呢,是否能用一些主流的规范呢?
若您想解决这俩个问题,请往下看👇!!!
高级实践
-
- 接入编码过程实时报错
-
- 1.1 编辑器vscode安装插件: 插件-搜索eslint-安装插件
安装插件成功后记得重新下编辑器, 然后你就能看到编码中的文件test.js相关的报错信息在调试器-问题处可实时查看。
其实本身不符合规范的, 基于安装的eslint版本是v2.2.2,也是会在文件处用波浪线表示,鼠标移上去会有相应的错误处理方案, eg如下图:
扩展: 非所有的开发者都会选择用vscode编辑器,对于使用微信开发者工具的开发者,其实也是可以引入eslint插件的,感兴趣的可戳此链接: 微信开发者工具扩展插件版本能否支持手动更新?
-
- 接入airbnb规范
-
- 2.1 package.json中新增下面依赖
npm install eslint-config-airbnb --save-dev
npm install eslint-config-airbnb-base --save-dev
-
- 2.2 修改.eslintrc.js文件
extends: [
'airbnb-base',
// 'plugin:promise/recommended'
'prettier',
],
-
- 2.3 去除.eslintrc.js中rules的配置,默认使用airbnb的,不满足团队规范的在此处做覆盖即可。
// delete rules的配置
rules: {
}
-
- 2.4 执行npm run lint命令测试airbnb是否引入成功
你会看到报错信息,之前的warning警告也变成了error, 是应用了airbnb的效果。
可选配置
eslint auto fix
-
- 其实eslint的部分rules是支持自动fix的,若我们想实现该功能,可修改package.json文件中的lint命令。
"scripts": {
"lint": "eslint --fix --ext .js ./" // 新增该语句
}
-
- 测试运行效果,执行npm run lint脚本
// test.js
const testFn = function () {
const userinfo = {};
let sex = '女';
userinfo.sex = sex;
};
testFn();
// npm run lint自动fix后该文件变动如下:
const testFn = function () {
const userinfo = {};
const sex = '女';
userinfo.sex = sex;
};
testFn();
你会发现,自动把对于let申明的变量后续无修改的,自动改成建议的const申明为常量。But不是所有的规则都适合fix,目前刚接入的阶段,建议采用人工fix比较好。
prettier的配置
prettier主要是用于统一样式,比如双引号、单引号这种。
- .prettier文件中新增如下配置
module.exports = {
singleQuote: true // 统一格式化后单引号
}
- 测试代码如下
const testFn = () => {
const userinfo = {};
const sex = "女";
userinfo.sex = sex;
};
testFn();
- 借助sourcTree提交后的效果:
咦,好像配置不生效啊,因为没有主动改成单引号:
经过排查之后发现是prettier的配置文件名写错了, 应该是.prettierrc.js而不是.prettier.js哦,需要小心。
纠正后再次测试,OK的,已经生效。
落地相关QA(持续更新)
问题一
问题描述: 使用mac的某一个小伙伴反馈在mac系统提交的代码没走eslint校验,大概率是由于脚本是不可执行的,执行下如下脚本给执行脚本添加执行权限。
解决方案如下: 项目根目录下执行如下脚本添加权限.
chmod ug+x .husky/*
问题二
问题描述: 切换到新分支,然后一顿操作写了很多代码提交,咦,发现竟然没法提交代码了。
报错信息如下: Some of your tasks use git add
command. Please remove it from the config since all modifications made by tasks will be automatically added to the git commit index.
后经排查发现:有同事在新分支上对.husky目录下的钩子文件有改动。
解决方案如下: 删除本地node_modules文件,重新npm install一下即可.
写在最后
若有错误之处, 恳请留言, 定会及时更正!
创作不易,如果您从文章中学到了东西,麻烦点个赞或者关注下再走呗,您的支持是我持续创作的动力!