配置
@utoo/pack 支持通过 utoopack.json、utoopack.config.mjs 和 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 | 输出目录、文件名模板、资源复制 |
resolve | alias 和扩展名解析 |
define | 构建时常量替换 |
provider | 自动注入模块,类似 Webpack ProvidePlugin |
externals | 将依赖排除出 bundle |
module | 自定义模块规则和 loader |
styles | CSS Modules、Less、Sass、PostCSS、Emotion、styled-components、styled-jsx |
images | 图片内联行为 |
react | JSX runtime 和 React transform 相关配置 |
mdx | Rust MDX transform 配置 |
reactCompiler | Rust React Compiler 配置 |
optimization | 压缩、tree shaking、split chunks、import 转换 |
devServer | host、port、HTTPS、HMR、proxy |
server | 服务端入口、Server Functions 和服务端输出 |
sourceMaps | 是否生成 source map |
stats | 是否输出构建统计信息 |
persistentCaching | 是否跨次构建复用缓存 |
turbopackMemoryEviction | 持久缓存的内存回收模式 |
nodePolyfill | 浏览器构建时是否补齐 Node.js 内置能力 |
swcPlugins | 自定义 SWC 插件 |
pluginRuntimeStrategy | loader / plugin 的运行进程模型 |
experimental | reactCompiler、swcPlugins 的兼容配置入口 |
核心配置
mode 和 target
mode 会影响默认优化策略,target 用来指定输出运行环境。
{
"mode": "production",
"target": "browser"
}| 值 | 描述 |
|---|---|
development | 更快构建,更好调试,启用 HMR |
production | 优化输出,压缩,tree shaking |
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 文件名模板 |
cssChunkFilename | CSS chunk 文件名模板 |
assetModuleFilename | 资源文件名模板 |
publicPath | 资源的公共 URL 前缀;也支持 runtime 和 auto |
crossOriginLoading | 懒加载 chunk 的 crossorigin 配置 |
copy | 将静态文件复制到输出目录 |
chunkLoadingGlobal | 运行时加载 chunk 使用的全局变量名 |
clean | 构建前清理输出目录 |
entryRootExport | 将入口导出挂到 window / globalThis 上 |
publicPath: "runtime" 会从 globalThis.publicPath 读取运行时前缀;publicPath: "auto" 会根据当前加载的脚本地址自动推断前缀。
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。
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 是精确匹配;如果要覆盖子路径,需要显式加 /*,或者使用以 / 结尾的目录简写。
| Webpack | Utoopack |
|---|---|
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。
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 18 和 19。
{
"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
}
}| 选项 | 类型 | 描述 |
|---|---|---|
moduleIds | named | deterministic | 模块 ID 生成策略 |
noMangling | boolean | 压缩时保留变量、函数等局部名称 |
compress | boolean | object | 控制压缩优化;对象支持 passes、sequences、keepClassnames、keepFnames |
minify | boolean | 压缩输出代码 |
extractComments | boolean | 库构建压缩时将 legal comments 提取到 [file].LICENSE.txt |
treeShaking | boolean | 移除未使用代码 |
splitChunks | object | 分别配置 js / css chunk 的尺寸和数量限制 |
cssChunking | boolean | string | object | CSS chunk 分组算法 |
modularizeImports | object | 按模板转换包导入,类似 babel-plugin-import |
packageImports | string[] | 优化具有大量导出的包入口 |
transpilePackages | string[] | 转译指定依赖包 |
removeConsole | boolean | object | 移除 console 调用,可通过 exclude 保留方法 |
concatenateModules | boolean | 合并模块以减少 chunk 数量 |
removeUnusedExports | boolean | 移除未使用导出;开发环境默认关闭,生产环境默认开启 |
removeUnusedImports | boolean | 移除未使用导入;开发环境默认关闭,生产环境默认开启 |
nestedAsyncChunking | boolean | 启用嵌套异步 chunk |
wasmAsAsset | boolean | 将 WASM 内联到 bundle;默认关闭并作为静态资源输出 |
optimization.packageImports
optimization.packageImports 用于优化导出大量模块的包的具名导入。将包名加入配置后,业务代码仍可从包的根入口导入,Utoopack 只加载实际使用的模块,从而减少开发和生产构建中的模块解析与编译开销。该选项的类型为 string[],用法类似 Next.js 的 optimizePackageImports。
{
"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 使用基于图的算法,也可以通过对象调整额外请求的估算成本和权重分布。
{
"optimization": {
"cssChunking": {
"type": "graph",
"requestCost": 100000,
"weightDistribution": 0.1
}
}
}false、strict 和 { "type": "strict" } 当前不受 Utoopack 支持,使用时构建会报错。
devServer
本地仓库当前支持的字段包括 hot、dynamicHmrChunkLists、host、port、https 和 proxy。
{
"devServer": {
"hot": true,
"dynamicHmrChunkLists": true,
"host": "0.0.0.0",
"port": 3000,
"https": false,
"proxy": [
{
"context": ["/api"],
"target": "http://localhost:7001",
"changeOrigin": true,
"pathRewrite": {
"^/api": ""
}
}
]
}
}dynamicHmrChunkLists 开启后,运行时会随着动态 chunk 加载注册对应的 HMR chunk list。
server
server 配置服务端入口、Server Functions 边界和服务端 chunk 输出。entry 可以是单个入口字符串,也可以是具名入口数组;数组中的第一个入口是主服务端运行时,并接收 Server Functions。
{
"server": {
"entry": [
{
"name": "server",
"import": "./src/server.ts"
},
{
"name": "admin-server",
"import": "./src/admin.server.ts"
}
],
"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)。
高级选项
| 选项 | 类型 | 描述 |
|---|---|---|
sourceMaps | boolean | 启用 source map |
stats | boolean | 启用构建统计输出 |
nodePolyfill | boolean | 为浏览器补齐 Node.js 内置模块 |
persistentCaching | boolean | 启用持久化构建缓存,默认开启 |
turbopackMemoryEviction | boolean | auto | full | 持久缓存的内存回收模式,默认 auto;false 关闭,true 等价于 full |
swcPlugins | [string, any][] | 自定义 SWC 插件及其选项 |
pluginRuntimeStrategy | workerThreads | childProcesses | loader / plugin 使用 worker thread 或子进程运行 |
experimental | object | reactCompiler 和 swcPlugins 的兼容配置入口 |
配置文件运行时字段
这些字段属于 UserConfig,可在 utoopack.config.* 中控制构建运行过程。
| 选项 | 类型 | 描述 |
|---|---|---|
processEnv | Record<string, string> | 编译时使用的环境变量 |
watch | object | 文件监听配置 |
dev | boolean | 是否以开发模式运行 |
buildId | string | 当前构建 ID |
tracing | boolean | 是否启用默认 tracing 日志,默认开启 |
packPath | string | @utoo/pack 的绝对路径 |
projectPath | string | 项目路径 |
rootPath | string | 根路径,monorepo 中可与项目路径不同 |
watch 支持 enable、pollIntervalMs、ignored 和 nodeModulesRegexes。默认忽略 node_modules;ignored 中的 !node_modules/<regex> 或 nodeModulesRegexes 中的包名正则可以重新纳入需要监听的依赖。
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
build()
const { build } = require('@utoo/pack');
await build({
config: {
mode: "production",
entry: [{ import: "./src/index.ts" }],
output: { path: "./dist" }
}
});完整配置 schema 见 config_schema.json 。