观Bun 1.0有感之实现前端检查器集成eslint配置+jest和mocha自动化测试
近期,前端运行时 Bun 1.0 正式发布。在相关的话题文章中,我看到这么一段话
- "Bun 不仅是一个专注性能与开发者体验的全新 JavaScript 运行时,还是一个快速的、全能的工具包,可用于运行、构建、测试和调试JavaScript和TypeScript代码,无论是单个文件还是完整的全栈应用"。*
是不是一开始就觉得这好像这是一个很厉害的东西,确实,我当时被这句话中 "全能" 所吸引,因为我也在开发自己的一个脚手架,一个功能强大,拓展性强的脚手架一直是我的追求。我被Bun 1.0中的测试运行器所吸引,它内置了一个测试模块,且与Jest完全兼容。我的想法也油然而生:
- 在我的脚手架上实现一个前端检查器,集成eslint语法检查+jest和mocha自动化测试
为什么要实现前端检查器
- 对团队代码规范实施统一管控,不同项目会维护不同的lint规范,无法实施统一管控
- 可以用于代码提交前对项目进行集中管控,对不符合规范的项目进行拦截
- 实现自动化测试的自动识别和执行,避免手动执行
在开发中,其实我们每个项目通常都会去配置一个eslint配置文件,这样子不同的项目配置文件存在着一些差异,不能实现团队项目的统一管控。而我所实现的前端检查器主要的一个任务就是不需要的项目中去创建eslint配置,而是通过脚手架去维护一个eslint配置,并用这套配置对代码进行检查。对于实现jest和mocha自动化测试,希望项目中不配置自动化测试工具也能通过脚手架去进行自动化测试
如何实现前端检查器
- eslint配置 + API调用
- jest 和 mocha自动化测试
说明
这个脚手架是我之前就开始做的,使用的技术栈是 lerna
、command
、egg.js
、mongodb
,在实现前端检查器之前已经实现了可使用 t-tsheep init下载vue3、react18、vue-element-admin 三种模板和实现了t-tsheep install命令拉取github和gitee远程仓库并下载项目及项目依赖两个功能,仓库地址:github.com/luo29/tshee... 。后续可能会写从零开始搭建脚手架并实现这些功能的文章。
功能实现
- 终端创建 lint 分包
arduino
// 终端
lerna create lint packages/
- 代码架构实现
js
// packages/lint/lib/index.js
import path from "node:path";
import Command from "@tsheep.com/command";
import { log, makeList, printErrorLog } from "@tsheep.com/utils";
import { ESLint } from "eslint";
import { execa } from "execa";
import ora from "ora";
import jest from "jest";
import Mocha, { test } from "mocha";
import vueConfig from "./eslint/vueConfig.js";
/**
* examples:
* t-tsheep lint
*/
class LintCommand extends Command {
get command() {
return "lint";
}
get description() {
return "lint project";
}
get options() {
return [];
}
extractESlint(resultText, type) {
const problems = /[0-9]+ problems/;
const warnings = /([0-9]+) warnings/;
const errors = /([0-9]+) errors/;
switch (type) {
case "problems":
return resultText.match(problems)[0].match(/[0-9]+/)[0];
case "warnings":
return resultText.match(warnings)[0].match(/[0-9]+/)[0];
case "errors":
return resultText.match(errors)[0].match(/[0-9]+/)[0];
default:
return null;
}
}
parseESlintResult(resultText) {
const problems = this.extractESlint(resultText, "problems");
const errors = this.extractESlint(resultText, "errors");
const warnings = this.extractESlint(resultText, "warnings");
return {
problems: +problems || 0,
errors: +errors || 0,
warnings: +warnings || 0,
};
}
async action() {
// 1.eslint
await this.eslintAction();
const testMode = await makeList({
choices: [
{ name: "jest", value: "jest" },
{ name: "mocha", value: "mocha" },
],
message: "请选择测试模型",
});
if (testMode === "jest") {
// 2.jest
await this.jestAction();
} else {
// 3.mocha
await this.mochaAction();
}
}
async eslintAction() {
log.verbose("lint");
const spinner = ora("正在安装ESlint相关依赖").start();
try {
await execa("npm", ["install", "-D", "eslint-plugin-vue"]);
await execa("npm", ["install", "-D", "eslint-config-airbnb-base"]);
} catch (e) {
printErrorLog(e);
} finally {
spinner.stop();
}
log.info("正在进行eslint检查");
// 执行工作,eslint
const cwd = process.cwd();
const eslint = new ESLint({ cwd, overrideConfig: vueConfig });
const results = await eslint.lintFiles(["./src/**/*.js", "./src/**/*.vue"]);
const formatter = await eslint.loadFormatter("stylish");
const resultText = formatter.format(results);
const eslintResult = this.parseESlintResult(resultText);
log.verbose("eslintResult", eslintResult);
log.success(
"eslint检查完毕",
"错误:" + eslintResult.errors,
",警告:" + eslintResult.warnings
);
}
async jestAction() {
log.info("自动执行jest测试");
await jest.run("test");
log.success("jest测试执行成功");
}
async mochaAction() {
const cwd = process.cwd();
log.info("自动执行mocha测试");
const mochaInstance = new Mocha();
mochaInstance.addFile(path.resolve(cwd, "__tests__/mocha_test.js"));
mochaInstance.run(() => {
log.success("mocha测试执行完毕");
});
}
}
function Lint(instance) {
return new LintCommand(instance);
}
export default Lint;
- eslint配置
js
// packages/lib/eslint/Vueconfig.js
export default {
env: {
browser: true,
es2021: true,
},
extends: ["plugin:vue/vue3-essential", "airbnb-base"],
overrides: [],
parserOptions: {
ecmaVersion: "latest",
sourceType: "module",
},
plugins: ["vue"],
rules: {},
};
这是配置的vue模板eslint检查,在这里也可以根据项目所需的eslint检查进行配置
实现效果
- 创建一个vue项目进行测试
- 执行t-tsheep lint 进行检查
总结
这就是从遐想到构建又到实现的一路"砍瓜切菜"。因为这次只展现了实现的代码和结果,全部代码在上面提到的仓库里面。后续我也可能会写一个从零实现这个脚手架的专栏。