观Bun 1.0有感之实现前端检查器集成eslint配置+jest和mocha自动化测试

观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自动化测试

说明

这个脚手架是我之前就开始做的,使用的技术栈是 lernacommandegg.jsmongodb,在实现前端检查器之前已经实现了可使用 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 进行检查

总结

这就是从遐想到构建又到实现的一路"砍瓜切菜"。因为这次只展现了实现的代码和结果,全部代码在上面提到的仓库里面。后续我也可能会写一个从零实现这个脚手架的专栏。

相关推荐
m4Rk_1 小时前
【论文阅读】Agent 记忆机制(75):TiMem——用时间记忆树实现长期记忆的层级巩固
论文阅读·人工智能·学习·开源·github
今夕资源网2 小时前
一只鹈鹕骑着单车闯海岛:开源 3D 网页游戏《鹈鹕骑车》体验与部署教程 github开源
开源·github·ai智能测试题·ai智能测试
沙蒿同学4 小时前
我把架构约定编译成了会变红的测试:Wails v2 + Go + Vue3 桌面脚手架实战
前端·后端·github
落魄大学生之流水线上谋生计5 小时前
幻境相机 Mirage Camera
github
wangruofeng5 小时前
从一个 10 万星 AI Agent 项目里,能学到什么真正的软件工程
github·agent·ai编程
子林super5 小时前
复杂JSON Schema结构与输出校验
github
子林super5 小时前
结构化输出解析失败处理策略
github
怕浪猫6 小时前
拆解 Google《AI Agent Handbook》:企业级 Agent 的六层架构与产品矩阵
面试·github·agent
枫叶丹46 小时前
开源还是开权重:2026 年 AI 模型战争的控制权之争
人工智能·chatgpt·开源·agent·codex
kali-Myon6 小时前
分享一个网络安全 AI 工具导航项目 SecSkills
安全·ai·github·ctf