Exclude specific packages from build cache reuse in pnpm

Exclude specific packages from build cache reuse in pnpm

Using pnpm 12.14.0 sideEffectsCache.exclude, you can skip cache reuse for specified packages. We compare reinstall behavior and explain configuration and cache retention.
2026.10.23

This page has been translated by machine translation. View original

Hey there! I'm Nishimura Yuji from the Operations Division!

For packages that depend on system shared libraries, there are cases where you don't want to reuse build results even if the package version is the same. Using sideEffectsCache.exclude, added in pnpm 12.14.0, you can exclude only specified packages from build result cache reuse.

Specifying Package Names to Exclude

In pnpm 12.14.0 and later, add the following configuration to pnpm-workspace.yaml in the root of your project. cache-demo-addon is the name of the sample package used in the second half. When actually using this, specify the names of the dependency packages you want to exclude.

pnpm-workspace.yaml
sideEffectsCache:
  exclude:
    - cache-demo-addon

With just this specification, reading and writing of side-effects caches for other packages remains in its default enabled state. Installation after configuration proceeds as normal.

pnpm install

Target packages will neither restore build results from local or remote side-effects caches, nor save to them. This is not a setting that disables caching of the downloaded package itself. Also, build script execution permission is separately required. Rebuilding with an existing node_modules in place is not verified in this article. Below, we compare by deleting node_modules.

Comparing by Reinstalling the Same Dependencies

Verified on Ubuntu 24.04.5 / Linux arm64, Node.js 24.21.0, pnpm 12.14.0. Instead of compiling a native module, we use a postinstall that writes an environment variable's value to a file, to see whether the build was re-executed.

1. Prepare a Package That Leaves Build Results

In an environment where pnpm 12.14.0 and Node.js are available, create a new sample directory.

mkdir pnpm-cache-demo
cd pnpm-cache-demo
mkdir package
cd package

Save the following 2 files inside package.

package/package.json
{"name":"cache-demo-addon","version":"1.0.0","scripts":{"postinstall":"node build.cjs"}}
package/build.cjs
const fs = require('node:fs');
fs.writeFileSync('built.txt', process.env.BUILD_MARKER || 'unset');

Pack the package into a tarball and return to the sample root.

pnpm pack --pack-destination ..
cd ..

2. Reinstall with Cache Enabled

Save the following 2 files in the root. For the build permission, specify the key representing this file: dependency.

package.json
{"name":"cache-demo-app","version":"1.0.0","private":true,"dependencies":{"cache-demo-addon":"file:cache-demo-addon-1.0.0.tgz"}}
pnpm-workspace.yaml
storeDir: .pnpm-store
updateNotifier: false
enableGlobalVirtualStore: false
permissions:
  cache-demo-addon@file:cache-demo-addon-1.0.0.tgz:
    build: true

In this example, we use a store dedicated to the sample and disable the global virtual store to align comparison conditions. The rm -rf node_modules below is the operation to reinstall the dependencies within this new sample.

BUILD_MARKER=first pnpm install
cat node_modules/cache-demo-addon/built.txt
rm -rf node_modules
BUILD_MARKER=second pnpm install --frozen-lockfile
cat node_modules/cache-demo-addon/built.txt

Both resulted in first. Even though the environment variable was changed to second on the second run, the first build result was restored from the cache.

3. Add the Exclusion Setting and Reinstall

Add the sideEffectsCache block from the beginning to the end of the pnpm-workspace.yaml from earlier. Leave the existing build permission in place.

rm -rf node_modules
BUILD_MARKER=third pnpm install --frozen-lockfile
cat node_modules/cache-demo-addon/built.txt
rm -rf node_modules
BUILD_MARKER=fourth pnpm install --frozen-lockfile
cat node_modules/cache-demo-addon/built.txt

This time the results were third and fourth respectively. Using the same tarball, postinstall was executed for each installation.

The following image shows the comparison results recorded in a file and displayed in the terminal. The last line is an additional verification done by removing the exclusion setting and reinstalling once more.

Comparison results showing first being reused normally, and rebuilding with third and fourth when excluded

Old Cache Is Reused When Exclusion Is Removed

Delete the sideEffectsCache block, leave the build permissions and other settings in place, and reinstall once more.

rm -rf node_modules
BUILD_MARKER=fifth pnpm install --frozen-lockfile
cat node_modules/cache-demo-addon/built.txt

The result returned to first. Not third or fourth created during exclusion — the cache from before the exclusion remained.

This setting is for skipping cache reads and writes, not an operation that deletes existing build caches. This distinction needs to be kept in mind when restoring excluded targets.

The official documentation also describes specifying @scope/* in addition to names, as well as specifying an exact matching version. Here we focused solely on the behavior of local tarball dependencies specified by name only. Remote cache, cross-project sharing with global virtual store, actual native modules, and behavior on macOS and Windows are not included in the verification scope.

Summary

By writing a package name in pnpm's sideEffectsCache.exclude, we were able to exclude that dependency from build result cache reuse. This is a setting to use for packages where conditions not included in the cache key — such as shared libraries — affect the build result. Its role differs from deleting existing caches or granting build script execution permission.

Reference Links:

Share this article