Files
stack/v1/packages/mosaic/framework/skills/tsdown/references/option-tree-shaking.md
T

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"]
}