Files
agent-skills/skills/tsdown/references/option-shims.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.5 KiB

Shims

Add compatibility between ESM and CommonJS module systems.

Overview

Shims provide small pieces of code that bridge the gap between CommonJS (CJS) and ECMAScript Modules (ESM), enabling cross-module-system compatibility.

What Shims Provide

ESM Output (when enabled)

With shims: true, adds CommonJS variables to ESM:

  • __dirname - Current directory path
  • __filename - Current file path

ESM Output (automatic)

Always added when using require in ESM on Node.js:

  • require function via createRequire(import.meta.url)

CJS Output (automatic)

Always added to CommonJS output:

  • import.meta.url
  • import.meta.dirname
  • import.meta.filename

Usage

CLI

tsdown --shims

Config File

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

Generated Code

ESM with Shims

Source:

console.log(__dirname)
console.log(__filename)

Output (shims: true):

import { fileURLToPath } from 'node:url'
import { dirname } from 'node:path'

const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)

console.log(__dirname)
console.log(__filename)

ESM with require

Source:

const mod = require('some-module')

Output (automatic on Node.js):

import { createRequire } from 'node:module'
const require = createRequire(import.meta.url)

const mod = require('some-module')

CJS with import.meta

Source:

console.log(import.meta.url)
console.log(import.meta.dirname)

Output (automatic):

const import_meta = {
  url: require('url').pathToFileURL(__filename).toString(),
  dirname: __dirname,
  filename: __filename
}

console.log(import_meta.url)
console.log(import_meta.dirname)

Common Patterns

Node.js CLI Tool

export default defineConfig({
  entry: ['src/cli.ts'],
  format: ['esm'],
  platform: 'node',
  shims: true,  // Add __dirname, __filename
})

Dual Format Library

export default defineConfig({
  entry: ['src/index.ts'],
  format: ['esm', 'cjs'],
  platform: 'node',
  shims: true,  // ESM gets __dirname/__filename
                // CJS gets import.meta.* (automatic)
})

Server-Side Code

export default defineConfig({
  entry: ['src/server.ts'],
  format: ['esm'],
  platform: 'node',
  shims: true,
  external: [/.*/],  // External all deps
})

File System Operations

// Source code
import { readFileSync } from 'fs'
import { join } from 'path'

// Read file relative to current module
const content = readFileSync(join(__dirname, 'data.json'), 'utf-8')
// tsdown config
export default defineConfig({
  entry: ['src/index.ts'],
  format: ['esm'],
  shims: true,  // Enables __dirname
})

When to Use Shims

Use shims: true when:

  • Building Node.js tools/CLIs
  • Code uses __dirname or __filename
  • Need file system operations relative to module
  • Migrating from CommonJS to ESM
  • Need cross-format compatibility

Don't need shims when:

  • Browser-only code
  • No file system operations
  • Using only import.meta.url
  • Pure ESM without CJS variables

Performance Impact

Runtime Overhead

Shims add minimal runtime overhead:

// Added to output when shims enabled
import { fileURLToPath } from 'node:url'
import { dirname } from 'node:path'

const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)

Tree Shaking

If __dirname or __filename are not used, they're automatically removed during bundling (no overhead).

Platform Considerations

Node.js Platform

export default defineConfig({
  platform: 'node',
  format: ['esm'],
  shims: true,  // Recommended for Node.js
})
  • require shim added automatically
  • __dirname and __filename available with shims: true

Browser Platform

export default defineConfig({
  platform: 'browser',
  format: ['esm'],
  shims: false,  // Not needed for browser
})
  • Shims not needed (no Node.js variables)
  • Will cause warnings if Node.js APIs used

Neutral Platform

export default defineConfig({
  platform: 'neutral',
  format: ['esm'],
  shims: false,  // Avoid platform-specific code
})
  • Avoid shims for maximum portability

CLI Examples

# Enable shims
tsdown --shims

# ESM with shims for Node.js
tsdown --format esm --platform node --shims

# Dual format with shims
tsdown --format esm --format cjs --shims

Troubleshooting

__dirname is not defined

Enable shims:

export default defineConfig({
  shims: true,
})

require is not defined in ESM

Automatic on Node.js platform. If not working:

export default defineConfig({
  platform: 'node',  // Ensure Node.js platform
})

Import.meta not working in CJS

Automatic - no configuration needed. If still failing, check output format:

export default defineConfig({
  format: ['cjs'],  // Shims added automatically
})

Tips

  1. Enable for Node.js tools - Use shims: true for CLIs and servers
  2. Skip for browsers - Not needed for browser code
  3. No overhead if unused - Automatically tree-shaken
  4. Automatic require shim - No config needed for require in ESM
  5. CJS shims automatic - import.meta.* always available in CJS