如何配置Vite的Rollup实现主项目与Widgets独立打包
Vite + Rollup 配置实现指定dist目录结构
问题背景
已有可正常构建的Vue项目,原Vite配置片段如下:
build: { rollupOptions: { output: { manualChunks: { mapboxGl: ['mapbox-gl'] } } }, sourcemap: 'hidden', }, plugins: [ vue(), svgLoader() ],
项目新增src/widgets目录存放独立组件,期望构建后dist目录结构为:
dist/ ├── index.html ├── assets/ │ └── ...项目相关资源 └── widgets/ └── 每个widget的构建产物(bundle + CSS)
修改Rollup输入配置后出现两个问题:
- 主项目的
index.html未生成 widgets目录被打包到assets文件夹内
解决方案
调整Vite的build配置,同时处理入口文件、输出路径和HTML生成逻辑:
完整配置代码
import { fileURLToPath, URL } from 'node:url' import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import svgLoader from 'vite-svg-loader' import globSync from 'glob' import { relative, extname } from 'node:path' export default defineConfig({ plugins: [vue(), svgLoader()], build: { sourcemap: 'hidden', rollupOptions: { input: { // 主项目入口关联index.html,确保生成根目录的index.html main: fileURLToPath(new URL('./index.html', import.meta.url)), // 遍历widgets下的所有入口文件,保留原有路径结构 ...Object.fromEntries( globSync('src/widgets/**/*.ts').map(file => [ relative('src', file.slice(0, file.length - extname(file).length)), fileURLToPath(new URL(file, import.meta.url)) ]) ) }, output: { // 自定义入口文件输出路径 entryFileNames: chunkInfo => { return chunkInfo.name.startsWith('widgets/') ? 'widgets/[name].js' : 'assets/[name]-[hash].js'; }, // 公共chunk统一放到assets chunkFileNames: 'assets/[name]-[hash].js', // 自定义资源文件输出路径(区分widgets和主项目的CSS等) assetFileNames: assetInfo => { return assetInfo.name?.startsWith('widgets/') ? 'widgets/[name][extname]' : 'assets/[name]-[hash][extname]'; }, manualChunks: { mapboxGl: ['mapbox-gl'] } } } } })
配置关键说明
入口调整:
- 主项目入口改为
index.html而非main.ts,让Vite正常生成根目录的index.html并处理主项目依赖打包 - 保留widgets目录下的ts文件作为额外入口,维持原路径转换逻辑以保留widgets内部的目录结构
- 主项目入口改为
输出路径区分:
- 通过
entryFileNames和assetFileNames的条件判断,将widgets相关的入口文件、CSS等资源单独输出到dist/widgets/目录 - 主项目资源和公共chunk仍输出到
dist/assets/目录
- 通过
验证效果
构建完成后,dist目录会完全符合预期:
- 根目录存在主项目的
index.html assets/存放主项目所有资源及公共chunkwidgets/下保留原有的子目录结构,每个widget对应的js、css文件都在对应路径下
内容的提问来源于stack exchange,提问作者vladys.bo
相关产品推荐
相关产品推荐

