在 Webpack 的产物优化环节中,optimization.splitChunks 是绕不开的配置。大多数人会把精力放在 chunks、maxInitialRequests 这些参数上,却很少有人注意到 automaticNameDelimiter 这个看似不起眼的字段。当你在构建多页应用或者抽取异步公共模块时,如果发现产物里出现了类似 vendors~main~detail.js 这样的文件名,中间那个波浪线就是 automaticNameDelimiter 的默认值在发挥作用。理解它的工作机制,对于控制产物命名、维护长期缓存以及排查模块归属问题都有实际意义。

automaticNameDelimiter 到底控制什么
先明确它的位置:automaticNameDelimiter 是 optimization.splitChunks 下的一个子配置项,作用范围仅限于「自动生成 chunk 名称」的场景。当 splitChunks 按照规则把若干模块抽取到一个新 chunk 中时,Webpack 需要给这个新 chunk 起名字。如果这个 chunk 由多个来源共同组成,比如同时服务于 main 和 detail 两个入口,Webpack 就会把所有相关 chunk 的名字拼接起来,中间用 automaticNameDelimiter 指定的字符连接。
默认值是波浪线 ~,所以你会看到 vendors~main.js、default~main~detail~runtime 这类名字。这个拼接逻辑发生在 Webpack 内部的 SplitChunksPlugin 中,最终通过 chunk.name 影响 output 阶段的文件命名。需要注意的是,只有当 chunk 名称是被自动推导出来的(也就是你没有显式指定 name 或者 name 未配置)时,这个分隔符才会生效。如果你给某组缓存组显式写了 name: 'vendor',那么产物就叫 vendor.js,拼接逻辑完全不参与。
一个容易混淆的点:有人以为 output.filename 里的中划线或点号也和它有关,其实两者互不相干。automaticNameDelimiter 只管名字内部的连接符,而 output.filename 里的 [name].[contenthash].js 决定的是文件名的整体骨架。
如何自定义分隔符及配置示例
修改方式很简单,直接在 splitChunks 配置中传入字符串即可。常见的做法是改成中划线 -,让产物名和团队现有的命名规范保持一致。下面是一份典型配置:
module.exports = {
optimization: {
splitChunks: {
chunks: 'all',
// 自动生成的 chunk 名称中,各部分之间用中划线连接
automaticNameDelimiter: '-',
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
// 注意:这里没有写 name,走自动命名
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
},
},
},
},
};
这份配置生效后,原本的 vendors~main.js 会变成 vendors-main.js。要注意 cacheGroups.vendors 里刻意没有写 name 字段——一旦写了,自动命名机制就不会触发,分隔符自然也没有用武之地。这是实践中最常见的失效原因:配置了 automaticNameDelimiter 却发现没效果,九成是因为缓存组里显式指定了 name。
另外,当你把 chunks 设为 'all' 并依赖自动命名时,同一个缓存组可能拆出多个 chunk,名字会带上入口信息,例如 vendors-main-detail.js。分隔符越短越干净,尽量避免使用 _ 以外的特殊字符,某些构建工具链(比如老版本的某些 CDN 或 Windows 文件系统对特殊字符的处理)可能出现兼容问题。中划线 - 和下划线 _ 是最稳妥的两个选择。
修改分隔符的连带影响与排查思路
改分隔符不是改个符号那么简单,它会带来两方面的连带影响。第一是缓存失效:文件名变了,[contenthash] 虽然由内容决定,但整个 URL 路径变了,已经发布的 HTML 里引用的旧地址会全部失效,所以最好配合一次性的缓存清理或者版本切换来发布。第二是 Runtime 对应关系:如果你使用 optimization.runtimeChunk,Runtime chunk 里维护的 chunk id 与名称映射在分隔符变更后需要整体重新构建,混合新旧产物可能导致模块加载失败,报出「ChunkLoadError」之类的错误。
排查相关问题时可以按这个思路走:先用 webpack --json 或者 webpack-bundle-analyzer 查看每个 chunk 的最终名称和模块构成,确认拼接结果是否符合预期;再检查 cacheGroups 里有没有显式 name 覆盖了自动命名;最后看 output.filename 与 output.chunkFilename 的模板是否把 [name] 放在了预期位置。一个典型的完整示例如下:
const path = require('path');
module.exports = {
entry: {
main: './src/main.js',
detail: './src/detail.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'js/[name].[contenthash:8].js',
chunkFilename: 'js/[name].[contenthash:8].js',
},
optimization: {
runtimeChunk: 'single',
splitChunks: {
chunks: 'all',
automaticNameDelimiter: '-',
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
},
},
},
},
};
按上面配置构建后,你会得到 js/runtime-xxxx.js、js/main-xxxx.js 以及公共部分自动命名为 js/vendors-main-detail-xxxx.js 之类的产物。整体来说,automaticNameDelimiter 是个小而美的配置点:它不改变拆分行为本身,只影响产物的可读性命名。把它和 name 的显隐关系、缓存发布策略结合起来理解,才能真正让构建产物既整洁又稳定。
WebpacksplitChunksautomaticNameDelimiter修改时间:2026-09-15 10:24:34