如何让Vite通过脚本生成嵌套模块并正确处理外部依赖?
解决Vite脚本批量构建库的两个问题
1. 保留嵌套目录结构生成产物
当前代码里entryFileNames: '[name].mjs'会丢失路径前缀——因为Rollup的[name]占位符默认只提取文件名(不含目录层级)。要生成build/parent/lib.mjs这种嵌套结构,只需修改entryFileNames,直接用原始模块名替换后缀即可:
entryFileNames: `${name.replace('.ts', '.mjs')}`
这样入口parent/lib.ts就会生成releases/tmp/parent/lib.mjs,自动保留原有的目录层级。
2. 让external正确识别嵌套依赖
Rollup的external默认匹配的是模块ID而非文件路径,直接传入libs数组可能无法匹配代码中的导入路径。可以改用函数形式的external,对导入路径做归一化处理后再判断:
首先把libs转换成绝对路径集合,方便后续匹配:
const libPaths = new Set(libs.map(name => path.resolve(__dirname, '..', name)))
然后在rollupOptions.external中使用匹配函数:
external: (source) => { // 将导入路径转为绝对路径,再判断是否属于外部依赖集合 const resolvedSource = path.resolve(process.cwd(), source) return libPaths.has(resolvedSource) }
修改后的完整代码
import path from 'path' import { build } from 'vite' // libs const libs = ['parent/lib.ts'] // 转换为绝对路径集合,用于external匹配 const libPaths = new Set(libs.map(name => path.resolve(__dirname, '..', name))) libs .map(name => [name, path.resolve(__dirname, '..', name)]) .forEach(async ([name, entry]) => { await build({ configFile: false, build: { target: "esnext", emptyOutDir: false, minify: false, lib: { entry, name, formats: ['es'] }, rollupOptions: { external: (source) => { const resolvedSource = path.resolve(process.cwd(), source) return libPaths.has(resolvedSource) }, output: { entryFileNames: `${name.replace('.ts', '.mjs')}`, dir: 'releases/tmp' } } } }) })
补充说明
如果代码中使用相对路径导入(比如import '../parent/lib.ts'),path.resolve(process.cwd(), source)会自动解析为绝对路径,和libPaths中的路径完成匹配;若需支持不带后缀的导入,可在匹配函数中给resolvedSource补充.ts等后缀后再判断。
内容的提问来源于stack exchange,提问作者Alex Craft
相关产品推荐
相关产品推荐

