Skip to Content

配置

@utoo/pack 支持通过 utoopack.json、utoopack.config.mjs、utoopack.config.js 和 Node API 进行配置。

配置文件

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 } }

如果配置完全可 JSON 序列化,推荐使用 utoopack.json。如果需要类型提示,或者要在 JS 里组合配置,推荐使用 utoopack.config.*。配置文件形式还可以承载 UserConfig 里的运行时字段,例如 processEnv、watch、dev、buildId、tracing、packPath、projectPath 和 rootPath。

顶层选项

选项描述
mode构建模式:development 或 production
target目标运行环境
entry入口、HTML 生成和库输出
output输出目录、文件名模板、资源复制
resolvealias 和扩展名解析
define构建时常量替换
provider自动注入模块,类似 Webpack ProvidePlugin
externals将依赖排除出 bundle
module自定义模块规则和 loader
stylesCSS Modules、Less、Sass、PostCSS、Emotion、styled-components、styled-jsx
images图片内联行为
reactJSX runtime 和 React transform 相关配置
mdxRust MDX transform 配置
reactCompilerRust React Compiler 配置
optimization压缩、tree shaking、split chunks、共享 runtime、import 转换
devServerhost、port、HTTPS、HMR、按需编译、浏览器日志转发、proxy
server服务端入口、Server Functions 和服务端输出
sourceMaps是否生成 source map
stats是否输出构建统计信息
persistentCaching是否跨次构建复用缓存
cacheDirectory持久缓存、锁文件和 trace 的存放目录
turbopackMemoryEviction持久缓存的内存回收模式
turbopackGc回收不再可达的 turbo-tasks 任务
nodePolyfill浏览器构建时是否补齐 Node.js 内置能力
swcPlugins自定义 SWC 插件
pluginRuntimeStrategyloader / plugin 的运行进程模型
experimentalreactCompiler、swcPlugins 的兼容配置入口

核心配置

mode 和 target

mode 会影响默认优化策略。

{ "mode": "production", "target": "chrome >= 80" }
值描述
development更快构建,更好调试,启用 HMR
production优化输出,压缩,tree shaking

target 是一个 Browserslist  查询。不设置时按浏览器构建;当解析出的第一个目标是 node(例如 "node 20" 或简写 "node")时,会按 Node.js 平台构建。

entry

定义应用入口、HTML 生成和库输出。

{ "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

配置输出目录、文件命名、静态资源复制和运行时资源路径。

{ "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" } }
选项描述
path输出目录
type输出类型:standalone 或 export
filename入口 chunk 文件名模板
chunkFilename非入口 chunk 文件名模板
cssFilename主 CSS 文件名模板
cssChunkFilenameCSS chunk 文件名模板
assetModuleFilename资源文件名模板
publicPath资源的公共 URL 前缀;也支持 runtime 和 auto
crossOriginLoading懒加载 chunk 的 crossorigin 配置
copy将静态文件复制到输出目录
chunkLoadingGlobal运行时加载 chunk 使用的全局变量名
clean构建前清理输出目录
entryRootExport将入口导出挂到 window / globalThis 上

publicPath: "runtime" 会从 globalThis.publicPath 读取运行时前缀;publicPath: "auto" 会根据当前加载的脚本地址自动推断前缀。

copy 支持源路径字符串,也支持 { "from": "./public", "to": "static" } 对象;to 默认与源路径相同。

生产环境下,客户端 JS 和 CSS chunk 默认使用 Turbopack 的 13 位内容哈希短文件名,开发环境保留可读文件名。显式设置的 output.filename、output.chunkFilename 和 output.cssFilename 模板优先;需要稳定入口文件名时可使用 "filename": "[name].js"。

define

构建时变量替换。

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

provider

自动注入模块,作用类似 Webpack 的 ProvidePlugin。

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

externals

从打包中排除依赖。

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

externals 支持简单字符串全局变量,也支持 script、commonjs、esm、global、promise 形式以及更复杂的子路径配置。

resolve

配置模块解析。resolve.alias 会在模块解析前,把导入请求改写到另一个模块或路径,规则采用 Turbopack 风格的 alias 行为 。

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

resolve.alias 支持以下结构:

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

匹配规则:

Alias会匹配不会匹配
"foo": "./src/foo"import "foo"import "foo/bar"
"foo/*": "./src/foo/*"import "foo/bar" 以及更深的子路径import "foo"
"foo/": "./src/foo/"等价于 "foo/*": "./src/foo/*"import "foo"

如果需要把匹配到的子路径带入替换结果,使用 *。* 可以跨路径分隔符,因此 "@/*": "./src/*" 可以解析 @/components/Button 这样的导入。

alias value 支持以下形式:

Value行为
string改写到单个包或路径
string[]按顺序尝试多个候选路径
条件对象按条件选择 value,常用条件是 browser,不满足时使用 default

相对路径 value 会从项目根目录解析,例如 "./src/foo"。项目内的绝对路径会被规范化为项目相对路径。不要配置指向项目目录之外的 alias。

utoopack.config.mjs
import { defineConfig } from '@utoo/pack'; export default defineConfig({ resolve: { alias: { // 精确替换 lodash: 'lodash-es', // 子路径替换 '@/*': './src/*', // 目录简写 'components/': './src/components/', // 多候选 'runtime/*': ['./src/runtime/*', './fallback/runtime/*'], // 条件 alias env: { browser: './src/env.browser.ts', default: './src/env.node.ts', }, }, extensions: ['.ts', '.tsx', '.js', '.jsx'], }, });

从 Webpack alias 迁移

最容易踩坑的差异是子路径匹配。Webpack 中常见的 foo: path.resolve(__dirname, 'src/foo') 通常可以同时覆盖 foo 和 foo/bar。在 Utoopack 中,普通 key 是精确匹配;如果要覆盖子路径,需要显式加 /*,或者使用以 / 结尾的目录简写。

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

Webpack 通过 $ 后缀表示精确匹配,例如 foo$: './src/foo'。Utoopack 不需要这个后缀,因为精确匹配就是默认行为:

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

这只会影响:

import "foo"

不会影响:

import "foo/bar"

如果需要覆盖子路径,应该写成:

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

或使用目录简写:

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

module

定义基于 loader 的模块规则。规则对象支持 loaders、condition 和 type 等字段。

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

styles

配置内置样式处理能力。

{ "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 } } }

styles.cssModules.localIdentName 用于自定义 CSS Modules 类名模板。styles.less.loader 用于指定自定义 Less loader;implementation 指定实际使用的 Less 实现,其他字段会继续传给 loader。

styles.postcss 中的插件会在发现的 postcss.config.* 插件之后、同一轮 PostCSS 处理中执行。

styles.postcss.implementation

指定构建时使用的 PostCSS 模块,类型为 string | null,值必须是模块的绝对路径。未配置或设为 null 时,默认在运行时解析 postcss。此字段不会传给 PostCSS 插件配置。

可以在 JS 配置文件中通过 require.resolve() 获取路径:

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'), }, }, });

images

配置图片内联行为。

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

react

React transform 相关配置。

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

mdx

mdx 启用 Rust MDX transform。可以直接传布尔值,也可以传对象配置编译模式、JSX runtime 和 MDX 语法模式。

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

mdxType 支持 commonmark 和 gfm。使用默认配置时可以简写为 "mdx": true。

React Compiler 和 SWC 插件

reactCompiler 可以是布尔值,也可以通过 compilationMode 和 target 配置 Rust React Compiler。compilationMode 支持 infer、annotation 和 all,target 支持 React 17、18 和 19,默认 19;React 17 和 18 需要安装 react-compiler-runtime。

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

experimental.reactCompiler 和 experimental.swcPlugins 仍然可用。顶层 reactCompiler 优先于 experimental.reactCompiler;顶层和 experimental 中的 swcPlugins 会合并执行。

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 } }
选项类型描述
moduleIdsnamed | deterministic模块 ID 生成策略
noManglingboolean压缩时保留变量、函数等局部名称,并保留生产构建的导出名
compressboolean | object控制压缩优化;对象支持 passes、sequences、keepClassnames、keepFnames
minifyboolean压缩输出代码
extractCommentsboolean库构建压缩时将 legal comments 提取到 [file].LICENSE.txt
treeShakingboolean移除未使用代码
inferModuleSideEffectsboolean当包元数据未声明 sideEffects 时,从源码推断无副作用模块;默认开启
splitChunksobject分别配置 js / css chunk 的尺寸和数量限制
cssChunkingboolean | string | objectCSS chunk 分组算法
modularizeImportsobject按模板转换包导入,类似 babel-plugin-import
packageImportsstring[]优化具有大量导出的包入口
transpilePackagesstring[]转译指定依赖包
removeConsoleboolean | object移除 console 调用,可通过 exclude 保留方法
concatenateModulesboolean合并模块以减少 chunk 数量;CLI 在生产环境默认开启
sharedRuntimeboolean生产浏览器应用入口共享 runtime 资源;默认关闭
removeUnusedExportsboolean移除未使用导出;开发环境默认关闭,生产环境默认开启
removeUnusedImportsboolean移除未使用导入;开发环境默认关闭,生产环境默认开启
nestedAsyncChunkingboolean启用嵌套异步 chunk
wasmAsAssetboolean将 WASM 内联到 bundle;默认关闭并作为静态资源输出

optimization.sharedRuntime

设置 optimization.sharedRuntime: true,将浏览器 runtime 提取为多个生产应用入口共用的资源,每个入口保留独立的 bootstrap 脚本。共享 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 } }

默认 false,开发模式、Node.js 目标和库构建会忽略此项。单入口应用则会比默认内嵌 runtime 多一次请求。

内置 HTML 生成会自动注入入口 bootstrap 和共享 runtime。自行生成 HTML 时,可开启 stats: true,按 stats.entrypoints[入口名].assets 中的 JS 资源顺序加载脚本,其中入口 bootstrap 位于共享 runtime 之前。

optimization.inferModuleSideEffects

当包没有声明 sideEffects 元数据时,Utoopack 可以根据源码推断无副作用模块,并将结果用于 tree shaking。默认 true,设置 optimization.inferModuleSideEffects: false 可关闭源码推断。

optimization.packageImports

optimization.packageImports 用于优化导出大量模块的包的具名导入。将包名加入配置后,业务代码仍可从包的根入口导入,Utoopack 只加载实际使用的模块,从而减少开发和生产构建中的模块解析与编译开销。该选项的类型为 string[],用法类似 Next.js 的 optimizePackageImports。

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

Utoopack 的内置列表参考 Next.js 维护,但以 DEFAULT_OPTIMIZE_PACKAGE_IMPORTS 的实现为准。当前共包含 74 个包或包子路径:

[ "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" ]

通过 optimization.packageImports 配置的包会与这份内置列表合并并去重。

optimization.cssChunking

optimization.cssChunking 支持 true、loose 和 graph。loose(以及 true)使用默认分组算法;graph 使用基于图的算法,也可以通过对象调整额外请求的估算成本和权重分布。

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

false、strict 和 { "type": "strict" } 当前不受 Utoopack 支持,使用时构建会报错。

devServer

配置本地开发服务器、HMR、动态导入按需编译、浏览器日志转发和 HTTP 代理。

{ "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": "" } } ] } }
选项类型默认值描述
hotboolean开发服务器中为 true启用 HMR
dynamicHmrChunkListsbooleanfalse随动态 chunk 加载注册对应的 HMR chunk list;需要开启 hot
lazyDynamicImportsbooleanfalse浏览器首次请求时才编译客户端 import() 目标;仅开发模式生效
browserToTerminalboolean | "error" | "warn"false将浏览器 console 输出转发到开发终端
hoststring"localhost"开发服务器监听地址
portnumber3000优先使用的端口;占用时选择可用端口
httpsbooleanfalse使用 HTTPS,可自动生成自签名证书
proxyobject[]无代理规则HTTP 代理规则

devServer.lazyDynamicImports

将客户端 import() 目标的编译延后到浏览器首次请求时,减少开发启动阶段需要编译的模块。仅开发模式生效,默认 false;首次加载对应模块时需要等待编译完成。

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

建议同时开启 hot 和 dynamicHmrChunkLists,让按需加载的模块继续接收 HMR 更新。lazyDynamicImports 不会自动开启这两个 HMR 选项。

devServer.browserToTerminal

使用 "error" 转发错误,"warn" 额外转发警告,true 转发全部受支持的 console 输出,默认 false。错误级别也包括失败断言、未捕获错误和未处理的 Promise rejection。

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

devServer.proxy

每条 proxy 规则支持以下字段:

字段描述
context需要代理的路径前缀,可以是数组;以 ^ 开头时按正则匹配
target目标服务地址
pathRewrite正则到替换串的对象,命中第一条即生效;JS 配置中也可以传 (path) => string 函数
changeOrigin是否把 Host 头改写为目标地址,默认 true
secure是否校验目标的 TLS 证书;自签名证书可设为 false

server

server 配置服务端入口、Server Functions 边界、服务端 chunk 输出,以及服务端专用的 resolve / externals 覆盖。entry 可以是单个入口字符串,也可以是具名入口数组;数组中的第一个入口是主服务端运行时,并接收 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" } } }

单入口可以简写为 "entry": "./src/server.ts"。clientProxy 模块需要导出 createServerReference(actionId, name),serverRegister 模块需要导出 registerServerReference(action, actionId, name)。

server.resolve 只作用于服务端构建:其中的 alias 会覆盖同名的顶层 resolve.alias,extensions 设置后会整体替换 resolve.extensions。server.externals 设置后会替换服务端入口和 Server Functions 使用的顶层 externals;不设置时继续沿用顶层 externals,设为 {} 可以让服务端构建不使用任何 externals。

高级选项

选项类型描述
sourceMapsboolean启用 source map
statsboolean启用构建统计输出
nodePolyfillboolean为浏览器补齐 Node.js 内置模块
persistentCachingboolean启用持久化构建缓存,默认开启
cacheDirectorystring持久缓存、锁文件和 trace 的目录,默认 .turbopack;相对路径基于项目路径解析,也支持绝对路径
turbopackMemoryEvictionboolean | auto | full持久缓存的内存回收模式,默认 auto;false 关闭,true 等价于 full
turbopackGcboolean在持久缓存快照阶段回收不再可达的 turbo-tasks 任务;默认 false
swcPlugins[string, any][]自定义 SWC 插件及其选项
pluginRuntimeStrategyworkerThreads | childProcessesloader / plugin 使用 worker thread 或子进程运行
experimentalobjectreactCompiler 和 swcPlugins 的兼容配置入口

缓存目录与任务回收

cacheDirectory 统一控制持久缓存、锁文件和 trace 的存放位置。请将自定义缓存目录加入 .gitignore。

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

turbopackGc 默认 false,不读取 TURBO_ENGINE_GC 环境变量。垃圾回收在持久缓存快照阶段执行,因此设置 persistentCaching: false 后,常规构建和开发流程不会触发垃圾回收。

开发模式使用可读写持久缓存时,若设置 turbopackMemoryEviction: false,即使 turbopackGc: true,后端也会发出警告并强制关闭垃圾回收。开启垃圾回收时,建议同时开启持久缓存,并将 turbopackMemoryEviction 设为 "auto" 或 "full"。

配置文件运行时字段

这些字段属于 UserConfig,可在 utoopack.config.* 中控制构建运行过程。

选项类型描述
processEnvRecord<string, string>编译时使用的环境变量
watchobject文件监听配置
devboolean是否以开发模式运行
buildIdstring当前构建 ID
tracingboolean是否显示编译进度,默认开启;Rust tracing 日志由 RUST_LOG 环境变量控制
packPathstring@utoo/pack 的绝对路径
projectPathstring项目路径
rootPathstring根路径,monorepo 中可与项目路径不同

watch 支持 enable、pollIntervalMs、ignored 和 nodeModulesRegexes。默认忽略 node_modules;ignored 中的 !node_modules/<regex> 或 nodeModulesRegexes 中的包名正则可以重新纳入需要监听的依赖。

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/.*'], }, });

编程 API

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

build(options, projectPath?, rootPath?) 和 serve(options, projectPath?, rootPath?, serverOptions?) 接收 BundleOptions(即 config 对象加上 processEnv、watch、dev、buildId、tracing、packPath 等运行时字段),或者兼容模式下的 WebpackConfig。不传 rootPath 时会从项目路径自动向上查找。serve() 的 serverOptions 支持 port、hostname、https、logServerInfo、selfSignedCertificate,以及在首次构建写出、服务开始监听后触发的 onReady 回调。

完整配置 schema 见 config_schema.json 。

Last updated on