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

vite-magic-tree-shaking

v1.0.0

Published

Auto-generate tree-shakeable lib entries for Vite build.lib.entry

Readme

vite-magic-tree-shaking

npm version npm downloads license CI

Auto-generate tree-shakeable build.lib.entry for Vite from your source directory.

Install

npm install -D vite-magic-tree-shaking

Usage

// vite.config.ts
import { defineConfig } from 'vite'
import { fileURLToPath } from 'node:url'
import { generateEntries } from 'vite-magic-tree-shaking'

const __dirname = fileURLToPath(new URL('.', import.meta.url))

export default defineConfig({
  build: {
    lib: {
      entry: generateEntries(__dirname),       // scans src/ by default
      // entry: generateEntries(__dirname, 'lib'), // custom source dir
      formats: ['es'],
      fileName: (_, entryName) => `${entryName}.js`,
    },
    rollupOptions: {
      external: ['react', 'react-dom'],
      output: {
        preserveModules: true,
        preserveModulesRoot: 'src',
      },
    },
  },
})

Warn when package.json exports are out of sync

Pass warnOnExportsMismatch: true to get a console.warn at build/dev time if the exports field in package.json does not match the entries resolved from your source directory:

entry: generateEntries(__dirname, 'src', { warnOnExportsMismatch: true })
[vite-magic-tree-shaking] package.json exports are out of sync with src entries.
Run: npx vite-magic generate

CLI

The package ships a vite-magic binary with two commands.

generate

Reads your source directory, derives the entry map, and writes the matching exports field into package.json. Run this after adding or removing source files.

# using npx (no install required)
npx vite-magic generate

# custom rootDir and srcDir
npx vite-magic generate /path/to/project lib

Example output:

✓ package.json exports updated:
  .
  ./Button/Button
  ./Users
  ./Users/domain/user
  ./Users/types/UserDTO

validate

Checks that the exports field in package.json matches the entries derived from the source directory. Exits with code 1 if they are out of sync — useful in CI.

npx vite-magic validate

Example output when in sync:

✓ package.json exports are in sync

Example output when out of sync:

✗ package.json exports are out of sync with src entries
  Missing : ./NewFeature
  Extra   : ./OldFeature
  Changed : ./Users

Run: npx vite-magic generate

Add to package.json scripts

{
  "scripts": {
    "sync-exports": "vite-magic generate",
    "validate-exports": "vite-magic validate",
    "prebuild": "vite-magic validate"
  }
}

With prebuild wired up, running npm run build will abort with a clear error if package.json exports are stale, before Vite even starts.

How entries are resolved

Given this structure:

src/
├── index.ts
├── Users/
│   ├── index.ts
│   ├── domain/
│   │   └── user.ts
│   └── types/
│       └── UserDTO.ts
└── Button/
    └── Button.tsx

generateEntries(__dirname) produces:

{
  index:                 '/abs/src/index.ts',
  Users:                 '/abs/src/Users/index.ts',
  'Users/domain/user':   '/abs/src/Users/domain/user.ts',
  'Users/types/UserDTO': '/abs/src/Users/types/UserDTO.ts',
  'Button/Button':       '/abs/src/Button/Button.tsx',
}

And vite-magic generate writes the corresponding exports to package.json:

{
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "import": "./dist/index.js",
      "require": "./dist/index.cjs"
    },
    "./Users": {
      "types": "./dist/Users.d.ts",
      "import": "./dist/Users.js",
      "require": "./dist/Users.cjs"
    },
    "./Users/domain/user": {
      "types": "./dist/Users/domain/user.d.ts",
      "import": "./dist/Users/domain/user.js",
      "require": "./dist/Users/domain/user.cjs"
    },
    "./Users/types/UserDTO": {
      "types": "./dist/Users/types/UserDTO.d.ts",
      "import": "./dist/Users/types/UserDTO.js",
      "require": "./dist/Users/types/UserDTO.cjs"
    },
    "./Button/Button": {
      "types": "./dist/Button/Button.d.ts",
      "import": "./dist/Button/Button.js",
      "require": "./dist/Button/Button.cjs"
    }
  }
}

Rules

| Source | Entry key | |---|---| | src/index.ts | index | | src/Users/index.ts | Users | | src/Button/Button.tsx (no index in dir) | Button/Button | | src/Users/domain/user.ts (subdir of indexed dir) | Users/domain/user |

Directories with an index file use the directory name as key. Their subdirectories are still scanned recursively.

Directories without an index expose each file individually using its relative path (without extension).

Ignored files

The following are never included as entries:

  • *.test.ts / *.spec.ts
  • *.stories.tsx
  • *.d.ts / *.d.mts / *.d.cts
  • Any file with an extension other than .ts, .tsx, .js, .jsx, .mts, .cts

API

generateEntries(rootDir: string, srcDir?: string, options?: GenerateEntriesOptions): Record<string, string>

| Parameter | Type | Default | Description | |---|---|---|---| | rootDir | string | — | Absolute path to the project root | | srcDir | string | 'src' | Source directory name, relative to rootDir | | options | GenerateEntriesOptions | {} | Optional configuration |

GenerateEntriesOptions

| Option | Type | Default | Description | |---|---|---|---| | warnOnExportsMismatch | boolean | false | Emit a console.warn if package.json exports do not match the resolved entries |

License

MIT