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

总结

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

相关推荐
HelloGitHub1 小时前
跟着 8.6k Star 的开源数据库,搞 RAG!
开源·github
GitCode官方2 小时前
GitCode 光引计划投稿 | GoIoT:开源分布式物联网开发平台
分布式·开源·gitcode
m0_748256782 小时前
WebGIS实战开源项目:智慧机场三维可视化(学习笔记)
笔记·学习·开源
猫头虎2 小时前
新纪天工 开物焕彩:重大科技成就发布会参会感
人工智能·开源·aigc·开放原子·开源软件·gpu算力·agi
血色橄榄枝4 小时前
进阶岛-L2G5000
人工智能·开源
sdaxue.com13 小时前
帝国CMS:如何去掉帝国CMS登录界面的认证码登录
数据库·github·网站·帝国cms·认证码
在肯德基吃麻辣烫14 小时前
使用开源在线聊天工具Fiora轻松搭建个性化聊天平台在线交流
开源
m0_7482475514 小时前
github webhooks 实现网站自动更新
github
是小崔啊14 小时前
开源轮子 - EasyExcel01(核心api)
java·开发语言·开源·excel·阿里巴巴
张国荣家的弟弟15 小时前
【Yonghong 企业日常问题04】永洪BI可视化工具Linux部署全攻略(部署详解版)
linux·运维·github