Skip to Content
Docs@utoo/packConfiguration

Configuration

@utoo/pack can be configured with utoopack.json, utoopack.config.mjs, utoopack.config.js, or the Node API.

Configuration Files

utoopack.json
{ "$schema": "@utoo/pack/config_schema.json", "mode": "production", "entry": [ { "import": "./src/index.ts", "html": { "template": "./index.html" } } ], "output": { "path": "./dist", "filename": "[name].[contenthash:8].js", "chunkFilename": "[name].[contenthash:8].js", "clean": true } }

Use utoopack.json when your config is fully JSON-serializable. Use utoopack.config.* when you want type inference or JS-based composition. The config-file form can also carry runtime-only UserConfig fields such as processEnv, watch, dev, buildId, tracing, packPath, projectPath, and rootPath.

Top-level Options

OptionDescription
modeBuild mode: development or production
targetTarget environment
entryEntry points, HTML generation, and library output
outputOutput path, filename templates, public path, asset copying
resolveAliases and extension resolution
defineBuild-time constant replacement
providerAuto-provide modules, similar to Webpack ProvidePlugin
externalsKeep dependencies out of the bundle
moduleCustom module rules and loaders
stylesCSS Modules, Less, Sass, PostCSS, Emotion, styled-components, styled-jsx
imagesAsset inlining behavior
reactJSX runtime and React transform options
mdxRust MDX transform options
reactCompilerRust React Compiler options
optimizationMinification, tree shaking, split chunks, shared runtime, import transforms
devServerHost, port, HTTPS, HMR, lazy compilation, browser console forwarding, proxy
serverServer entries, Server Functions, and server output
sourceMapsEnable source maps
statsEmit build stats
persistentCachingReuse cache across runs
cacheDirectoryDirectory for the persistent cache, lock, and trace files
turbopackMemoryEvictionMemory eviction mode for the persistent cache
turbopackGcGarbage collection of unreachable tasks
nodePolyfillPolyfill Node.js built-ins for browser builds
swcPluginsCustom SWC plugins
pluginRuntimeStrategyLoader / plugin process model
experimentalCompatibility entry for reactCompiler and swcPlugins

Core Configuration

mode and target

Build mode affects optimizations and defaults.

{ "mode": "production", "target": "chrome >= 80" }
ValueDescription
developmentFaster builds, better debugging, HMR enabled
productionOptimized output, minification, tree shaking

target is a Browserslist  query. Omit it for a browser build. When the first resolved distribution is node, for example "node 20" or the shorthand "node", the build targets the Node.js platform.

entry

Define application entry points, HTML generation, and library output.

{ "entry": [ { "name": "main", "import": "./src/index.ts", "library": { "name": "MyBundle", "export": ["default"] }, "html": { "template": "./index.html", "filename": "index.html", "title": "My App", "inject": "body", "scriptLoading": "module" } } ] }

output

Configure output path, file naming, static copying, and runtime asset URLs.

{ "output": { "path": "./dist", "type": "standalone", "filename": "[name].[contenthash:8].js", "chunkFilename": "[name].[contenthash:8].js", "cssFilename": "[name].[contenthash:8].css", "cssChunkFilename": "[name].[contenthash:8].css", "assetModuleFilename": "assets/[name].[contenthash:8][ext]", "publicPath": "/", "crossOriginLoading": "anonymous", "copy": ["./public"], "chunkLoadingGlobal": "TURBOPACK", "clean": true, "entryRootExport": "AppExports" } }
OptionDescription
pathOutput directory
typeOutput type: standalone or export
filenameEntry chunk filename template
chunkFilenameNon-entry chunk filename template
cssFilenameMain CSS filename template
cssChunkFilenameCSS chunk filename template
assetModuleFilenameAsset filename template
publicPathPublic URL prefix for assets; also supports runtime and auto
crossOriginLoadingCross-origin attribute for lazy chunks
copyCopy static files into the output directory
chunkLoadingGlobalGlobal variable used by the runtime to load chunks
cleanClean output directory before build
entryRootExportExpose entry exports on window / globalThis

Use publicPath: "runtime" to read the runtime prefix from globalThis.publicPath, or publicPath: "auto" to infer it from the currently loaded script URL.

copy accepts source path strings or { "from": "./public", "to": "static" } objects; to defaults to the source path.

In production, client JS and CSS chunks default to short content-hashed names using Turbopack’s 13-character hash, while development builds keep readable names. Explicit output.filename, output.chunkFilename, and output.cssFilename templates take precedence; use "filename": "[name].js" when consumers need stable entry filenames.

define

Build-time variable replacement.

{ "define": { "process.env.NODE_ENV": "\"production\"", "__VERSION__": "\"1.0.0\"" } }

provider

Automatically inject modules, similar to Webpack ProvidePlugin.

{ "provider": { "$": "jquery", "Buffer": ["buffer", "Buffer"] } }

externals

Exclude dependencies from the bundle.

{ "externals": { "react": "React", "react-dom": "ReactDOM", "lodash-es": { "root": "_", "type": "global" } } }

Externals support simple string globals, script, commonjs, esm, global, and promise forms, plus more advanced subpath configuration.

resolve

Configure module resolution. resolve.alias rewrites an import request to another module or path, using Turbopack-style alias rules .

{ "resolve": { "alias": { "react": "preact/compat", "@/*": "./src/*", "legacy/": "./src/legacy/", "runtime/*": ["./src/runtime/*", "./fallback/runtime/*"] }, "extensions": [".ts", ".tsx", ".js", ".jsx"] } }

resolve.alias accepts this shape:

type ResolveAlias = Record<string, string | string[] | Record<string, string | string[]>>

Matching rules:

AliasMatchesDoes not match
"foo": "./src/foo"import "foo"import "foo/bar"
"foo/*": "./src/foo/*"import "foo/bar" and deeper subpathsimport "foo"
"foo/": "./src/foo/"Same as "foo/*": "./src/foo/*"import "foo"

Use * when you want to carry the matched subpath into the replacement. The * can match across path separators, so "@/*": "./src/*" resolves imports such as @/components/Button.

Alias values can be:

ValueBehavior
stringRewrite to a single package or path
string[]Try multiple candidates in order
condition objectPick a value by condition, commonly browser, with default as the fallback

Relative path values are resolved from the project root, for example "./src/foo". Absolute paths inside the project are normalized to project-relative paths. Avoid aliases that point outside the project directory.

utoopack.config.mjs
import { defineConfig } from '@utoo/pack'; export default defineConfig({ resolve: { alias: { // Exact replacement lodash: 'lodash-es', // Subpath replacement '@/*': './src/*', // Directory shortcut 'components/': './src/components/', // Multiple candidates 'runtime/*': ['./src/runtime/*', './fallback/runtime/*'], // Conditional alias env: { browser: './src/env.browser.ts', default: './src/env.node.ts', }, }, extensions: ['.ts', '.tsx', '.js', '.jsx'], }, });

Migrating from Webpack alias

The biggest difference is subpath matching. In Webpack, an alias such as foo: path.resolve(__dirname, 'src/foo') is commonly used to cover both foo and foo/bar. In Utoopack, a plain key is exact. Add /* or use the trailing slash shortcut when you want subpath imports.

WebpackUtoopack
foo: path.resolve(__dirname, 'src/foo') for import "foo""foo": "./src/foo"
foo: path.resolve(__dirname, 'src/foo') for import "foo/bar""foo/*": "./src/foo/*" or "foo/": "./src/foo/"
'@': path.resolve(__dirname, 'src') for import "@/Button""@/*": "./src/*"
react: 'preact/compat'"react": "preact/compat"

Webpack’s $ suffix marks an exact alias, for example foo$: './src/foo'. Utoopack does not need that suffix because exact matching is the default:

{ "resolve": { "alias": { "foo": "./src/foo" } } }

This only affects:

import "foo"

It does not affect:

import "foo/bar"

To cover subpaths, use:

{ "resolve": { "alias": { "foo/*": "./src/foo/*" } } }

Or the directory shortcut:

{ "resolve": { "alias": { "foo/": "./src/foo/" } } }

module

Define loader-based module rules. Rule objects can include loaders, condition, and type.

{ "module": { "rules": { "*.md": ["raw-loader"], "*.svg": [ { "loaders": [ { "loader": "@svgr/webpack", "options": { "icon": true } } ] } ] } } }

styles

Configure built-in style processing.

{ "styles": { "autoCssModules": true, "cssModules": { "localIdentName": "[local]__[hash:base64:6]" }, "postcss": {}, "less": { "loader": "less-loader", "implementation": "less" }, "sass": { "implementation": "sass" }, "inlineCss": { "injectType": "styleTag" }, "emotion": { "autoLabel": "dev-only" }, "styledComponents": { "displayName": true, "ssr": true }, "styledJsx": { "useLightningcss": true } } }

Use styles.cssModules.localIdentName to customize the CSS Modules class-name template. Use styles.less.loader to select a custom Less loader; implementation selects the Less implementation, and additional fields are forwarded to the loader.

Inline styles.postcss plugins run after plugins from a discovered postcss.config.* file in the same PostCSS pass.

styles.postcss.implementation

styles.postcss.implementation accepts an absolute path to the PostCSS module as a string, or null. When omitted or set to null, Utoopack resolves postcss at runtime. Use a JavaScript config to resolve a specific installed implementation:

utoopack.config.mjs
import { createRequire } from 'node:module'; import { defineConfig } from '@utoo/pack'; const require = createRequire(import.meta.url); export default defineConfig({ entry: [{ import: './src/index.ts' }], styles: { postcss: { implementation: require.resolve('postcss'), }, }, });

This field selects the implementation and is not forwarded to PostCSS plugins.

images

Configure image inlining.

{ "images": { "inlineLimit": 8192 } }

react

React transform options.

{ "react": { "runtime": "automatic", "importSource": "react", "absoluteSourceFilename": false } }

mdx

mdx enables the Rust MDX transform. It accepts a boolean or an object that configures compilation, the JSX runtime, and the MDX syntax mode.

{ "mdx": { "development": false, "jsx": false, "jsxRuntime": "automatic", "jsxImportSource": "react", "providerImportSource": "@mdx-js/react", "mdxType": "gfm" } }

mdxType supports commonmark and gfm. Use "mdx": true to enable the default configuration.

React Compiler and SWC plugins

reactCompiler accepts a boolean or an object with compilationMode and target for the Rust React Compiler. compilationMode supports infer, annotation, and all; target supports React 17, 18, and 19 and defaults to 19. React 17 and 18 require react-compiler-runtime.

{ "reactCompiler": { "compilationMode": "infer", "target": "19" }, "swcPlugins": [ ["swc-plugin-name", {}] ] }

experimental.reactCompiler and experimental.swcPlugins remain supported. Top-level reactCompiler takes precedence over experimental.reactCompiler; swcPlugins from the top level and experimental are merged.

optimization

{ "optimization": { "minify": true, "extractComments": true, "treeShaking": true, "moduleIds": "deterministic", "splitChunks": { "js": { "minChunkSize": 50000, "maxChunkCountPerGroup": 40, "maxMergeChunkSize": 200000 } }, "cssChunking": "graph", "modularizeImports": { "lodash": { "transform": "lodash/{{member}}", "preventFullImport": true } }, "packageImports": ["package-name"], "transpilePackages": ["shared-ui"], "removeConsole": { "exclude": ["error"] }, "concatenateModules": true, "removeUnusedExports": true, "removeUnusedImports": true } }
OptionTypeDescription
moduleIdsnamed | deterministicModule ID generation strategy
noManglingbooleanDisable local-name minifier mangling and production export-name mangling
compressboolean | objectControl compression; object options include passes, sequences, keepClassnames, and keepFnames
minifybooleanMinify output code
extractCommentsbooleanExtract legal comments to [file].LICENSE.txt when minifying library output
treeShakingbooleanRemove unused code
inferModuleSideEffectsbooleanInfer side-effect-free modules from source when package metadata does not declare sideEffects; defaults to true
splitChunksobjectConfigure size and count limits for js / css chunks
cssChunkingboolean | string | objectCSS chunk grouping algorithm
modularizeImportsobjectTransform package imports with templates, similar to babel-plugin-import
packageImportsstring[]Optimize package entry points with many exports
transpilePackagesstring[]Transpile selected dependencies
removeConsoleboolean | objectRemove console calls, with optional methods retained through exclude
concatenateModulesbooleanConcatenate modules to reduce chunk count; the CLI enables it by default in production
sharedRuntimebooleanShare one runtime asset across production browser application entries; defaults to false
removeUnusedExportsbooleanRemove unused exports; defaults off in development and on in production
removeUnusedImportsbooleanRemove unused imports; defaults off in development and on in production
nestedAsyncChunkingbooleanEnable nested async chunks
wasmAsAssetbooleanInline WASM into the bundle; defaults off and emits static assets instead

optimization.sharedRuntime

Set optimization.sharedRuntime: true to emit one browser runtime asset shared across production application entries. Each entry keeps its own small bootstrap script. Sharing reduces duplicated runtime code and lets separate pages reuse the cached runtime.

utoopack.json
{ "mode": "production", "entry": [ { "name": "main", "import": "./src/index.ts", "html": { "template": "./index.html", "filename": "index.html" } }, { "name": "admin", "import": "./src/admin.ts", "html": { "template": "./admin.html", "filename": "admin.html" } } ], "optimization": { "sharedRuntime": true } }

The option defaults to false and is ignored in development, Node.js, and library builds. For a single entry, separating the runtime adds a request compared with the default embedded runtime.

Generated HTML automatically includes the entry bootstrap followed by the shared runtime. If you maintain HTML yourself, enable stats: true and load JavaScript assets in the order returned by stats.entrypoints[entry].assets, including the bootstrap before the runtime. Preserve that order when adding script tags.

optimization.inferModuleSideEffects

When a package does not declare sideEffects metadata, Utoopack can infer side-effect-free modules from their source and use that information for tree shaking. This option defaults to true. Set optimization.inferModuleSideEffects: false to disable source-based inference.

optimization.packageImports

optimization.packageImports optimizes named imports from packages that export many modules. After adding a package, application code can keep importing from the package root while Utoopack loads only the modules that are actually used, reducing module parsing and compilation overhead in development and production builds. The option accepts a string[] and behaves similarly to Next.js optimizePackageImports.

utoopack.json
{ "optimization": { "packageImports": ["package-name"] } }

Utoopack’s built-in list is maintained with reference to Next.js, but the DEFAULT_OPTIMIZE_PACKAGE_IMPORTS implementation is the source of truth. It currently contains 74 packages or package subpaths:

[ "lucide-react", "date-fns", "lodash-es", "ramda", "react-bootstrap", "ahooks", "@ant-design/icons", "@headlessui/react", "@headlessui-float/react", "@heroicons/react/20/solid", "@heroicons/react/24/solid", "@heroicons/react/24/outline", "@visx/visx", "@tremor/react", "rxjs", "@mui/material", "@mui/icons-material", "recharts", "react-use", "effect", "@effect/schema", "@effect/platform", "@effect/platform-node", "@effect/platform-browser", "@effect/platform-bun", "@effect/sql", "@effect/sql-mssql", "@effect/sql-mysql2", "@effect/sql-pg", "@effect/sql-sqlite-node", "@effect/sql-sqlite-bun", "@effect/sql-sqlite-wasm", "@effect/sql-sqlite-react-native", "@effect/rpc", "@effect/rpc-http", "@effect/typeclass", "@effect/experimental", "@effect/opentelemetry", "@material-ui/core", "@material-ui/icons", "@tabler/icons-react", "mui-core", "react-icons/ai", "react-icons/bi", "react-icons/bs", "react-icons/cg", "react-icons/ci", "react-icons/di", "react-icons/fa", "react-icons/fa6", "react-icons/fc", "react-icons/fi", "react-icons/gi", "react-icons/go", "react-icons/gr", "react-icons/hi", "react-icons/hi2", "react-icons/im", "react-icons/io", "react-icons/io5", "react-icons/lia", "react-icons/lib", "react-icons/lu", "react-icons/md", "react-icons/pi", "react-icons/ri", "react-icons/rx", "react-icons/si", "react-icons/sl", "react-icons/tb", "react-icons/tfi", "react-icons/ti", "react-icons/vsc", "react-icons/wi" ]

Packages configured through optimization.packageImports are merged with this built-in list and de-duplicated.

optimization.cssChunking

optimization.cssChunking supports true, loose, and graph. loose (and true) uses the default grouping algorithm. graph uses graph-based grouping and can be configured with estimated request cost and weight distribution.

utoopack.json
{ "optimization": { "cssChunking": { "type": "graph", "requestCost": 100000, "weightDistribution": 0.1 } } }

false, strict, and { "type": "strict" } are not currently supported by Utoopack and cause the build to fail.

devServer

Configure the development server, HMR, on-demand compilation, browser console forwarding, and HTTP proxies.

{ "devServer": { "hot": true, "dynamicHmrChunkLists": true, "lazyDynamicImports": true, "browserToTerminal": "warn", "host": "0.0.0.0", "port": 3000, "https": false, "proxy": [ { "context": ["/api"], "target": "http://localhost:7001", "changeOrigin": true, "pathRewrite": { "^/api": "" } } ] } }
OptionTypeDefaultDescription
hotbooleantrue in the dev serverEnable Hot Module Replacement
dynamicHmrChunkListsbooleanfalseRegister HMR chunk lists as dynamic chunks load; requires hot: true
lazyDynamicImportsbooleanfalseCompile client import() targets when the browser first requests them; development only
browserToTerminalboolean | "error" | "warn"falseForward browser console output to the development terminal
hoststring"localhost"Host to bind
portnumber3000Preferred port; an available port is selected if it is in use
httpsbooleanfalseEnable HTTPS; a self-signed certificate may be generated
proxyobject[]No proxy rulesHTTP proxy rules

devServer.lazyDynamicImports

lazyDynamicImports defers compiling the targets of client import() calls until the browser first requests them. It only applies in development and defaults to false. This can reduce the modules compiled at startup; the first request for an imported module waits for its compilation.

utoopack.json
{ "devServer": { "hot": true, "dynamicHmrChunkLists": true, "lazyDynamicImports": true } }

Pair this option with dynamicHmrChunkLists: true and keep hot: true so modules loaded on demand continue receiving HMR updates. Enabling lazyDynamicImports does not automatically enable either HMR option.

devServer.browserToTerminal

Use "error" to forward errors, "warn" to include warnings, or true to forward all supported console output. The default is false. Error-level output also includes failed assertions, uncaught errors, and unhandled Promise rejections.

utoopack.json
{ "devServer": { "browserToTerminal": "warn" } }

devServer.proxy

Each proxy rule supports:

FieldDescription
contextPath prefix or prefixes to match; a value starting with ^ is treated as a regular expression
targetTarget server URL
pathRewriteObject of regex-to-replacement pairs where the first match wins, or a (path) => string function in JS configs
changeOriginRewrite the Host header to match the target; defaults to true
secureVerify the target’s TLS certificate; set false to accept self-signed certificates

server

server configures server entries, Server Functions boundaries, server chunk output, and server-only resolve / externals overrides. entry accepts a single entry string or an array of named entries. The first item in an entry array is the primary server runtime and receives Server Functions.

utoopack.json
{ "server": { "entry": [ { "name": "server", "import": "./src/server.ts" }, { "name": "admin-server", "import": "./src/admin.server.ts" } ], "resolve": { "alias": { "@/*": "./src/*" } }, "externals": { "pg": { "root": "pg", "type": "commonjs" } }, "function": { "clientProxy": "./src/transport.ts", "serverRegister": "./src/register.ts" }, "output": { "path": "./dist/server", "filename": "[name].[contenthash:8].js", "chunkFilename": "chunks/[name].[contenthash:8].js" } } }

For a single entry, use the shorthand "entry": "./src/server.ts". The clientProxy module must export createServerReference(actionId, name), and the serverRegister module must export registerServerReference(action, actionId, name).

server.resolve is applied only to server builds: its alias entries override matching top-level resolve.alias entries, and its extensions replace resolve.extensions when set. server.externals replaces the top-level externals map for server entries and Server Functions when provided; omit it to keep using top-level externals, or set it to {} to disable externals for server builds.

Advanced Options

OptionTypeDescription
sourceMapsbooleanEnable source maps
statsbooleanEnable build statistics output
nodePolyfillbooleanPolyfill Node.js built-ins for browser
persistentCachingbooleanEnable persistent build cache; enabled by default
cacheDirectorystringPersistent cache, lock, and trace directory; defaults to .turbopack, relative to projectPath
turbopackMemoryEvictionboolean | auto | fullPersistent-cache memory eviction; defaults to auto; false disables it and true is equivalent to full
turbopackGcbooleanCollect unreachable tasks during persistent-cache snapshots; defaults to false
swcPlugins[string, any][]Custom SWC plugins and their options
pluginRuntimeStrategyworkerThreads | childProcessesRun loaders / plugins in worker threads or child processes
experimentalobjectCompatibility entry for reactCompiler and swcPlugins

Cache directory and task garbage collection

cacheDirectory sets the directory used for persistent cache data, lock files, and trace files. It defaults to .turbopack. Relative paths are resolved from projectPath; absolute paths are also supported. Add a custom cache directory to .gitignore.

utoopack.json
{ "persistentCaching": true, "cacheDirectory": ".cache/utoopack", "turbopackMemoryEviction": "auto", "turbopackGc": true }

turbopackGc defaults to false and does not read the TURBO_ENGINE_GC environment variable. Garbage collection runs during persistent-cache snapshots, so setting persistentCaching: false prevents it from running in the normal build and development workflow.

In development with read/write persistent caching, setting turbopackMemoryEviction: false disables garbage collection even if turbopackGc: true; the backend emits a warning. Enable persistent caching and use turbopackMemoryEviction: "auto" or "full" when enabling garbage collection.

Config-file runtime fields

These UserConfig fields can be used in utoopack.config.* to control the build process.

OptionTypeDescription
processEnvRecord<string, string>Environment variables used during compilation
watchobjectFile-watching options
devbooleanRun in development mode
buildIdstringCurrent build ID
tracingbooleanShow compilation progress; enabled by default. Rust tracing logs are controlled by RUST_LOG
packPathstringAbsolute path to @utoo/pack
projectPathstringProject path
rootPathstringRoot path, which may differ from the project path in a monorepo

watch supports enable, pollIntervalMs, ignored, and nodeModulesRegexes. node_modules is ignored by default. Use !node_modules/<regex> entries in ignored, or package-name regular expressions in nodeModulesRegexes, to include selected dependencies in watching.

utoopack.config.mjs
import { defineConfig } from '@utoo/pack'; export default defineConfig({ entry: [{ import: './src/index.ts' }], watch: { enable: true, pollIntervalMs: 500, ignored: ['node_modules'], nodeModulesRegexes: ['rc-.*', '@rc-component/.*'], }, });

Programmatic API

const { build } = require('@utoo/pack'); await build({ config: { mode: "production", entry: [{ import: "./src/index.ts" }], output: { path: "./dist" } } });

build(options, projectPath?, rootPath?) and serve(options, projectPath?, rootPath?, serverOptions?) accept either BundleOptions, which is the config object plus runtime fields such as processEnv, watch, dev, buildId, tracing, and packPath, or a WebpackConfig in compatibility mode. When rootPath is omitted it is discovered from the project path. serverOptions for serve() supports port, hostname, https, logServerInfo, selfSignedCertificate, and an onReady callback that fires once the first build is written and the server is listening.

For the full configuration schema, see config_schema.json .

Last updated on