为vite项目自动添加eslint和prettier

762 阅读4分钟

1. vite-pretty-lint

项目中配置合适的代码格式化配置方案助于统一项目代码风格,让开发者专注于代码逻辑本身,更有助于提高团队协作中代码的可读性,提高协作效率。

一般以下步骤:

  • 安装eslint和配置eslintrc.json
  • 安装prettier和配置prettier.json

当多个项目或者团队多人需要公用一套格式化配置时,重复的工作就需要通过工具来解放双手。vite-pretty-lint是一个自动为vite项目添加eslint和prettier的工具包,研究源码有助于学习批量给多个项目添加配置或者修改文件的思路。

vite-pretty-lint配置:

  • 在vite项目中运行 npm init vite-pretty-lint 即可完成默认配置

github地址: github.com/tzsk/vite-p…

\

2. 主要项目结构

vite-pretty-lint

...

├── lib

│   ├── ast.js // ast语法树模板

│   ├── main.js // 项目入口

│   ├── shared.js // 公共配置模板

│   ├── templates // 不同项目类型的配置模板

│   │   ├── react-ts.js

│   │   ├── react.js

│   │   ├── vue-ts.js

│   │   └── vue.js

│   └── utils.js // 公共方法

├── tests // 测试相关

...

├── package-lock.json

├── package.json

└── vitest.config.js

3. 本地运行与调试

拉下代码,本地安装依赖之后准备运行项目。

这里学到一个新知识点:

new npm inite 命令会执行package.json的bin中配置的命令

从package.json中可以看出,npm create-vite-pretty-lint时,执行的时入口文件"lib/main.js"

{
  ...
  "bin": {
      "create-vite-pretty-lint": "lib/main.js"
   },
  ...
}

可以使用node lib/main.js本地运行进行调试

然而,直接在该项目中运行node lib.mian.js,脚本中止并提示找不到vite.config.js

原因是该工具是在vite项目的运行环境中执行配置方法的,所以正确的本地调试方法应该是在一个本地的vite项目中调用该package。

正确本地运行姿势:

  • 新初始化一个本地的vite项目vite-demo
  • 在vite项目中运行 node ../vite-pretty-lint/lib/main.js

目录关系

...

├── vite-demo

└── vite-pretty-lint

4. 源码的调试和学习

本地运行的过程结合lib/main.js中的代码,可以大致了解工具运行的过程如下:

过程的逻辑很清晰,主要的逻辑lib/main.js中,有许多值得学习的地方

4.1 npm package: chalk

www.npmjs.com/package/cha…

运行时发现的终端输出的字符带生动的样式,原来是chalk发挥的作用

console.log(
    chalk.bold(
      gradient.morning('\n🚀 Welcome to Eslint & Prettier Setup for Vite!\n')
    )
  );

结果:

\

4.2 npm package: enquirer

www.npmjs.com/package/enq…

命令行中的选择过程是通过enquirer实现的

export function askForProjectType() {
  return enquirer.prompt([
    {
      type: 'select',
      name: 'projectType',
      message: 'What type of project do you have?',
      choices: getOptions(),
    },
    {
      type: 'select',
      name: 'packageManager',
      message: 'What package manager do you use?',
      choices: ['npm', 'yarn', 'pnpm'],
    },
  ]);
}

结果:

\

4.3 process.cwd()

该方法返回 Node.js 进程的当前工作目录。

通过此node API在vite项目运行此npm包时,vite-pretty-lint可以定位到vite项目的目录地址,并且获取对应的配置以备修改配置所需。

const projectDirectory = process.cwd();

const eslintFile = path.join(projectDirectory, '.eslintrc.json');
const prettierFile = path.join(projectDirectory, '.prettierrc.json');
const eslintIgnoreFile = path.join(projectDirectory, '.eslintignore');
...
const viteJs = path.join(projectDirectory, 'vite.config.js');
const viteTs = path.join(projectDirectory, 'vite.config.ts');

这个node API可以和几个类似的API结合学习

console.log(process.execPath) // 当前执行node的路径
console.log(process.cwd) // 当前命令行执行的路径
console.log(_dirname) // 当前执行脚本所在的路径
console.log(_filename) // 当前正在执行脚本的文件夹名

4.4 await import()

const { packages, eslintOverrides } = await import(
    `./templates/${projectType}.js`
);

动态引入中尝试了把await删除,无法获取到packages和eslintOverrides,背后原因可以后面再深入学习。

4.5 node API:fs

fs(file system)是node中提供本地文件读写能力的核心模块

nodejs.org/api/fs.html

4.6 AST抽象语法树

viteEslint方法中,该方法主要功能是合并配置。大致过程是将动态选中的配置文件和公共配置文件通过babel转换为ast后在进行合并,合并之后通过babel转换为js。

export function viteEslint(code) {
  const ast = babel.parseSync(code, {
    sourceType: 'module',
    comments: false,
  });
  const { program } = ast;

  ...
  // 合并配置
  ...

  ast.program = program;

  return babel.transformFromAstSync(ast, code, { sourceType: 'module' }).code;
}

关于ast这点引用一些网上的文章进行学习了解:

这样入门 js 抽象语法树(AST),从此我来到了一个新世界

JavaScript中AST详解

5. 总结

vite-pretty-lint工具源码逻辑简洁,逐行阅读下来还算比较轻松,但也有不少收获:

  • npx与npm
  • npm init 原理
  • eslint+prettier 基本实现
  • 命令行开发常用npm包:chalk, enquirer
  • node APIs:各种路径相关的apis,fs文件系统模块
  • babel与ast抽象语法树
  • 对多个项目进行批量修改文件的封装思想