【前端】基于vite的react项目工程化(1)

928 阅读11分钟

1.vite创建项目

我的技术栈是react,因此创建项目时有2种选择:

  • 1.使用create-react-app创建
  • 2.基于vite创建,目前5.2.0版本(2024.04.07)

推荐使用基于vite创建,因为vite是基于浏览器 es module import 实现的编译服务,而CRA底层是基于webpack编译打包,多了打包环节,开发时界面响应速度就慢,具体可参考vite实现原理

在创建时推荐使用pnpm包管理工具,具体原因在这,创建命令是: pnpm create vite frontend --template react-ts ,该模版来自这里

2.代码质量工具

eslint侧重检查js语法错误,prettier侧重格式化代码样式,stylelint侧重css代码检查

在vite创建React项目时就已经内置了ESlint

1.首先初始化eslint,执行pnpm create @eslint/config会生成.eslintrc.cjs 配置文件:

这里执行pnpm create @eslint/config相当于执行pnpm eslint --init,使用的eslint版本为"eslint": "^8.57.0",在eslint>=8.23.0时使用eslint.config.js配置文件而不是.eslintrc.cjs文件,具体说明来自这里,但也能兼容 截屏2024-04-07 20.26.08.png 执行结果如下: 截屏2024-04-07 20.27.54.png 可以看到生成的配置文件继承了 'eslint:recommended','plugin:@typescript-eslint/recommended','plugin:react-hooks/recommended',如果需要配置 lint 规则可以在 rules 中添加,此时自动生成的.eslintrc.cjs文件包含以下内容:

module.exports = {
  root: true,
  env: { browser: true, es2020: true },
  extends: [
    'eslint:recommended',// ESLint 官方推荐的规则集
    'plugin:@typescript-eslint/recommended',
    'plugin:react-hooks/recommended',
  ],
  ignorePatterns: ['dist', '.eslintrc.cjs'],
  parser: '@typescript-eslint/parser',
  plugins: ['react-refresh'],
  rules: {
    'react-refresh/only-export-components': [
      'warn',
      { allowConstantExport: true },
    ],
  },
}

此时在App.tsx中删除return中的内容后,会在上面发现'useState' is defined but never used.eslint[@typescript-eslint/no-unused-vars](https://typescript-eslint.io/rules/no-unused-vars),说明此时eslint开始起作用了

截屏2024-04-07 19.18.29.png

但是会发现此时package.json中自动添加了一个lint的脚本 "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",当执行pnpm run lint时会报错:

截屏2024-04-07 19.32.23.png 这是因为在最新的ESLint版本中,--ext命令行选项不再可用,文件扩展名应通过配置文件中的files属性来指定,而不是在命令行中指定。

export default {
  // ...
  files: ["**/*.{ts,tsx}"],
  // ...
};

将命令修改成"lint": "eslint . --report-unused-disable-directives --max-warnings 0"此时再执行pnpm run lint时,结果如下: 截屏2024-04-07 21.17.26.png 会发现.eslintrc.cjs根本不需要eslint检测,直接将其忽略/* eslint-disable */后再去执行 截屏2024-04-07 21.24.30.png

2.接着来安装prettier:

pnpm i prettier -D

然后在根目录创建 .prettierrc.cjs 配置文件

module.exports = {
    // 每行最大列,超过换行
    printWidth: 120,
    // 使用制表符而不是空格缩进
    useTabs: false,
    // 缩进
    tabWidth: 2,
    // 结尾不用分号
    semi: false,
    // 使用单引号
    singleQuote: true,
    // 在JSX中使用单引号而不是双引号
    jsxSingleQuote: true,
    // 箭头函数里面,如果是一个参数的时候,去掉括号
    arrowParens: "avoid",
    // 对象、数组括号与文字间添加空格
    bracketSpacing: true,
    // 尾随逗号
    trailingComma: "none",
  };

在App.tsx添加 ";" 执行以下命令测试pnpm prettier --write ./src/App.tsx ,会发现文件被自动修复

3.接下来在 ESLint 中引入 Prettier,安装相关依赖:

虽然已经安装了eslint和prettier,但为了让ESLint能够在执行时调用Prettier进行代码格式化的检查和修正,就需要在ESLint配置文件中集成Prettier的规则。

pnpm i eslint-config-prettier eslint-plugin-prettier -D

其中eslint-plugin-prettier 是将 Prettier 的代码格式化规则转化为 ESLint 可以识别和执行的规则,eslint-config-prettier 是关闭或忽略 ESLint 中与 Prettier 产生冲突的格式化相关的规则

然后更改 Eslint 的配置文件 .eslintrc.cjs 在里面加入 Prettier 相关配置。具体含义在这

module.exports = {
  // 其他ESLint配置...
  extends: [
    // ...其他继承的规则集
    'plugin:prettier/recommended', // 引入Prettier的推荐规则
 ],
 plugins: [
   // ...其他插件
   'prettier', // 添加Prettier插件
 ],
  rules: {
    // 确保Prettier规则优先级最高
    'prettier/prettier': 'error',
    // 其他自定义规则...
  },
};

同样在App.tsx中添加";"后执行pnpm run lint命令,就会调用prettier:

截屏2024-04-07 21.34.16.png 可以更改eslint脚本,加上自动修改"lint": "eslint . --report-unused-disable-directives --max-warnings 0 --fix",

4.在 Vite 中引入 ESLint 插件,以便在开发阶段发现问题,自动触发eslint。

首先安装依赖pnpm i vite-plugin-eslint -D ,然后在 vite.config.ts 引入插件

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import viteEslint from 'vite-plugin-eslint'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    react(),
    viteEslint({
      failOnError: true
    })
  ]
})

此时会发现它在报类型错误无法找到模块“vite-plugin-eslint”的声明文件。这需要等待作者修复,临时方案是先忽略它:

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
import viteEslint from 'vite-plugin-eslint'

此时同样在App.tsx中添加";",现在就可以在运行时的控制台看到 ESLint 报错了。

截屏2024-04-07 22.07.08.png 如果想要在发现错误时自动修复,可以添加以下配置:

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
import viteEslint from 'vite-plugin-eslint'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    react(),
    viteEslint({
      fix: true,
      failOnError: true,
      include: ['src/*.ts', 'src/*.tsx', 'src/**/*.ts', 'src/**/*.tsx']
    })
  ]
})

这样在出错时,当command+s保存时就会自动修复了

5.添加 stylelint 检查 css 代码 首先安装依赖:pnpm i -D stylelint stylelint-config-standard

接着通过pnpm create stylelint初始化,它会在根目录下生成.stylelintrc.json配置文件 截屏2024-04-08 10.07.59.png 其配置如下:

{ 
    "extends": [
        "stylelint-config-standard"
     ] 
}

此时运行npx stylelint "**/*.css"结果如下:

截屏2024-04-08 10.11.14.png 将自动修改加上后重新运行:npx stylelint "**/*.css" --fix 截屏2024-04-08 10.12.31.png 它也需要在运行时自动检测并修复,所以也需要集成到vite的配置文件中,先来安装所需要的依赖 pnpm i -D stylelint stylelint-config-standard vite-plugin-stylelint

接着在Vite配置文件中添加vite-plugin-stylelint插件:

// 集成stylelint运行时检测修复
import stylelint from 'vite-plugin-stylelint'
import stylelintConfig from './.stylelintrc.json'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    // ...
    stylelint({
      // 配置stylelint选项
      config: stylelintConfig,
      // stylelint的文件范围
      include: ['src/**/*.{css,scss,less,tsx,html}']
    })
  ]
})

此时App.css文件故意改错,然后运行pnpm run dev,结果如下: 截屏2024-04-08 10.22.18.png

body {
  color: invalid-color-name;
}

加上自动修复fix: true,此时会发现报另外一个错误: Unexpected empty source no-empty-source 截屏2024-04-08 10.28.55.png 这是因为index.css中没有任何的css内容,但希望忽略这条规则,可以在配置文件中将该规则关闭

{ 
    "extends": [
        "stylelint-config-standard"
    ],
    "rules": {
        "no-empty-source": null
    }
}

再来运行时就不会报错了

3.提交规范

在提交前需要对代码自动进行检查,

1.通过 Husky 在 Git commit 时进行代码校验,它本质是git的钩子

先安装依赖: pnpm i husky -D

然后初始化: pnpm exec husky init,它会添加"prepare": "husky"脚本命令,并且在根目录下生成.husky目录,其中pre-commit钩子中有pnpm test,意味着在git commit时会自动执行test脚本命令,但此时并没有test脚本命令,我希望自己编写一个,在执行它时会依次进行eslint和stylelint检测,其中eslint检测的命令为"lint:eslint": "eslint . --report-unused-disable-directives --max-warnings 0 --fix",stylelint检测命令为 "lint:stylelint":"",如何把他们集中到test命令?

"scripts":{
    "lint:eslint": "eslint . --report-unused-disable-directives --max-warnings 0 --fix",
    "lint:stylelint": "stylelint \"**/*.{css,scss,less,tsx }\"", 
    "test": "npm-run-all lint:*"
},
"husky": {
    "hooks": {
      "pre-commit": "pnpm test"
    }
  },

可以看到集成了lint:eslint,lint:stylelinttest三个脚本指令,并且添加了husky指令,此时如果故意改错一些格式,然后执行git commit

截屏2024-04-08 10.56.56.png 会发现此时报错sh: npm-run-all: command not found,但是husky - pre-commit script failed (code 1)钩子已经触发了,只需要安装了 npm-run-all 包即可解决pnpm install npm-run-all -D,此时执行git commit结果如下: 截屏2024-04-08 11.13.31.png

  1. 通过 lint-staged 只对暂存区的代码进行检验。

首先安装依赖: pnpm i lint-staged -D

然后在 package.json 添加相关配置:

{
    "scripts": {
    "lint:stylelint": "stylelint \"**/*.{css,scss,less,tsx }\" --fix",
    "lint-staged":"lint-staged"
  },
  "lint-staged": {
    "*.{js,jsx,tsx,ts}": [
      "pnpm run lint:eslint",
    ],
    "*.{css,scss,less}": [
      "pnpm run lint:stylelint",
    ]
  },
}

接着在pre-commit文件中修改命令:pnpm run lint-staged后再来执行:

截屏2024-04-08 11.42.56.png

  1. 使用 commitlint 对提交信息进行校验。 先安装依赖:pnpm i @commitlint/{cli,config-conventional} -D

然后在根目录创建配置文件 commitlint.config.js

export default {
  extends: ['@commitlint/config-conventional']
}

然后把 commitlint 命令添加到 Husky commit-msg钩子。

运行命令:echo "npx --no -- commitlint --edit \$1" > .husky/commit-msg,这样在.husky目录下就会添加commit-msg,内容为npx --no -- commitlint --edit $1

现在提交信息不合法就会被拦截导致提交失败,规范可见 commitlint ,也可以根据需要修改提交信息规范。 截屏2024-04-08 13.14.35.png 可以看到由于不符合提交信息规范,本次commit就被终止了,具体规范如下:

<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>

因此上面的信息要改成git commit -m "chore(commitlint): 添加commitlint用于检测合法提交信息"后再来提交 截屏2024-04-08 13.17.01.png

4.vscode设置

通过.editorconfig实现在不同的开发环境中遵循同一套代码格式标准

# https://editorconfig.org
root = tue

[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

此时可通过编辑器自带的功能检查是否生效:

截屏2024-04-08 13.18.50.png

5.强制使用pnpm

pnpm可以锁文件且可复用依赖,团队开发时强制使用pnpm,为了实现强制效果,原理是在使用包管理工具install的时候会触发preinstall(npm提供的生命周期钩子),只需在此拦截只允许使用pnpm即可

首先在根目录创建scripts/preinstall.js文件,添加下面的内容:

/* eslint-env node */
console.log(process.env.npm_execpath)
if (!/pnpm/.test(process.env.npm_execpath || '')) {
  console.warn(`Oops,同学,当前模版只能使用pnpm包管理工具`)
  process.exit(1)
}

然后在package.json的scripts中添加 "preinstall": "node ./scripts/preinstall.js" 此时若是用npm或其他工具进行安装时就会报错终止,提示必须使用pnpm 截屏2024-04-10 20.44.22.png 截屏2024-04-10 20.46.00.png