npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@sudharsank/spfx-selective-build

v0.1.0

Published

Reusable CLI for profile-based selective SPFx builds, packaging, backup sync, and profile scaffolding.

Readme

spfx-selective-build

spfx-selective-build is a reusable npm/npx CLI for profile-based selective SPFx builds.

It packages a profile-based selective build pattern into an installable tool so teams do not need to keep a one-off script in each repository.

It works against the real files in your SPFx solution. The CLI reads the live config.json, package-solution.json, and tsconfig.json, creates backup companions when they do not exist yet, and then applies profile-specific rewrites around each command.

What it automates

  • lists available build profiles from config/build-profiles.json
  • scopes config/config.json to the selected bundle set
  • scopes tsconfig.json to the selected web part folder(s) plus src/shared/**
  • swaps config/package-solution.json to the selected profile package file
  • runs heft start, heft test, heft build, or heft package-solution
  • restores the baseline config files after the command completes or fails
  • scaffolds new profile entries and starter package-solution.<profile>.json files
  • updates or removes bundles from existing profiles with guard rails
  • synchronizes committed backup files with a single command

Install and run

Use it directly with npx:

cd ./spfx-solution
npx spfx-selective-build list
npx spfx-selective-build build prh
npx spfx-selective-build package gov-suite

If you run from a repo root instead of the SPFx solution folder, add --solution-dir ./spfx-solution.

Or install it as a local dev dependency and wire npm scripts:

npm install --save-dev spfx-selective-build
{
  "scripts": {
    "wp:list": "spfx-selective-build list --solution-dir ./spfx-solution",
    "wp:start": "spfx-selective-build start --solution-dir ./spfx-solution",
    "wp:test": "spfx-selective-build test --solution-dir ./spfx-solution",
    "wp:build": "spfx-selective-build build --solution-dir ./spfx-solution",
    "wp:package": "spfx-selective-build package --solution-dir ./spfx-solution",
    "wp:create-profile": "spfx-selective-build create-profile --solution-dir ./spfx-solution",
    "wp:update-profile": "spfx-selective-build update-profile --solution-dir ./spfx-solution",
    "wp:remove-profile": "spfx-selective-build remove-profile --solution-dir ./spfx-solution",
    "wp:sync-backups": "spfx-selective-build sync-backups --solution-dir ./spfx-solution",
    "wp:reset": "spfx-selective-build reset --solution-dir ./spfx-solution"
  }
}

Then run:

npm run wp:list
npm run wp:test -- prh
npm run wp:build -- prh
npm run wp:package -- gov-suite
npm run wp:create-profile -- --key my-webpart --name "My Web Part" --bundle my-web-part
npm run wp:update-profile -- --key gov-suite --bundle external-sharing-command-center-web-part
npm run wp:remove-profile -- --key gov-suite --bundle external-sharing-command-center-web-part
npm run wp:sync-backups
npm run wp:reset

wp:start, wp:test, wp:build, and wp:package are the selective commands. Your existing default npm run build script still behaves exactly as your project defines it unless you intentionally replace it. In a stock SPFx project, npm run build continues to run the full-solution Heft flow.

When you pass arguments through npm run, always use -- before the command arguments. For example:

npm run wp:create-profile -- --key my-webpart --name "My Web Part" --bundle my-web-part

To wire those scripts automatically into the current project package, run:

npx spfx-selective-build wire

If you run that from a repo root that contains ./spfx-solution, the generated scripts automatically include --solution-dir ./spfx-solution. If you run it inside the SPFx solution folder itself, the generated scripts use the local project directly.

If you are testing from a local filesystem path instead of an installed npm package, run wire through that local path too. The generated scripts will use that same local CLI entry:

node /absolute/path/to/spfx-selective-build/bin/spfx-selective-build.js wire \
  --wire-command "node /absolute/path/to/spfx-selective-build/bin/spfx-selective-build.js"

Avoid using npx /absolute/path/to/spfx-selective-build wire for long-lived script wiring. npx may execute from a temporary cache path, and that cache path is not stable for future npm run wp:* commands.

First-time setup in a stock SPFx project

If your SPFx project only has the default generator output, start by creating the first profile. The CLI will:

  • use the existing live SPFx files in the project
  • create config.backup.json, package-solution.backup.json, and tsconfig.backup.json if they are missing
  • create config/build-profiles.json if it does not exist yet
  • scaffold package-solution.<profile>.json from the current package-solution.json

Example:

npx spfx-selective-build create-profile \
  --key hello-world \
  --name "Hello World" \
  --bundle hello-world-web-part

--name is the human-readable profile label. It is what shows up in wp:list, and it is also used as the basis for the generated starter package metadata. --key is the stable machine-friendly profile identifier.

Command reference

list

Lists the profiles in config/build-profiles.json.

start <profile>

Applies a profile, runs heft start --clean, and restores the baseline files afterward.

test <profile>

Applies a profile, runs heft test --clean, and restores the baseline files afterward.

Use this when you want selective test execution for the chosen profile without changing the meaning of the project's default build script.

build <profile>

Applies a profile, runs heft build --clean --production, and restores the baseline files afterward.

package <profile>

Applies a profile, runs heft build --clean --production and heft package-solution --production, and restores the baseline files afterward.

create-profile

Creates or updates a profile entry plus a starter package-solution.<profile>.json file. If build-profiles.json does not exist yet, the command bootstraps it from the current SPFx project.

Example:

npx spfx-selective-build create-profile \
  --key gov-suite \
  --name "Governance Insights Suite" \
  --bundle global-governance-admin-web-part \
  --bundle permission-risk-heatmap-web-part

Optional flags:

  • --package-file <filename>
  • --loc-key-override <bundle>=<resourceKey>
  • --force

update-profile

Updates an existing profile by appending one or more bundles, or by changing the profile name, package file, or localized resource overrides.

Examples:

npx spfx-selective-build update-profile \
  --key gov-suite \
  --bundle external-sharing-command-center-web-part
npx spfx-selective-build update-profile \
  --key gov-suite \
  --name "Governance Insights Suite" \
  --package-file package-solution.governance-suite.json

Use this when a profile already exists and you need to add another web part to that profile without overwriting the existing bundle list.

If you recently added a new web part to the SPFx solution and update-profile says the bundle is unknown even though it exists in config.json, run:

npm run wp:sync-backups

That updates config.backup.json, which is the baseline used for validation and restore.

remove-profile

Removes one or more bundles from an existing profile.

Examples:

npx spfx-selective-build remove-profile \
  --key gov-suite \
  --bundle external-sharing-command-center-web-part
npx spfx-selective-build remove-profile \
  --key gov-suite \
  --bundle external-sharing-command-center-web-part \
  --bundle policy-drift-dashboard-web-part

Validation rules:

  • supports removing multiple bundles in one command
  • warns if a requested bundle is not currently part of the profile
  • prevents removing the last remaining bundle from a profile

wire

Updates the nearest project package.json with the full wp:* script set based on the current layout.

Generated scripts:

  • wp:list
  • wp:start
  • wp:test
  • wp:build
  • wp:package
  • wp:create-profile
  • wp:update-profile
  • wp:remove-profile
  • wp:sync-backups
  • wp:reset

Example:

npx spfx-selective-build wire

For local source testing without installing the package into the project:

node /absolute/path/to/spfx-selective-build/bin/spfx-selective-build.js \
  --wire-command "node /absolute/path/to/spfx-selective-build/bin/spfx-selective-build.js" \
  wire

After that, you can use:

npm run wp:list
npm run wp:create-profile -- --key hello-world --name "Hello World" --bundle hello-world-web-part
npm run wp:update-profile -- --key hello-world --bundle another-web-part
npm run wp:remove-profile -- --key hello-world --bundle another-web-part
npm run wp:test -- hello-world
npm run wp:build -- hello-world

sync-backups

Refreshes the committed baseline copies:

  • config/config.backup.json
  • config/package-solution.backup.json
  • tsconfig.backup.json

This is useful after intentional structural changes to the full solution.

reset

Restores the baseline files from their backups.

Expected project layout

The tool expects either:

  • to be run inside the SPFx solution directory, or
  • to be run from a repo root that contains ./spfx-solution

Minimum expected files:

spfx-solution/
  tsconfig.json
  tsconfig.backup.json
  config/
    build-profiles.json
    config.json
    config.backup.json
    package-solution.json
    package-solution.backup.json
    package-solution.<profile>.json

Backups are created automatically from the live project files the first time they are needed. build-profiles.json is created automatically when you run create-profile in a stock SPFx project.

Why the tool scopes tsconfig.json

Filtering config.json is not enough in a multi-web-part SPFx solution. TypeScript can still compile unrelated source trees if the root tsconfig.json includes them. The CLI rewrites tsconfig.json during the run so the selected web part compiles together with src/shared/**, but unrelated web parts stay out of scope.

Practical expectation

This CLI is meant to operate on your actual SPFx solution folder, not on bundled template config files. The package uses the project’s current baseline as the source of truth and only creates backup copies to support safe restore behavior.

Troubleshooting

npm run wp:* points to a dead npx cache path

If your generated scripts point to a path under .npm/_npx/..., they were wired from a temporary npx cache location and will eventually break.

Do not wire long-lived project scripts with:

npx /absolute/path/to/spfx-selective-build wire

Use one of these instead:

npx spfx-selective-build wire

or, for local source testing:

node /absolute/path/to/spfx-selective-build/bin/spfx-selective-build.js \
  --wire-command "node /absolute/path/to/spfx-selective-build/bin/spfx-selective-build.js" \
  wire

If the project is already wired to a dead cache path, rerun wire with one of the commands above to rewrite the wp:* scripts.

Host path works locally but not inside Docker or a dev container

If your script points to a path like /Users/<name>/..., that path exists on the host machine, not inside the container.

In a containerized SPFx project, install the package inside the container filesystem or use a tarball mounted into the container, then re-run:

npx spfx-selective-build wire

After rewiring, package.json should reference either spfx-selective-build or a path that exists inside the container.

npm install ./spfx-selective-build-0.1.0.tgz hangs or tries to hit the registry

If npm install hangs and logs show requests like:

UNABLE_TO_GET_ISSUER_CERT_LOCALLY

then the environment has a TLS trust problem, often caused by a corporate proxy or custom certificate authority.

If you can fix trust for Node, configure the container or shell with your CA bundle, for example with NODE_EXTRA_CA_CERTS, and retry the install.

If you only need to test the package and want to avoid registry access, unpack the tarball manually:

mkdir -p node_modules/spfx-selective-build node_modules/.bin
tar -xzf spfx-selective-build-0.1.0.tgz \
  -C node_modules/spfx-selective-build \
  --strip-components=1 package
ln -sf ../spfx-selective-build/bin/spfx-selective-build.js node_modules/.bin/spfx-selective-build
chmod +x node_modules/spfx-selective-build/bin/spfx-selective-build.js

Then wire and test normally:

npx spfx-selective-build wire
npm run wp:list

wp:build fails with Sass embedded compiler errors on Linux ARM

If Heft fails with an error like this:

Embedded Dart Sass couldn't find the embedded compiler executable.
Please make sure the optional dependency sass-embedded-linux-arm64 is installed in node_modules.

then the selective build command is working, but the underlying SPFx toolchain is missing an optional platform-specific Sass package.

This is a project dependency issue, not a profile-selection issue. Fix the SPFx project dependencies first, then rerun the profile command.

Typical options:

  • run a normal npm install after TLS and registry access are working
  • explicitly install the platform-specific optional dependency required by the environment
  • verify the container or build agent architecture matches the installed optional package

The CLI now restores config.json, package-solution.json, and tsconfig.json even when Heft fails, so a failing Sass plugin should not leave the solution in a filtered state.

npm run wp:list works but wp:build fails because build-profiles.json is missing

That is expected on a stock SPFx project before the first profile exists.

Create the first profile from the live project files:

npm run wp:create-profile -- --key hello-world --name "Hello World" --bundle hello-world-web-part

That command also creates:

  • config/build-profiles.json
  • config/config.backup.json
  • config/package-solution.backup.json
  • tsconfig.backup.json
  • config/package-solution.<profile>.json