项目集成之语法规范
项目语法规范在大型项目以及团队成员之间的协作中发挥着非常重要的作用,尤其是在项目需求变更或者重构时随心所欲的代码可能让团队头疼简直比推倒重写还难。因此团队统一代码规范及质量有利于团队之间的协作,更有益于项目的长远维护,那么如何做好这方面的工作呢?
当然这里对于语法规范及质量要求只是个辅助工具,最重要的核心性能提升还是要靠每个人的开发功底
重要性
前面简单讲了下随心所欲的代码会变得难以维护,无规矩不成方圆,只有大家达成同一种编码意识,才能事半功倍。在项目开发中代码的质量及语法规范发挥着重要的作用,主要体现在以下几点:
可读性和可维护性:高质量的代码应具有良好的可读性,使团队成员能够轻松理解代码逻辑和意图。可维护性是指代码易于修改和扩展,减少引入错误的风险。良好的代码质量可以提高代码的可读性和可维护性,使团队能够更轻松地维护和修改代码
可靠性和稳定性:优质的代码应具备高度的可靠性和稳定性,以减少bug和错误的发生。良好的代码质量可以通过静态类型检查、代码规范、单元测试等方式来提高代码的可靠性,并减少在项目维护过程中出现的潜在问题
可扩展性和重用性:良好的代码质量可以提供良好的结构和设计,使代码易于扩展和重用。模块化和清晰的代码结构可以促进团队协作,使团队成员能够更轻松地理解和使用彼此的代码,从而提高开发效率和项目的可扩展性
团队协作和知识共享:高质量的代码可以促进团队协作和知识共享。一致的代码风格、规范和最佳实践可以帮助团队成员更好地理解和协作,减少因为代码质量差异而引起的摩擦和冲突
如何做
首先需要在每个人的编码功底的基础上使用统一的编码规范,可以借助辅助工具eslint帮助检查编码的规范降低错误风险。除此之外可以在项目中添加typescript,众所周知js是个弱类型动态语言,对于相关变量的类型要求没有约束,如下面代码:
// 数字与字符串的转换问题
var total = 3;
total = "3";
total += 3; // => "33"
2
3
4
除了上面的问题外还有很多常见的问题如:变量提升、作用域问题等等,因此使用纯原生js很有可能造成相关问题,那么通过eslint结合ts就可以完美的解决这些问题。使用ts可以加强类型提示,使得js如其他语言Java一样可以对类型进行限制,从而降低代码错误风险
ESLint
eslint是一个JavaScript/TypeScript的静态代码分析工具,用于检测和报告代码中的潜在问题和编码规范的违规。它可以帮助检查修复运行时漏洞、最佳规范实践、代码风格等问题,但推荐仅作为漏洞、语法规范的检查器。对于协同编码规范eslint是必不可少的工具,总之没有typescript也不能没有eslint
ESLint原理是基于静态代码分析,通过解析代码构建抽象语法树,然后应用配置的规则来对代码进行检查和分析
配置文件
eslint支持多种形式的配置文件,你可以创建.eslintrc.js
、.eslintrc.json
、.eslintrc.yml
或在package.json
中配置eslint,下面以.eslintrc.js
形式配置:
module.exports = {
root: true,
env: {}, // 环境
globals: {}, // 全局变量
extends: [], // 扩展
plugins: [], // 插件
parser: "", // 解析器
parserOptions: {}, // 解析器选项
rules: {}, // 具体规则
overrides: { files: [], rules: {} }, // 覆盖特定规则
}
2
3
4
5
6
7
8
9
10
11
eslint配置总体来说包含env、globals、extends、plugins、parser、parserOptions、rules、overrides等几个模块的配置,了解每个模块的作用对理解整体eslint的配置非常重要
创建eslint忽略的检查文件,可以在配置文件中添加ignorePatterns
字段配置,或者创建一个单独的配置文件.eslintignore
(推荐):
node_modules
.eslint*
// etc..
2
3
environments、globals
environments、globals都是用来设置设置当前代码的语言环境和全局变量的,通过二者配置可以轻松使用环境中的语法和变量以及自定义全局变量
environments 设置代码的语言环境,可以设置一个或多个,支持的语言选择项有:browser、node、commonjs、es6等等,简单配置:
module.exports = {
env: {
browser: true,
node: true,
es6: true
}
}
// 代码中可以使用browser、node、es6的语法及变量
// window.innerWidth
// process.env
// Promise
2
3
4
5
6
7
8
9
10
11
12
globals 用来配置自定义的全局变量,告诉eslint会存在的全局变量有哪些,这样对于没有定义的全局变量就不会报错了:
module.exports = {
globals: {
__is_Dev__: "realonly",
version: "writable"
}
}
// 定义了 __is_Dev__、version 两个全局变量,前者只读、后者可以修改
if (__is_Dev__) console.log("dev");
console.log(version);
version = "change version";
2
3
4
5
6
7
8
9
10
parser、parserOptions
parser用于指定 ESLint 使用的解析器。解析器负责将代码转换成抽象语法树AST,以便 ESLint 可以对代码进行静态分析。默认情况eslint使用espree作为解析器,除此之外常用的解析器有以下几种:
- Esprima:基于 JavaScript 的 ECMAScript 5.1 标准实现的解析器,很适合纯粹的 JavaScript 项目
- @babel/eslint-parser:使 Babel 解析器与 ESLint 兼容的的包装器
- @typescript-eslint/parser:将 TypeScript 转换为与 ESTree 兼容的形式的解析器,通常在ts项目中使用其作为解析器
module.exports = {
parser: "@typescript-eslint/parser"
}
2
3
parserOptions用于提供解析器的选项和配置信息,比如支持的js版本、jsx支持等等,为解析器服务
module.exports = {
parserOptions: {
"ecmaVersion": "latest", // js版本
"sourceType": "module", // 代码形式 module | script
// "allowReserved": true, // 允许使用保留字
"ecmaFeatures": { // 特性
"jsx": true,
"globalReturn": true, // 全局return
"impliedStrict": true // 严格模式
}
}
}
2
3
4
5
6
7
8
9
10
11
12
这块应该比较好理解的,大家根据自己的需求选择即可
rules、overrides
以上的属性如不作特殊定制可以不进行配置,rules是eslint的核心模块,用来配置代码校验的一套规则。eslint中内置了很多规则,可以根据自己需求进行配置,规则还可以包含针对该规则的额外配置选项
规则值
- "off" 或 0 - 关闭规则
- "warn" 或 1 - 启用并视作警告(不影响退出)。
- "error" 或 2 - 启用并视作错误(触发时退出代码为 1)
除此之外还可以针对单个规则添加额外的配置
示例
module.exports = {
rules: {
'no-console': 'warn', // console警告
"no-tabs": 0, // 关闭tabs 规则
"max-len": ['error', { 'code': 80 }], // 每行最大长度,超过80报错
}
}
2
3
4
5
6
7
上面展示了如何使用 '字符' 和 '数值' 作为值,并对 'max-len' 单个规则设置了选项
优先级
规则优先级 extends < rules < overrides < comments
overrides
知道了rules那么什么是overrides呢?rules是对设置的指定目标进行代码检查,如果对于特殊的目标文件不想使用rules的规则,那么就可以使用overrides进行规则覆盖
module.exports = {
"rules": {
"quotes": ["error", "double"]
},
"overrides": [
{
"files": ["bin/*.js", "lib/*.js"],
"excludedFiles": "*.test.js",
"rules": {
"quotes": ["error", "single"]
}
}
]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
上面列子展示了在bin、lib下除了*.test.js外只能使用单引号,覆盖掉全局的双引号规则
plugins、extends
前面知道eslint内置了很多规则和默认解析解析器,那么plugins就是来扩展除内置以外的其他规则,说白了就是让eslint有解析其他自定义规则的能力。注意引入plugin并不是引入了当前plugin中所有的规则,他只是扩展了eslint解析当前plugin中规则的能力,至于具体的规则还需要在rules中配置
module.exports = {
plugins: ["react"], // 引入第三方插件,eslint-plugin-react简写
rules: {
"react/jsx-boolean-value": 2 // 配置插件中的规则
}
}
2
3
4
5
6
注意使用第三方插件需要先安装:
➜ npm install eslint-plugin-react -D
插件名通常包含两种形式:
- 非group类:如eslint-plugin-react
- group类:@react/eslint-plugin-react
提示
使用插件时可以省略掉插件名的前的eslint-plugin-
,如:eslint-plugin-react可以写成react,@react/eslint-plugin-react可以写成@react/react
对于插件的规则配置也是基于插件名的两种形式:
// eslint-plugin-react => react/no-console
// @react/eslint-plugin-react => @react/react/no-console
module.exports = {
plugins: ["react", "@react/react"],
rules: {
"react/no-console": "error",
"@react/react/no-console": 1
}
}
2
3
4
5
6
7
8
9
从plugin的使用中可以看到步骤繁琐,需要对plugin中规则一一写出很麻烦,因此引入了extends的概念,用来继承某些规则,如使用了plugin时,可以在extends中写入plugin的推荐配置,命名规则:plugin:包名/规则
module.exports = {
plugins: ["react"],
extends: [
"eslint:recommended", // 继承官方推荐的
"plugin:react/recommended" // 继承react插件中推荐的规则集
]
}
2
3
4
5
6
7
除了可以扩展第三方插件的规则集,还可以使用本地的规则
module.exports = {
extends: ["./somepath/.eslintrc-jsx"]
}
2
3
对于这些工具,一般推荐使用官方维护的eslint插件和配置,然后在其基础上进行定制,这样可以减少繁琐的配置,避免浪费时间
编辑器集成
这里使用vscode进行eslint的集成,首先下载eslint插件
在vscode配置中加入以下配置(或者在设置面板中搜索eslint进行选择配置):
{
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true,
// "source.fixAll": true
},
"eslint.codeActionsOnSave.mode": "problems",
}
2
3
4
5
6
7
以上配置好了后重新vscode
规则集
TypeScript
eslint虽然可以帮助降低代码出错的风险,但仍无法更直接表达相关的类型约束,js是个弱类型语言没有相关的类型约束,对于约束性不强的开发者来说仍是个头疼的问题,久而久之可能就会变得难以维护
使用typescript可以增强类型提示提高开发效率降低协作成本,也方便后续的维护。关于typescript的使用可以查看我有关typescript的文章