前端程式碼規範與工程化實戰:ESLint + Prettier + Husky 全流程搭建

前端工程

為什麼你的團隊需要程式碼規範工程化

說兩個真實場景。

場景一:同事 A 用 2 空格縮排,同事 B 用 4 空格。每次 Code Review,80% 的 diff 是縮排和換行。評審人精力消耗在格式上,邏輯問題反而被忽略。

場景二:一個實習生提交了一段程式碼,npm run build 通過了,合併到主分支。第二天生產環境報錯:「typo in variable name」。如果有自動化檢查,這個提交根本過不了 pre-commit hook。

程式碼規範不是「條條框框約束人」,而是「用工具自動保證底線,讓人把精力放在真正有價值的決策上」。這篇文章基於我在三個團隊的實踐。


快速預覽:搭建完後的效果

git add .
git commit -m "feat: add user login"

# Husky 自動觸發 pre-commit hook
# → lint-staged 對暫存檔案執行 ESLint --fix + Prettier --write
# → commitlint 校驗 commit message 格式
# → 全部通過後才真正提交

ESLint Flat Config:告別 .eslintrc

2024 年底 ESLint 9.x 將 Flat Config 設為預設,舊的 .eslintrc.* 進入棄用週期。

Flat Config 基礎結構

// eslint.config.mjs
import js from '@eslint/js';
import tseslint from 'typescript-eslint';
import globals from 'globals';

export default tseslint.config(
  js.configs.recommended,
  ...tseslint.configs.recommended,

  {
    languageOptions: {
      globals: {
        ...globals.browser,
        ...globals.node,
      },
      parserOptions: {
        project: './tsconfig.json',
      },
    },
  },

  {
    rules: {
      '@typescript-eslint/no-unused-vars': ['error', {
        argsIgnorePattern: '^_',
        varsIgnorePattern: '^_',
      }],
      '@typescript-eslint/no-explicit-any': 'warn',
      'no-console': ['warn', { allow: ['warn', 'error'] }],
      'prefer-const': 'error',
      'no-var': 'error',
      'eqeqeq': ['error', 'always'],
    },
  },

  {
    ignores: [
      'dist/**',
      'node_modules/**',
      '.next/**',
      'coverage/**',
    ],
  }
);

為什麼遷移到 Flat Config

舊格式 (eslintrc) 新格式 (Flat Config) 說明
.eslintrc.js / .eslintrc.json eslint.config.mjs 統一為單個檔案
extends 鏈式繼承 tseslint.config() 組合 函式組合替代繼承
overrides + 檔案匹配 配置物件中的 files 更直觀的覆蓋規則
外掛用字串名稱 import pluginX from '...' ESM 原生 import

Prettier:格式化交給專業工具

// .prettierrc
{
  "semi": true,
  "singleQuote": true,
  "trailingComma": "all",
  "printWidth": 100,
  "tabWidth": 2,
  "arrowParens": "always",
  "endOfLine": "lf",
  "bracketSpacing": true
}

讓 ESLint 和 Prettier 和平共處:

// eslint.config.mjs
import prettier from 'eslint-config-prettier';

export default tseslint.config(
  // ...前面的配置
  prettier,  // 放最後,確保覆蓋所有衝突規則
);

Husky + lint-staged:在提交前攔住問題

npm i -D husky lint-staged
npx husky init
// package.json
{
  "lint-staged": {
    "*.{ts,tsx,js,jsx}": [
      "eslint --fix --max-warnings=0",
      "prettier --write"
    ],
    "*.{json,css,scss,md}": [
      "prettier --write"
    ]
  }
}
# .husky/pre-commit
npx lint-staged

commitlint:統一提交資訊格式

npm i -D @commitlint/cli @commitlint/config-conventional
// commitlint.config.mjs
export default {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'type-enum': [
      2,
      'always',
      [
        'feat', 'fix', 'docs', 'style',
        'refactor', 'perf', 'test', 'chore',
        'ci', 'revert',
      ],
    ],
    'subject-case': [0],
  },
};

正確的提交格式:

git commit -m "feat: add user authentication module"
git commit -m "fix: resolve token refresh race condition"

CI 流水線整合

# .github/workflows/lint.yml
name: Lint & Format Check

on:
  pull_request:
    branches: [main, develop]

jobs:
  lint:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - name: Install dependencies
        run: npm ci
      - name: Run ESLint
        run: npx eslint . --max-warnings=0
      - name: Check formatting
        run: npx prettier --check "src/**/*.{ts,tsx,js,jsx,json,css}"
      - name: Type check
        run: npx tsc --noEmit

遷移真實專案的經驗

第一步:先格式,後規則

# 1. 先用 Prettier 格式化整個專案
npx prettier --write "src/**/*.{ts,tsx}"

# 2. 提交格式化變更
git add .
git commit -m "style: format all files with Prettier"

# 3. 逐步開啟 ESLint 規則

第二步:漸進式收緊

// 第一期:只開 error 級別
{
  rules: {
    '@typescript-eslint/no-explicit-any': 'warn',
    'no-console': 'off',
    '@typescript-eslint/no-unused-vars': 'error',
  },
}

常見坑與解決

坑 1:ESLint Flat Config 和 VSCode 外掛不相容

{
  "eslint.useFlatConfig": true,
  "eslint.options": {
    "overrideConfigFile": "eslint.config.mjs"
  }
}

坑 2:Windows 和 macOS 換行符打架

.prettierrc 中設 "endOfLine": "lf",再加 .gitattributes

* text=auto eol=lf

相關工具

本站提供瀏覽器本地工具,免註冊即可試用 →

#ESLint#Prettier#代码规范#工程化#前端#教程