Configuration
Complete guide to configuring Packem for your project needs
Configuration
Learn how to configure Packem to meet your specific project requirements with detailed examples and best practices.
Configuration File
Packem uses a packem.config.ts file for configuration. This file should be placed in your project root.
Basic Configuration
import { defineConfig } from '@visulima/packem/config'
import transformer from '@visulima/packem/transformer/esbuild'
export default defineConfig({
transformer,
sourcemap: true,
declaration: true
})Configuration Options
Core Options
transformer
Specify which transformer to use for code compilation:
// esbuild (default, fastest)
import esbuild from '@visulima/packem/transformer/esbuild'
// swc (Rust-powered)
import swc from '@visulima/packem/transformer/swc'
// OXC (experimental)
import oxc from '@visulima/packem/transformer/oxc'
// sucrase (lightweight)
import sucrase from '@visulima/packem/transformer/sucrase'
export default defineConfig({
transformer: esbuild // or swc, oxc, sucrase
})bundler
Choose the bundler backend. Rollup is the default and fully-supported path; the experimental Rolldown backend is opt-in:
export default defineConfig({
bundler: 'rollup', // default
// or
bundler: 'rolldown', // experimental — omit `transformer`, DTS still routes through Rollup
})See the bundler option for the full Rolldown caveats.
sourcemap
Control source map generation:
export default defineConfig({
sourcemap: true, // Generate source maps
sourcemap: false, // No source maps
sourcemap: 'inline', // Inline source maps
sourcemap: 'hidden' // Hidden source maps
})declaration
Generate TypeScript declaration files:
export default defineConfig({
declaration: true, // Generate .d.ts files
declaration: false, // Skip declaration generation
declaration: 'compatible', // Generate compatible declarations
declaration: 'node16' // Generate node16 declarations
})minify
Control code minification:
export default defineConfig({
minify: true, // Enable minification
minify: false, // Disable minification
})banner / footer
Prepend (banner) or append (footer) text to the build output — useful for
license headers, runtime directives, or shims. The values map onto Rollup/Rolldown's
output.banner / output.footer, so both bundler backends honour them and they apply
to both the CommonJS and ESM bundles.
export default defineConfig({
// A bare string (or function) targets the JS output only:
banner: "/*! my-lib v1.0.0 | MIT */",
footer: (chunk) => `/* built ${chunk.fileName} */`,
})Use the object form to target the JavaScript bundle (js) and the generated
declaration files (dts) independently:
export default defineConfig({
banner: {
js: "'use client';",
dts: "// AUTO-GENERATED — do not edit",
},
})A bare banner/footer value never touches the declaration files — opt declarations in
explicitly via the { dts } form. An explicit rollup.dts.banner/footer takes
precedence over the top-level option.
Entry Points
Automatic Detection
Packem automatically detects entry points from your package.json:
{
"exports": {
".": "./src/index.ts",
"./utils": "./src/utils.ts"
}
}Manual Configuration
Override automatic detection:
export default defineConfig({
entries: [
'src/index.ts',
'src/cli.ts',
'src/utils.ts'
]
})Entry Objects
Use objects for more control:
export default defineConfig({
entries: [
{
input: 'src/index.ts',
outDir: 'dist'
},
{
input: 'src/cli.ts',
outDir: 'dist/bin'
}
]
})Rollup Configuration
Packem is built on Rollup, so you can use any Rollup options:
export default defineConfig({
rollup: {
external: ['react', 'react-dom'],
output: {
banner: '/* My Library v1.0.0 */',
footer: '/* End of bundle */'
},
plugins: [
// Additional Rollup plugins
],
watch: {
include: 'src/**',
exclude: 'node_modules/**'
}
}
})CSS Configuration
Quick Setup:
Use the add command to interactively configure CSS loaders:
npx packem add cssThis will:
- Prompt you to select a main CSS loader (PostCSS, Lightning CSS, or Tailwind CSS)
- Ask about additional loaders (Sass, Less, Stylus)
- Optionally configure CSS minification
- Install all necessary dependencies
- Update your
packem.config.tsautomatically
Manual Configuration:
import postcssLoader from '@visulima/packem/css/loader/postcss'
import sassLoader from '@visulima/packem/css/loader/sass'
import lessLoader from '@visulima/packem/css/loader/less'
import stylusLoader from '@visulima/packem/css/loader/stylus'
import sourceMapLoader from '@visulima/packem/css/loader/sourcemap'
import cssnanoMinifier from '@visulima/packem/css/minifier/cssnano'
import lightningcssMinifier from '@visulima/packem/css/minifier/lightningcss'
export default defineConfig({
rollup: {
css: {
mode: 'extract', // or 'inject'
loaders: [postcssLoader, sassLoader, lessLoader, stylusLoader, sourceMapLoader],
minifier: cssnanoMinifier
}
}
})Native Modules Configuration
Configure native Node.js addon (.node files) handling:
import { defineConfig } from '@visulima/packem/config'
import transformer from '@visulima/packem/transformer/esbuild'
export default defineConfig({
transformer,
rollup: {
nativeModules: {
nativesDirectory: 'natives' // Custom directory name
}
}
})The native modules plugin automatically:
- Detects
.nodefile imports - Copies native modules to the output directory
- Generates appropriate
require()statements - Handles name collisions and platform-specific files
Options:
nativesDirectory: Directory name for native modules (default:'natives')
After bundling, the .node file will be copied to dist/natives/ and the import will be automatically rewritten to load from the correct location at runtime.
[!NOTE]
- Native modules are platform and architecture-specific. Make sure to distribute the correct
.nodefiles for your target platforms.- This only works with direct
.nodeimports. If you're using packages that dynamically load native modules viabindingsornode-pre-gyp, you'll need to handle them separately.
Handling dependencies with native modules
If you're using packages with native modules (like chokidar which depends on fsevents):
- If in
dependencies/peerDependencies: ✅ Works automatically - these are externalized (not bundled) - If in
devDependencies: ⚠️ Will be bundled. If they usebindings()ornode-pre-gyppatterns, move them todependenciesinstead, or useoptionalDependenciesif they're optional.
Example - if you have chokidar in devDependencies and get build errors, move it to dependencies:
{
"dependencies": {
"chokidar": "^3.0.0"
}
}This externalizes it (users will need to install it), avoiding the need to bundle its native modules.
Advanced Configurations
Multi-Format Builds
Build multiple output formats by configuring package.json properly:
{
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"require": "./dist/index.cjs"
}
}
}Environment-Specific Config
const isDev = process.env.NODE_ENV === 'development'
export default defineConfig({
sourcemap: isDev,
minify: !isDev,
declaration: !isDev,
rollup: {
watch: isDev ? {
include: 'src/**'
} : undefined
}
})Conditional Configuration
import esbuildTransformer from '@visulima/packem/transformer/esbuild'
import swcTransformer from '@visulima/packem/transformer/swc'
export default defineConfig({
transformer: process.env.TRANSFORMER === 'swc'
? swcTransformer
: esbuildTransformer,
externals: process.env.BUNDLE_DEPS
? []
: ['react', 'react-dom']
})Library-Specific Configurations
React Library
Quick Setup (Recommended):
Use the add command to automatically configure React:
npx packem add reactThis will:
- Add
preset: 'react'to your config - Install React, React DOM, and Babel dependencies
- Automatically detect TypeScript and add
@types/reactand@types/react-domif TypeScript is installed - Prompt you to add TypeScript if not already installed
Manual Configuration:
import { defineConfig } from '@visulima/packem/config'
import transformer from '@visulima/packem/transformer/esbuild'
export default defineConfig({
preset: 'react', // Automatically configures Babel for React
transformer,
sourcemap: true,
declaration: true,
externals: ['react', 'react-dom'],
rollup: {
css: {
mode: 'extract'
}
}
})With React Compiler:
import { defineConfig } from '@visulima/packem/config'
import { createReactPreset } from '@visulima/packem/config/preset/react'
import transformer from '@visulima/packem/transformer/esbuild'
export default defineConfig({
preset: createReactPreset({
compiler: true // Enable React Compiler optimization
}),
transformer,
sourcemap: true,
declaration: true,
externals: ['react', 'react-dom'],
rollup: {
css: {
mode: 'extract'
}
}
})Manual Configuration:
import { defineConfig } from '@visulima/packem/config'
import transformer from '@visulima/packem/transformer/esbuild'
export default defineConfig({
transformer,
sourcemap: true,
declaration: true,
externals: ['react', 'react-dom'],
rollup: {
babel: {
presets: [
['@babel/preset-react', { runtime: 'automatic' }],
['@babel/preset-typescript', { allExtensions: true, isTSX: true }]
]
},
css: {
mode: 'extract'
}
}
})SolidJS Library
Quick Setup (Recommended):
Use the add command to automatically configure SolidJS:
npx packem add solidThis will:
- Add
preset: 'solid'to your config - Install SolidJS and Babel dependencies
Manual Configuration:
import { defineConfig } from '@visulima/packem/config'
import transformer from '@visulima/packem/transformer/esbuild'
export default defineConfig({
preset: 'solid', // Automatically configures Babel for SolidJS
transformer,
sourcemap: true,
declaration: true,
externals: ['solid-js', 'solid-js/web', 'solid-js/store'],
rollup: {
css: {
mode: 'extract'
}
}
})With SSR Support:
import { defineConfig } from '@visulima/packem/config'
import { createSolidPreset } from '@visulima/packem/config/preset/solid'
import transformer from '@visulima/packem/transformer/esbuild'
export default defineConfig({
preset: createSolidPreset({
solidOptions: {
generate: 'ssr',
hydratable: true
}
}),
transformer,
sourcemap: true,
declaration: true,
externals: ['solid-js', 'solid-js/web', 'solid-js/store'],
rollup: {
css: {
mode: 'extract'
}
}
})Manual Configuration:
import { defineConfig } from '@visulima/packem/config'
import transformer from '@visulima/packem/transformer/esbuild'
export default defineConfig({
transformer,
sourcemap: true,
declaration: true,
externals: ['solid-js', 'solid-js/web', 'solid-js/store'],
rollup: {
babel: {
presets: [
['babel-preset-solid', { generate: 'dom' }],
['@babel/preset-typescript', { allExtensions: true, isTSX: true }],
['@babel/preset-env', { bugfixes: true, targets: 'last 2 years' }]
]
},
css: {
mode: 'extract'
}
}
})Node.js Library
export default defineConfig({
transformer,
runtime: 'node',
externals: (id) => !id.startsWith('.') && !id.startsWith('/')
})CLI Tool
export default defineConfig({
entries: [
{
input: 'src/cli.ts',
executable: true
}
],
externals: ['fs', 'path', 'process']
})Browser Library
export default defineConfig({
transformer,
runtime: 'browser',
minify: true
})Configuration Patterns
Shared Configuration
Create reusable configuration:
// config/base.ts
export const baseConfig = {
transformer,
sourcemap: true,
declaration: true
}
// packem.config.ts
import { baseConfig } from './config/base'
export default defineConfig({
...baseConfig,
// Project-specific overrides
})Factory Functions
// config/factory.ts
export function createConfig(options: {
runtime: 'node' | 'browser'
}) {
return defineConfig({
transformer,
runtime: options.runtime,
minify: options.runtime === 'browser',
rollup: {
external: options.runtime === 'node'
? (id) => !id.startsWith('.')
: []
}
})
}
// packem.config.ts
import { createConfig } from './config/factory'
export default createConfig({
runtime: 'node'
})Output formats (CommonJS / ESM) are derived from your package.json exports,
main, and module fields — there is no top-level format or target option.
Set the JavaScript language target via rollup.esbuild.target, your tsconfig.json,
or browserTargets.
Plugin System
// plugins/banner.ts
export function bannerPlugin(text: string) {
return {
rollup: {
output: {
banner: text
}
}
}
}
// packem.config.ts
export default defineConfig({
transformer,
...bannerPlugin('/* My Library */'),
})TypeScript Integration
Declaration Files
Generate TypeScript declaration files alongside your bundle:
export default defineConfig({
transformer,
declaration: true, // 'compatible' | 'node16' | false also accepted
})See the declaration option above for the meaning of each value.
Path Mapping
Packem reads your tsconfig.json automatically and resolves TypeScript path
mappings. Configure the paths in tsconfig.json:
// tsconfig.json
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"],
"@utils/*": ["./src/utils/*"]
}
}
}Path resolution is enabled by default. To resolve mapped paths to absolute
paths, enable the rollup.tsconfigPaths plugin option:
export default defineConfig({
transformer,
rollup: {
tsconfigPaths: {
resolveAbsolutePath: true
}
}
})Debugging Configuration
Verbose Output
Enable debug mode for verbose logging during the build:
export default defineConfig({
transformer,
debug: true
})Bundle Analysis
import { visualizer } from 'rollup-plugin-visualizer'
export default defineConfig({
transformer,
rollup: {
plugins: [
visualizer({
filename: 'dist/stats.html',
open: true
})
]
}
})Best Practices
Performance Optimization
export default defineConfig({
transformer: esbuild, // Fastest transformer
sourcemap: false, // Disable in production
declaration: 'node16', // Emit only .d.mts + .d.cts (skip the extra .d.ts)
rollup: {
treeshake: true, // Enable tree shaking
external: [ // Externalize dependencies
'react',
'react-dom'
]
}
})Development Experience
const isDev = process.env.NODE_ENV === 'development'
export default defineConfig({
sourcemap: isDev ? true : false,
declaration: !isDev,
rollup: {
watch: isDev ? {
include: 'src/**',
clearScreen: false
} : undefined
}
})Always test your configuration with both development and production builds to ensure everything works correctly.
Common Issues
External Dependencies
Make sure to externalize peer dependencies:
export default defineConfig({
rollup: {
external: ['react', 'react-dom', 'lodash']
}
})CSS Processing
Configure CSS loaders properly:
import postcssLoader from '@visulima/packem/css/loader/postcss'
export default defineConfig({
rollup: {
css: {
mode: 'extract', // Extract CSS to a separate file ('inject' is the default)
autoModules: true, // Treat *.module.css files as CSS modules
loaders: [postcssLoader]
}
}
})Declaration Generation
Ensure TypeScript configuration is correct:
// tsconfig.json
{
"compilerOptions": {
"declaration": true,
"declarationMap": true,
"outDir": "dist"
}
}This configuration guide provides a comprehensive foundation for setting up Packem in any project scenario.