Output Directory

Configure where Packem writes your built files and assets

Output Directory

The output directory determines where Packem writes your built files, assets, and generated code. Proper configuration ensures your build artifacts are organized and accessible.

Basic Configuration

Default Directory

By default, Packem outputs to the dist directory:

export default defineConfig({
  // Uses 'dist' by default
})

Custom Directory

export default defineConfig({
  rollup: {
    output: {
      dir: 'build' // Custom output directory
    }
  }
})

Multiple Directories

export default defineConfig({
  rollup: {
    output: [
      { format: 'esm', dir: 'dist/esm' },
      { format: 'cjs', dir: 'dist/cjs' },
      { format: 'iife', dir: 'dist/browser' }
    ]
  }
})

Directory Structure

Flat Structure

export default defineConfig({
  rollup: {
    output: {
      dir: 'dist',
      // All files in root
      entryFileNames: '[name].js',
      chunkFileNames: '[name].js',
      assetFileNames: '[name].[ext]'
    }
  }
})

Organized Structure

export default defineConfig({
  rollup: {
    output: {
      dir: 'dist',
      // Organized by type
      entryFileNames: 'js/[name].js',
      chunkFileNames: 'chunks/[name]-[hash].js',
      assetFileNames: 'assets/[name]-[hash].[ext]'
    }
  }
})

Format-Based Structure

export default defineConfig({
  rollup: {
    output: [
      {
        format: 'esm',
        dir: 'dist/esm',
        entryFileNames: '[name].mjs'
      },
      {
        format: 'cjs',
        dir: 'dist/cjs',
        entryFileNames: '[name].cjs'
      }
    ]
  }
})

File Naming Patterns

Entry Files

export default defineConfig({
  rollup: {
    output: {
      dir: 'dist',
      entryFileNames: (chunkInfo) => {
        // Custom naming logic
        if (chunkInfo.name === 'index') {
          return 'main.js'
        }
        return '[name]-[hash].js'
      }
    }
  }
})

Chunk Files

export default defineConfig({
  rollup: {
    output: {
      dir: 'dist',
      chunkFileNames: 'chunks/[name]-[hash].js'
    }
  }
})

Asset Files

export default defineConfig({
  rollup: {
    output: {
      dir: 'dist',
      assetFileNames: (assetInfo) => {
        const extType = assetInfo.name.split('.').pop()
        
        if (/png|jpe?g|svg|gif|tiff|bmp|ico/i.test(extType)) {
          return 'images/[name]-[hash].[ext]'
        }
        
        if (/css|scss|sass|less|styl/i.test(extType)) {
          return 'styles/[name]-[hash].[ext]'
        }
        
        return 'assets/[name]-[hash].[ext]'
      }
    }
  }
})

Package.json Integration

Automatic Directory Detection

{
  "main": "./lib/index.js",
  "module": "./esm/index.js",
  "exports": {
    ".": {
      "import": "./esm/index.js",
      "require": "./lib/index.js"
    }
  }
}
export default defineConfig({
  // Automatically uses 'lib' and 'esm' directories
  rollup: {
    output: [
      { format: 'cjs', dir: 'lib' },
      { format: 'esm', dir: 'esm' }
    ]
  }
})

Custom Export Paths

{
  "exports": {
    ".": {
      "import": "./dist/modern/index.mjs",
      "require": "./dist/legacy/index.cjs"
    }
  }
}
export default defineConfig({
  rollup: {
    output: [
      { format: 'esm', dir: 'dist/modern' },
      { format: 'cjs', dir: 'dist/legacy' }
    ]
  }
})

Directory Cleaning

Automatic Cleaning

export default defineConfig({
  clean: true, // Clean output directory before build
  
  rollup: {
    output: {
      dir: 'dist'
    }
  }
})

Selective Cleaning

export default defineConfig({
  clean: ['dist/**/*.js', 'dist/**/*.css'], // Clean specific patterns
  
  rollup: {
    output: {
      dir: 'dist'
    }
  }
})

Custom Cleaning

export default defineConfig({
  hooks: {
    'build:before': async () => {
      const { rimraf } = await import('rimraf')
      await rimraf('dist')
    }
  },
  
  rollup: {
    output: {
      dir: 'dist'
    }
  }
})

Asset Handling

Static Assets

export default defineConfig({
  rollup: {
    output: {
      dir: 'dist',
      assetFileNames: 'assets/[name]-[hash].[ext]'
    },
    
    plugins: [
      // Copy static assets
      copy({
        targets: [
          { src: 'public/*', dest: 'dist' }
        ]
      })
    ]
  }
})

CSS Assets

export default defineConfig({
  rollup: {
    output: {
      dir: 'dist',
      assetFileNames: (assetInfo) => {
        if (assetInfo.name?.endsWith('.css')) {
          return 'styles/[name]-[hash].[ext]'
        }
        return 'assets/[name]-[hash].[ext]'
      }
    }
  }
})

Image Assets

export default defineConfig({
  rollup: {
    output: {
      dir: 'dist',
      assetFileNames: (assetInfo) => {
        const imageExts = ['png', 'jpg', 'jpeg', 'gif', 'svg', 'webp']
        const ext = assetInfo.name?.split('.').pop()?.toLowerCase()
        
        if (imageExts.includes(ext)) {
          return 'images/[name]-[hash].[ext]'
        }
        
        return 'assets/[name]-[hash].[ext]'
      }
    }
  }
})

Monorepo Configuration

Package-Specific Directories

// packages/ui/packem.config.ts
export default defineConfig({
  rollup: {
    output: {
      dir: 'dist',
      entryFileNames: '[name].js'
    }
  }
})

// packages/utils/packem.config.ts
export default defineConfig({
  rollup: {
    output: {
      dir: 'lib', // Different directory per package
      entryFileNames: '[name].js'
    }
  }
})

Shared Output Directory

export default defineConfig({
  rollup: {
    output: {
      dir: '../../dist/packages/my-package',
      entryFileNames: '[name].js'
    }
  }
})

Development vs Production

Environment-Specific Directories

export default defineConfig({
  rollup: {
    output: {
      dir: process.env.NODE_ENV === 'production' ? 'dist' : 'dev',
      entryFileNames: '[name].js'
    }
  }
})

Development Server

export default defineConfig({
  rollup: {
    output: {
      dir: 'dev',
      sourcemap: true,
      entryFileNames: '[name].js'
    }
  },
  
  server: {
    static: 'dev' // Serve from output directory
  }
})

Advanced Patterns

Dynamic Directory Names

export default defineConfig({
  rollup: {
    output: {
      dir: `dist/${process.env.BUILD_TARGET || 'default'}`,
      entryFileNames: '[name].js'
    }
  }
})

Conditional Outputs

export default defineConfig({
  rollup: {
    output: process.env.DUAL_PACKAGE ? [
      { format: 'esm', dir: 'dist/esm' },
      { format: 'cjs', dir: 'dist/cjs' }
    ] : {
      format: 'esm',
      dir: 'dist'
    }
  }
})

Platform-Specific Directories

export default defineConfig({
  rollup: {
    output: [
      {
        format: 'esm',
        dir: 'dist/node',
        platform: 'node'
      },
      {
        format: 'esm',
        dir: 'dist/browser',
        platform: 'browser'
      }
    ]
  }
})

Directory Permissions

Setting Permissions

export default defineConfig({
  hooks: {
    'build:after': async () => {
      const { chmod } = await import('fs/promises')
      await chmod('dist', 0o755)
    }
  },
  
  rollup: {
    output: {
      dir: 'dist'
    }
  }
})

Ownership

export default defineConfig({
  hooks: {
    'build:after': async () => {
      const { chown } = await import('fs/promises')
      const { getuid, getgid } = await import('process')
      await chown('dist', getuid(), getgid())
    }
  }
})

Troubleshooting

Directory Not Found

Ensure the output directory exists or can be created.

export default defineConfig({
  hooks: {
    'build:before': async () => {
      const { mkdir } = await import('fs/promises')
      await mkdir('dist', { recursive: true })
    }
  }
})

Permission Errors

export default defineConfig({
  hooks: {
    'build:before': async () => {
      const { access, constants } = await import('fs/promises')
      
      try {
        await access('dist', constants.W_OK)
      } catch {
        throw new Error('Output directory is not writable')
      }
    }
  }
})

Path Conflicts

export default defineConfig({
  rollup: {
    output: {
      dir: 'dist',
      // Avoid conflicts with reserved names
      entryFileNames: (chunkInfo) => {
        const reserved = ['index', 'main', 'lib']
        if (reserved.includes(chunkInfo.name)) {
          return `${chunkInfo.name}-bundle.js`
        }
        return '[name].js'
      }
    }
  }
})

Performance Considerations

SSD Optimization

export default defineConfig({
  rollup: {
    output: {
      dir: 'dist',
      // Optimize for SSD performance
      compact: true,
      generatedCode: {
        preset: 'es2015'
      }
    }
  }
})

Network Drives

export default defineConfig({
  rollup: {
    output: {
      dir: process.env.CI ? '/tmp/dist' : 'dist', // Use local storage in CI
      entryFileNames: '[name].js'
    }
  }
})

Large Files

export default defineConfig({
  rollup: {
    output: {
      dir: 'dist',
      // Split large chunks
      maxParallelFileOps: 5,
      chunkFileNames: 'chunks/[name]-[hash].js'
    }
  }
})

  • Output Format - Configure output formats
  • Entry - Configure entry points
  • Assets - Handle static assets
  • Clean - Clean output directories
Support

Contribute to our work and keep us going

Community is the heart of open source. The success of our packages wouldn't be possible without the incredible contributions of users, testers, and developers who collaborate with us every day.Want to get involved? Here are some tips on how you can make a meaningful impact on our open source projects.

Ready to help us out?

Be sure to check out the package's contribution guidelines first. They'll walk you through the process on how to properly submit an issue or pull request to our repositories.

Submit a pull request

Found something to improve? Fork the repo, make your changes, and open a PR. We review every contribution and provide feedback to help you get merged.

Good first issues

Simple issues suited for people new to open source development, and often a good place to start working on a package.
View good first issues