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

@wolfcola/eslint-plugin-treeshake

v1.1.1

Published

ESLint plugin that flags code patterns known to break tree-shaking

Downloads

1,311

Readme

@wolfcola/eslint-plugin-treeshake

An ESLint plugin that flags code patterns known to break tree-shaking. Catches problems at authoring time so they don't reach production bundles.

Optionally integrates with @wolfcola/treeshake-check for full Rollup-based bundle analysis mapped back to source locations.

Installation

pnpm add -D @wolfcola/eslint-plugin-treeshake

For bundle-check mode (optional):

pnpm add -D @wolfcola/treeshake-check

Setup

Flat config (ESLint 9+)

// eslint.config.mjs
import treeshake from '@wolfcola/eslint-plugin-treeshake';

export default [
  // Use the recommended preset (all static checks, warn severity)
  treeshake.configs.recommended,

  // Or configure manually:
  {
    plugins: { wolfcola: treeshake },
    rules: {
      'wolfcola/no-treeshake-hazard': [
        'warn',
        {
          checkEnums: true,
          checkUnannotatedCalls: true,
          checkPrototypeMutation: true,
          checkGlobalAssignment: true,
          checkCjsPatterns: true,
          checkSideEffectsField: true,
          additionalPureFunctions: [],
          bundleCheck: false,
        },
      ],
    },
  },
];

Strict preset

Enables all static checks at error severity and turns on bundle-check mode:

import treeshake from '@wolfcola/eslint-plugin-treeshake';

export default [treeshake.configs.strict];

Rule: wolfcola/no-treeshake-hazard

A single rule covering all tree-shaking hazard categories.

What it detects

| Hazard | What it flags | Autofix | | ------------------------- | ------------------------------------------------------------- | ----------------------------- | | EnumPattern | TypeScript enum declarations at module scope | Suggestion: as const object | | UnannotatedCall | Top-level function calls without /*#__PURE__*/ | Fix: inserts /*#__PURE__*/ | | PrototypeMutation | Object.defineProperty, .prototype.x = ... at module scope | None | | GlobalAssignment | window.x = ..., globalThis.x = ... at module scope | None | | CjsPatterns | require(), module.exports in ESM files | None | | MissingSideEffectsField | Missing "sideEffects" field in the nearest package.json | None |

Options

| Option | Type | Default | Description | | ------------------------- | ---------- | ------- | ------------------------------------------------ | | checkEnums | boolean | true | Flag TypeScript enums | | checkUnannotatedCalls | boolean | true | Flag top-level calls without /*#__PURE__*/ | | checkPrototypeMutation | boolean | true | Flag prototype/property mutations | | checkGlobalAssignment | boolean | true | Flag global object assignments | | checkCjsPatterns | boolean | true | Flag CommonJS patterns in ESM | | checkSideEffectsField | boolean | true | Warn if nearest package.json lacks sideEffects | | additionalPureFunctions | string[] | [] | Function names to treat as side-effect-free | | bundleCheck | boolean | false | Run full Rollup-based analysis (slow) | | bundleCheckCwd | string | auto | Working directory for bundle check |

Known-pure functions (not flagged)

The following top-level calls are recognized as side-effect-free and not flagged by checkUnannotatedCalls:

Object.freeze, Object.create, Object.keys, Object.values, Object.entries, Object.fromEntries, Symbol, Symbol.for, Array.from, Array.of, Array.isArray, Map, Set, WeakMap, WeakSet, Number.isNaN, Number.isFinite, Number.parseInt, Number.parseFloat, String.fromCharCode, String.fromCodePoint, JSON.parse, JSON.stringify, Math.max, Math.min, Math.floor, Math.ceil, Math.round, Math.abs, Promise.resolve, Promise.reject

Extend with additionalPureFunctions.

Bundle check mode

When bundleCheck: true, the rule runs a full Rollup build via @wolfcola/treeshake-check and maps results back to source locations. This is slow but catches issues that static analysis misses (transitive side effects, bundler-specific behavior).

Bundle-check findings are deduplicated against static findings — if both detect the same hazard category in the same file, only the static finding is reported.

Requires @wolfcola/treeshake-check as a dev dependency.

Relationship to @wolfcola/treeshake-check

| | eslint-plugin-treeshake | treeshake-check | | --------------- | -------------------------------- | ------------------------ | | When | Authoring time | Post-build / CI | | Speed | Fast (per-file AST) | Slow (full Rollup build) | | Accuracy | Heuristic | Ground truth | | Integration | Editor squiggles, eslint --fix | CLI, exit codes |

Use both: the ESLint plugin for fast feedback during development, treeshake-check as a CI quality gate.

Examples

Before (flagged)

// Enum - breaks tree-shaking
export enum Direction {
  Up,
  Down,
  Left,
  Right,
}

// Unannotated call - bundler assumes side effects
const registry = createRegistry();

// Global assignment - observable side effect
window.MY_APP = { version: '1.0' };

After (clean)

// as const object - fully shakeable
export const Direction = {
  Up: 'Up',
  Down: 'Down',
  Left: 'Left',
  Right: 'Right',
} as const;
export type Direction = (typeof Direction)[keyof typeof Direction];

// PURE annotation - bundler can safely drop if unused
const registry = /*#__PURE__*/ createRegistry();

// Moved into an explicit init function
export function initApp() {
  window.MY_APP = { version: '1.0' };
}