观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 进行检查

总结

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

相关推荐
逛逛GitHub1 小时前
AI 时代 Markdown 又火了,7 款 GitHub 高赞开源编辑器。
github
小白说大模型2 小时前
LLM集成数据库的幻觉治理:当AI给出的SQL建议是错的
数据库·人工智能·sql·oracle·重构·开源
u1301302 小时前
GitHub 热榜项目:日榜(2026-08-18)
github
峰向AI2 小时前
5万多人点赞的下载工具,凭什么让我放下了用了三年的老软件
github
glustful3 小时前
语音唤醒技术选型与实践:从开源方案到自主训练
开源·ai智能·语音唤醒·语音服务
OpsEye4 小时前
直连大模型API、开源网关、商用AI管理平台,该如何抉择
人工智能·开源
ClouGence4 小时前
2026 年 4 款数据库管理工具推荐:免费、开源、付费怎么选?
数据库·后端·开源
人工智能研究所5 小时前
正面硬刚 Seedance 2.5, 开源视频模型:LTX-2.5 用 6.8 秒生成 10 秒视频
人工智能·开源·音视频·文生视频·seedance·ltx-2.5
ZJU_统一阿萨姆5 小时前
【推理优化进阶】图编译与运行时:动态形状、CUDA Graph 与内存规划
开发语言·人工智能·语言模型·架构·开源
小玮看世界5 小时前
AtomGit 429 报错引发的思考:从“未授权限流”看开源平台的“浏览权”博弈
开源·github