Files
agent-skills/skills/tsdown/references/option-tree-shaking.md
Jason Woltje f5792c40be feat: Complete fleet — 94 skills across 10+ domains
Pulled ALL skills from 15 source repositories:
- anthropics/skills: 16 (docs, design, MCP, testing)
- obra/superpowers: 14 (TDD, debugging, agents, planning)
- coreyhaines31/marketingskills: 25 (marketing, CRO, SEO, growth)
- better-auth/skills: 5 (auth patterns)
- vercel-labs/agent-skills: 5 (React, design, Vercel)
- antfu/skills: 16 (Vue, Vite, Vitest, pnpm, Turborepo)
- Plus 13 individual skills from various repos

Mosaic Stack is not limited to coding — the Orchestrator and
subagents serve coding, business, design, marketing, writing,
logistics, analysis, and more.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 16:27:42 -06:00

5.1 KiB

Tree Shaking

Remove unused code from bundles.

Overview

Tree shaking eliminates dead code (unused exports) from your final bundle, reducing size and improving performance.

Default: Enabled

Basic Usage

CLI

# Tree shaking enabled (default)
tsdown

# Disable tree shaking
tsdown --no-treeshake

Config File

export default defineConfig({
  entry: ['src/index.ts'],
  treeshake: true,  // Default
})

How It Works

With Tree Shaking

Source:

// src/util.ts
export function unused() {
  console.log("I'm unused")
}

export function hello(x: number) {
  console.log('Hello World', x)
}

// src/index.ts
import { hello } from './util'
hello(1)

Output:

// dist/index.mjs
function hello(x) {
  console.log('Hello World', x)
}
hello(1)

unused() function is removed because it's never imported.

Without Tree Shaking

Output:

// dist/index.mjs
function unused() {
  console.log("I'm unused")
}

function hello(x) {
  console.log('Hello World', x)
}
hello(1)

All code is included, even if unused.

Advanced Configuration

Enable (Default)

export default defineConfig({
  treeshake: true,
})

Uses Rolldown's default tree shaking.

Custom Options

export default defineConfig({
  treeshake: {
    moduleSideEffects: false,
    propertyReadSideEffects: false,
    unknownGlobalSideEffects: false,
  },
})

See Rolldown docs for all options.

Disable

export default defineConfig({
  treeshake: false,
})

Side Effects

Package.json sideEffects

Declare side effects in your package:

{
  "sideEffects": false
}

Or specify files with side effects:

{
  "sideEffects": ["*.css", "src/polyfills.ts"]
}

Module Side Effects

export default defineConfig({
  treeshake: {
    moduleSideEffects: (id) => {
      // Preserve side effects for polyfills
      return id.includes('polyfill')
    },
  },
})

Common Patterns

Production Build

export default defineConfig({
  entry: ['src/index.ts'],
  format: ['esm', 'cjs'],
  treeshake: true,
  minify: true,
})

Development Build

export default defineConfig((options) => ({
  entry: ['src/index.ts'],
  treeshake: !options.watch,  // Disable in dev
}))

Library with Side Effects

export default defineConfig({
  entry: ['src/index.ts'],
  treeshake: {
    moduleSideEffects: (id) => {
      return (
        id.includes('.css') ||
        id.includes('polyfill') ||
        id.includes('side-effect')
      )
    },
  },
})

Utilities Library

export default defineConfig({
  entry: ['src/index.ts'],
  format: ['esm'],
  treeshake: true,
  dts: true,
})

Users can import only what they need:

import { onlyWhatINeed } from 'my-utils'

Benefits

Smaller Bundles

  • Only includes imported code
  • Removes unused functions, classes, variables
  • Reduces download size

Better Performance

  • Less code to parse
  • Faster execution
  • Improved loading times

Cleaner Output

  • No dead code in production
  • Easier to debug
  • Better maintainability

When to Disable

Debugging

During development to see all code:

export default defineConfig((options) => ({
  treeshake: !options.watch,
}))

Side Effect Code

Code with global side effects:

// This has side effects
window.myGlobal = {}

export function setup() {
  // ...
}

Disable tree shaking or mark side effects:

{
  "sideEffects": true
}

Testing

Include all code for coverage:

export default defineConfig({
  treeshake: false,
})

Tips

  1. Leave enabled for production builds
  2. Mark side effects in package.json
  3. Use with minification for best results
  4. Test tree shaking - verify unused code is removed
  5. Disable for debugging if needed
  6. Pure functions are easier to tree shake

Troubleshooting

Code Still Included

  • Check for side effects
  • Verify imports are ES modules
  • Ensure code is actually unused
  • Check sideEffects in package.json

Missing Code at Runtime

  • Code has side effects but marked as none
  • Set sideEffects: true or list specific files

Unexpected Behavior

  • Module has side effects not declared
  • Try disabling tree shaking to isolate issue

Examples

Pure Utility Functions

// utils.ts - perfect for tree shaking
export function add(a, b) {
  return a + b
}

export function multiply(a, b) {
  return a * b
}

// Only 'add' imported = only 'add' bundled
import { add } from './utils'

With Side Effects

// polyfill.ts - has side effects
if (!Array.prototype.at) {
  Array.prototype.at = function(index) {
    // polyfill implementation
  }
}

export {} // Need to export something
{
  "sideEffects": ["src/polyfill.ts"]
}