Skip to content

前端项目工程化配置

本文部分内容参考链接出处:

作者:cloudM 链接:https://juejin.cn/post/7373505141489762315 来源:稀土掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

作者:mzong 链接:https://juejin.cn/post/7363460840567701567 来源:稀土掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

结合当前前端生态,我们采用 ESLint + Prettier + Commitlint + Husky 结合的方法,确保本地和仓库代码的规范化。

集成Eslint

ESLint 可帮助你查找和修复 JavaScript 代码中的问题。 无论你是在浏览器中还是在服务器上编写 JavaScript,无论是否使用框架,ESLint 都可以帮助你的代码发挥最大的作用。

  • 发现问题 ESLint 静态地分析你的代码以快速发现问题。 ESLint 内置于大多数文本编辑器中,你也可以在持续集成管道中运行 ESLint。

  • 自动修复问题 ESLint 发现的许多问题都可以自动修复。 ESLint 修复是语法感知的,因此你不会遇到传统查找和替换算法引入的错误。

  • 配置一切 预处理代码,使用自定义解析器,并编写与 ESLint 的内置规则一起工作的你自己的规则。 自定义 ESLint 以完全按照项目所需的方式工作。

安装

bash
npm init @eslint/config@latest

添加Eslint配置文件

9.0.0以上的版本使用的是eslint.config.mjs

配置规则的严重性有以下三种:

"off" 或 0 - 关闭规则 "warn" 或 1 - 打开规则作为警告(不影响退出代码) "error" 或 2 - 打开规则作为错误(触发时退出代码为 1)

规则通常设置为 "error",以在持 Sequelize 成测试、预提交检查和拉取请求合并期间强制遵守规则,因为这样做会导致 ESLint 以非零退出代码退出。 以下是一则配置示例:

如官方自动生成的模板中继承的 recommended ,他是官方提供的规则集,我们也可以其他自定义规则集。 如果有部分不想采用以上 recommended 规则,我们只需要在下方 rules 中覆盖即可。如:

js
rules: {
    'no-extra-semi': ['off'],
}

配置规则参考

eslint.config.mjs

js
import globals from "globals";
import pluginJs from "@eslint/js";
import tseslint from "typescript-eslint";
import pluginVue from "eslint-plugin-vue";


export default [
  { files: ["**/*.{js,mjs,cjs,ts,vue}"] },
  { languageOptions: { globals: globals.browser } },
  pluginJs.configs.recommended,
  ...tseslint.configs.recommended,
  ...pluginVue.configs["flat/essential"],
  { files: ["**/*.vue"], languageOptions: { parserOptions: { parser: tseslint.parser } } },
  {
    rules: {
      // 不允许使用console.log 2代表 error 报错
      'no-console': 2
    }
  }
];

eslintignore

node_modules
src/assets
build
public
dist

启动Eslint

文档参考

配置启动方式 package.json

json
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "eslint ."
  },

添加测试代码

vue
<template>
  <div class="hello">
    <h1>{{ name }}</h1>
    <button @click="changeName">改变</button>
  </div>
</template>

<script lang="ts" setup>
import { ref } from "vue";

let name = ref("张三");

function changeName() {
  console.log("a");
  name.value = "李四";
}

console.log("a");
</script>

运行

bash
npm run lint

运行后可以发现eslint已经帮我们找到错误,但是每次都需要手动运行npm run lint十分的繁琐

配置VsCode插件

以上过程将 ESLint 配置集成到项目中,可使用 eslint 命令对代码进行检测,但是对于我们开发过程中不能及时提示。因此我们需要下载 vscode ESLint 插件,实时提示代码存在的规范问题。安装eslint vscode插件之后在编写代码阶段就可以看到具体的eslint错误

配置成功以后即使我们不使用eslint命令进行校验,vscode也能为我们提示报错

集成Prettier

Prettier 是一个代码格式化工具。可支持以下类型文件:

JavaScript (including experimental features)JSXAngularVueFlowTypeScriptCSS, Less, and SCSSHTMLEmber/HandlebarsJSONGraphQLMarkdown, including GFM and MDX v1YAML

它通过解析代码再根据配置规则,重新生成代码,可以修复一些低级的规范报错

安装

bash
yarn add prettier

配置

新建 .prettierrc 文件,semi代表每一行代码以 ; 号结尾

.prettierrc.js

module.exports = {
    printWidth: 80,
    tabWidth: 2,
    useTabs: false,
    semi: true,
    singleQuote: true,
    quoteProps: 'as-needed',
    trailingComma: 'all',
    bracketSpacing: true,
    jsxBracketSameLine: false,
    arrowParens: 'always',
    rangeStart: 0,
    rangeEnd: Infinity,
    requirePragma: false,
    insertPragma: false,
    proseWrap: 'preserve',
    htmlWhitespaceSensitivity: 'css',
    endOfLine: 'auto',
}

忽略文件配置: 选择是否新建 .prettierignore 文件,如果不创建则使用 .gitignore 规则。

接下来配置 vscode 自动保存调用代码,editor.formatOnSave 设置为 true

在项目根目录下建立settings.json文件 settings.json

json
{
  "editor.tabSize": 2,
  "editor.formatOnSave": true, // 保存时自动格式化
  "editor.wordWrap": "on",
  "vetur.format.defaultFormatter.html": "js-beautify-html", // 因为prettier不能格式化vue文件template  因此使用js-beautify-html格式化
  "vetur.format.defaultFormatterOptions": {
    "js-beautify-html": {
      "wrap_attributes": "auto"
    }
  },
  /* eslint的配置 */
  "eslint.enable": true,
  "eslint.run": "onSave",
  "eslint.options": {
    "extensions": [
      ".js",
      ".vue"
    ]
  },
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": "explicit"
  },
  // 关闭 vscode 默认的检查工具
  "html.validate.scripts": false,
  "javascript.validate.enable": false,
  "eslint.alwaysShowStatus": true,
  "eslint.format.enable": true,
  "scss.lint.duplicateProperties": "error",
  "css.lint.duplicateProperties": "error",
  "less.lint.zeroUnits": "error",
  "eslint.validate": [ // 验证文件类型
    "javascript",
    "javascriptreact",
    "vue-html",
    "vue",
    "html"
  ]
}

示例代码:

vue
<template>
  <div class="hello">
    <h1>{{ name }}</h1>
    <button @click="changeName">改变</button>
  </div>
</template>

<script lang="ts" setup>
import { ref } from 'vue'

let name = ref('张三')

function changeName() {
  name.value = '李四'
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
h3 {
  margin: 40px 0 0;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>

ctrl + S 后会调用 prettierrc 自动进行代码格式化

html
<template>
  <div class="hello">
    <h1>{{ name }}</h1>
    <button @click="changeName">改变</button>
  </div>
</template>

<script lang="ts" setup>
import { ref } from 'vue';

let name = ref('张三');

function changeName() {
  name.value = '李四';
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
h3 {
  margin: 40px 0 0;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>

ESLint和Prettier的区别

ESLintPrettier是两个不同的工具,它们各自有不同的侧重点和功能。包括以下区别:

ESLint:主要是一个代码质量检查工具,用于检测JavaScript代码中的错误和潜在问题,例如未使用的变量、未定义的引用、不必要的括号等。它还可以检测代码风格问题,但主要集中在语法和逻辑错误上。ESLint具有高度的可配置性,允许用户根据项目需求定义自己的规则。 Prettier:主要是一个代码格式化工具,用于统一代码风格,确保代码的可读性和一致性。它专注于格式化,如代码缩进、单引号与双引号的使用等。Prettier支持多种语言,包括JavaScript等,并且可以与其他工具集成,以在代码提交前自动格式化代码。

在实际开发中,通常将ESLintPrettier一起使用,以实现代码质量和风格的双重检查。为了防止两者之间的冲突,可能需要调整它们的配置,确保它们在代码格式和规则上保持一致。 如上所述,ESLintPrettier 侧重点不一样,结合使用可实现功能互补。

Husky

1\安装Husky,我这里的husky版本是"husky": "^9.0.11"

bash
npm install --save-dev husky

2、安装后初始化一下

bash
npx husky init

前面两步执行完之后,就会在项目目录自动生成一个.husky文件夹,然后package.json里面也会多一行代码

bash
"scripts": {
    "prepare": "husky"
  }

文件夹里面会默认有一个pre-commit文件。当执行git commit的时候就会自动执行该文件里面脚本。不过本次我们不需要在这里写,后期的自动校验代码就需要。本次只演示git提交格式校验。

校验git消息格式

1、在项目根目录创建一个scripts目录,里面创建一个verify-commit.js文件,内容如下:

js
/* eslint-disable no-undef */
import chalk from 'chalk'

// argv[2]参数就是commit-msg消息的文件路径,里面放的就是commit -m后面的消息内容
const msgPath = process.argv[2]
import * as fs from 'node:fs'
const msg = fs
  .readFileSync(msgPath, 'utf-8')
  .trim()

const commitRE = /^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|release)(\(.+\))?: .{1,50}/

if (!commitRE.test(msg)) {
  console.error(
    `  ${chalk.bgRed.white(' ERROR ')} ${chalk.red(
      '不合法的 commit 消息格式'
    )}\n\n`
    + chalk.red(
      '  请使用正确的提交格式:\n\n'
    )
    + `    ${chalk.green('feat: add \'comments\' option')}\n`
    + `    ${chalk.green('fix: handle events on blur (close #28)')}\n\n`
    + chalk.red('  请查看 git commit 提交规范:https://jdf2e.github.io/jdc_fe_guide/docs/git/commit/。\n')
  )

  process.exit(1)
}

原理就是当我们执行git commit -m "xxx"的时候,husky去执行这个文件,当校验不通过的时候,就结束node进程。那如何让git提交的时候执行这个文件呢?接下来就是用到commit-msg这个生命周期了。

2、在.husky目录创建一个文件,名字叫commit-msg。内容是:

bash
node scripts/verify-commit.js $1

这样就完成了,文件的命名就是git hook的生命周期,git操作会自动触发。

随便写个提交,注意这里会报错,因为verify-commit.js采用的是esm规范,稍微修改下 package.json

随便写一个git提交测试下

bash
git commit -m "dddd"

可以看到git提交校验已经触发

Git提交规范

提交的代码必须通过 eslint 的校验(可通过 husky 自动完成)

格式: type (scope): subject

bash
  - type
    - 用于说明 `commit` 的类别,只允许使用下面10个标识。
      - feat:新功能(feature)
      - fix:修补bug
      - docs:文档(documentation)
      - style: 格式(不影响代码运行的变动)
      - refactor:重构(即不是新增功能,也不是修改bug的代码变动)
      - perf:性能优化
      - test:增加测试
      - chore:构建过程或辅助工具的变动
      - revert:回退
      - build:打包
  - scope(可选)
    - 用于说明 `commit` 影响的范围,比如Button组件、store、首页、路由等等,视项目不同而不同。
  - subject(可选))
    - `commit` 目的的简短描述,不超过50个字符。
      - 以动词开头,使用第一人称现在时,比如change,而不是changed或changes
      - 第一个字母小写
      - 结尾不加句号(.)

正确的提交规范:

bash
 git commit -m "release: 发布v1.0.0版本"

版本记录

最后记录下本次使用的依赖的版本

json
{
  "name": "eslint-demo",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "npx eslint",
    "prepare": "husky"
  },
  "type": "module",
  "dependencies": {
    "babel-eslint": "^10.1.0",
    "chalk": "^5.3.0",
    "D": "^1.0.0",
    "eslint-config-prettier": "^9.1.0",
    "eslint-plugin-prettier": "^5.2.1",
    "prettier": "^3.3.3",
    "vue": "^3.2.13",
    "vue-router": "^4.0.3",
    "vuex": "^4.0.0"
  },
  "devDependencies": {
    "@commitlint/cli": "^19.5.0",
    "@commitlint/config-conventional": "^19.5.0",
    "@eslint/js": "^9.13.0",
    "@vue/cli-plugin-router": "~5.0.0",
    "@vue/cli-plugin-typescript": "~5.0.0",
    "@vue/cli-plugin-vuex": "~5.0.0",
    "@vue/cli-service": "~5.0.0",
    "eslint": "^9.13.0",
    "eslint-plugin-vue": "^9.29.0",
    "globals": "^15.11.0",
    "husky": "^9.0.11",
    "lint-staged": "^15.2.10",
    "sass": "^1.32.7",
    "sass-loader": "^12.0.0",
    "typescript": "~4.5.5",
    "typescript-eslint": "^8.10.0"
  }
}

上次更新于: