核心目标:实现如果提git commit的文件中存在eslint报错,就终止commit(merge-commit除外)
Eslint接口用法
根据官网的示例,我们可以通过如下代码获取到指定文件的Eslint报错信息
const fs = require('fs');
const CLIEngine = require('eslint').CLIEngine;
const cli = new CLIEngine({
parser: '@babel/eslint-parser',
env: {
browser: true
},
extends: '../rules/index'
});
const code = fs.readFileSync('../test/index.jsx', 'utf-8');
const report = cli.executeOnText(code);
console.log(report.results[0].messages);
对于test/index.jsx文件件,测试内容如下:
import React from 'react';
import PropTypes from 'prop-types';
new Buffer(5);
new Buffer([1, 2, 3]);
得到的输出结果是:
[
{
ruleId: 'no-unused-vars',
severity: 2,
message: "'React' is defined but never used.",
line: 1,
column: 8,
nodeType: 'Identifier',
messageId: 'unusedVar',
endLine: 1,
endColumn: 13
},
{
ruleId: 'no-unused-vars',
severity: 2,
message: "'PropTypes' is defined but never used.",
line: 2,
column: 8,
nodeType: 'Identifier',
messageId: 'unusedVar',
endLine: 2,
endColumn: 17
},
{
ruleId: 'import/no-extraneous-dependencies',
severity: 2,
message: "'prop-types' should be listed in the project's dependencies. Run 'npm i -S prop-types' to add it",
line: 2,
column: 23,
nodeType: 'Literal',
endLine: 2,
endColumn: 35
},
{
ruleId: 'no-new',
severity: 2,
message: "Do not use 'new' for side effects.",
line: 4,
column: 1,
nodeType: 'ExpressionStatement',
messageId: 'noNewStatement',
endLine: 4,
endColumn: 15
},
{
ruleId: 'no-buffer-constructor',
severity: 2,
message: 'new Buffer() is deprecated. Use Buffer.from(), Buffer.alloc(), or Buffer.allocUnsafe() instead.',
line: 4,
column: 1,
nodeType: 'NewExpression',
messageId: 'deprecated',
endLine: 4,
endColumn: 14
},
{
ruleId: 'no-new',
severity: 2,
message: "Do not use 'new' for side effects.",
line: 5,
column: 1,
nodeType: 'ExpressionStatement',
messageId: 'noNewStatement',
endLine: 5,
endColumn: 23
},
{
ruleId: 'no-buffer-constructor',
severity: 2,
message: 'new Buffer() is deprecated. Use Buffer.from(), Buffer.alloc(), or Buffer.allocUnsafe() instead.',
line: 5,
column: 1,
nodeType: 'NewExpression',
messageId: 'deprecated',
endLine: 5,
endColumn: 22
}
];
我们可以获知一个错误的级别、所处的位置、报错内容、错误名称等信息,这些信息足够我们定位问题。如果没有报错,则 report.results[0].messages 是一个空数组。
如何获取Git提交文件
修改.git/hooks/文件夹下的文件,可以执行对应的钩子函数
在钩子函数里执行如下命令 git diff --staged --diff-filter=ACMR --name-only -z,可以得到缓存区(被commit的都是进入缓存区的)里对应的变化文件。
其中--diff-filter取值的含义是:
- Added (A),
- Copied (C)
- Deleted (D)
- Modified (M)
- Renamed (R)
与Git的结合
我们可以利用husky+lint-staged实现上述功能
常见问题
- 如果安装
husky之后发现.git/hooks/文件夹下面没有生成对应的钩子脚本,可以试着尝试更改node或npm版本,我安装4.3.8版本的husky,如果node版本是9.11.2就不成功,改为13.10.2就成功了。查阅文档发现一行小字:Existing hooks are kept. Requires Node >= 10 and Git >= 2.13.0.。不过究竟是升级后哪个地方导致的,目前还不清楚。其实husky的这点很不友好,因为在团队开发中,存在无法统一node版本的情况,会出现钩子执行覆盖不到的情况。针对这种情况,我们可以自己编写一个npm script,利用pre&post特性,给项目必用的命令添加前置或后置命令,自己覆盖掉.git/hooks/里的指定命令。