SPFx 1.22 CI/CD — Upgrade pipeline to npm + Heft
Why change the pipeline
SPFx 1.22 uses the Rushstack Heft build rig. Calling npm scripts (which delegate to Heft) ensures your prebuild hooks (e.g., run-script tasks) execute before bundling or packaging. Direct gulp calls may bypass Heft or run out of sync with your build-phase tasks.
References:
- Heft toolchain overview: https://learn.microsoft.com/en-us/sharepoint/dev/spfx/toolchain/sharepoint-framework-toolchain-rushstack-heft
- Customize Heft rig: https://learn.microsoft.com/en-us/sharepoint/dev/spfx/toolchain/customize-heft-toolchain-heft-included-plugins
- Heft Run Script plugin: https://heft.rushstack.io/pages/plugins/run-script/
Old pipeline (SPFx Toolkit default)
This is the typical pipeline the toolkit generates:
name: Deploy Solution react-copilot-retrieval-api
...
- name: Run npm ci
run: npm ci
- name: Bundle & Package
run: |
gulp bundle --ship
gulp package-solution --ship
- name: CLI for Microsoft 365 Login
...
Upgraded GitHub Actions workflow
Switch the bundling/packaging step to npm scripts so Heft prebuild hooks run. The rest of the workflow stays the same.
name: Deploy Solution react-copilot-retrieval-api
on:
push:
branches:
- main
workflow_dispatch:
jobs:
build-and-deploy:
runs-on: ubuntu-latest
env:
NodeVersion: 22.x
steps:
- name: Checkout
uses: actions/checkout@v3.5.3
- name: Use Node.js
uses: actions/setup-node@v3.7.0
with:
node-version: ${{ env.NodeVersion }}
- name: Install dependencies
run: npm ci
- name: Bundle (Heft) & Package (SPFx)
run: |
# Use npm scripts so npm hooks and Heft customizations run
npm run build -- --production
npm run package-solution -- --production
- name: CLI for Microsoft 365 Login
uses: pnp/action-cli-login@v2.2.4
with:
CERTIFICATE_ENCODED: ${{ secrets.CERTIFICATE_ENCODED }}
CERTIFICATE_PASSWORD: ${{ secrets.CERTIFICATE_PASSWORD }}
APP_ID: ${{ secrets.APP_ID }}
TENANT: ${{ secrets.TENANT_ID }}
- name: CLI for Microsoft 365 Deploy App
uses: pnp/action-cli-deploy@v4.0.0
with:
APP_FILE_PATH: sharepoint/solution/react-copilot-retrieval-api.sppkg
SKIP_FEATURE_DEPLOYMENT: false
OVERWRITE: true
This change replaces direct gulp calls with npm scripts that delegate to Heft. As a result, npm lifecycle hooks run reliably and any Heft pipeline modifications (e.g., run-script plugins or custom phases) are honored. It’s a clean and consistent way to ensure your prebuild logic executes before packaging.
npm lifecycle hooks (examples)
npm supports automatic lifecycle hooks that run before/after a named script. This is handy for ensuring setup/validation steps happen without duplicating commands in workflows.
{
"scripts": {
"build": "heft build",
"prebuild": "node ./scripts/set-build-env.mjs",
"postbuild": "node ./scripts/verify-artifacts.mjs",
}
}
prebuild/postbuild: Run automatically when you callnpm run build.- Benefit: Centralize orchestration in package.json so CI and local builds behave the same.
Run locally or in CI exactly the same way:
npm run build -- --production
npm run package-solution -- --production