SPFx 1.22 — Pre-commit hooks to improve quality

SPFx 1.22 — Pre-commit hooks to improve quality

Why pre-commit hooks

Heft brings consistency to the SPFx 1.22 toolchain. Combine it with pre-commit hooks to keep code clean and catch issues early: format, lint, type-check key files before they get committed.

References:

Tooling overview

  • Husky: Git hooks manager
  • lint-staged: Run linters on staged files only
  • Prettier: Formatting
  • ESLint: Linting (TypeScript 5.x compatible)
  • Optional: Stylelint (via Heft run-script), Commitlint (conventional commits)

Install

# prerequisites: run inside your SPFx repo with git initialized
git init

npm i -D husky lint-staged prettier 
# optional extras
npm i -D @commitlint/cli @commitlint/config-conventional

# initialize Husky (v9+). This creates the .husky/ folder
npx husky init

Add scripts to package.json:

{
  "scripts": {
    "prepare": "husky",
    "lint": "heft test",
    "format": "prettier --write ."
  },
  "lint-staged": {
    "*.{ts,tsx,js,jsx}": ["eslint --max-warnings=0 --fix"],
    "*.{css,scss}": ["stylelint --fix"],
    "*.{md,mdx,json}": ["prettier --write"]
  }
}

Husky hooks

Create hooks to run on staged files and block bad commits.

# pre-commit hook (Husky v9+)
echo 'npx --no-install lint-staged' > .husky/pre-commit
chmod +x .husky/pre-commit

# optional: commit-msg hook for conventional commits
echo 'npx --no-install commitlint --edit "$1"' > .husky/commit-msg
chmod +x .husky/commit-msg

Tie into Heft

Heft already runs lint in its rig. For stronger guarantees:

  • Keep pre-commit fast by focusing on staged files.
  • Run full heft build or heft test in CI for comprehensive checks.

Optional: add a Stylelint task in Heft using the Run Script plugin.

{
  "$schema": "https://developer.microsoft.com/json-schemas/heft/v0/heft.schema.json",
  "extends": "@microsoft/spfx-web-build-rig/profiles/default/config/heft.json",
  "phasesByName": {
    "build": {
      "tasksByName": {
        "stylelint": {
          "taskPlugin": {
            "pluginPackage": "@rushstack/heft",
            "pluginName": "run-script-plugin",
            "options": { "scriptPath": "./config/run-script/stylelint.mjs" }
          }
        }
      }
    }
  }
}
import { execa } from "execa";
export async function runAsync() {
  await execa("npx", ["stylelint", "src/**/*.scss", "--fix"], { stdio: "inherit" });
}

Note: ESLint is provided by the SPFx 1.22 Heft rig (@microsoft/spfx-web-build-rig). You typically don’t need a custom .eslintrc — rely on the rig defaults and use heft test --only lint -- for CI.

Suggested workflow

  • Dev: rely on pre-commit hooks (fast feedback)
  • CI: run heft build, heft test, and packaging
  • Enforce formatting/lint via lint-staged; keep heavy checks for CI

TL;DR

  • Add Husky + lint-staged to SPFx 1.22
  • Format with Prettier, lint with ESLint (and Stylelint if needed)
  • Keep hooks fast; use Heft for full lint/build in CI