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

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