如何用Rollup为每个Vue 3组件生成单独的TypeScript定义文件?
问题描述
我在React.js项目中使用当前Rollup配置时,能为每个React组件生成对应的TypeScript定义文件;但将该配置用于Vue 3项目时,生成的dist目录并未实现此效果。请问如何修改配置以实现为每个Vue 3组件生成单独的TypeScript定义文件?
现有Rollup配置(rollup.config.js)
import resolve from "@rollup/plugin-node-resolve"; import filesize from "rollup-plugin-filesize"; import typescript from "@rollup/plugin-typescript"; import vue from "rollup-plugin-vue"; const packageJson = require("./package.json"); export default [ { input: "./index.ts", output: [ { file: packageJson.main, format: "cjs", sourcemap: true, }, { file: packageJson.module, format: "esm", sourcemap: true, }, ], plugins: [ resolve(), vue(), typescript({ tsconfig: "./tsconfig.json" }), filesize(), ], external: ["vue"], }, ];
现有tsconfig.json配置
{ "compilerOptions": { "target": "ESNext", "jsx": "preserve", "module": "ESNext", "moduleResolution": "node", "baseUrl": ".", "typeRoots": [ "../../node_modules/@types", "./shims-vue.d.ts" ], "declaration": true, "emitDeclarationOnly": true, "sourceMap": true, "outDir": "dist", "declarationDir": "types", "allowSyntheticDefaultImports": true, "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true, "skipLibCheck": true, }, "include": ["./components", "./**/*.ts", "./**/*.d.ts"], "exclude": ["**/node_modules"] }
目录对比
- Vue项目生成的dist目录:

- React项目生成的dist目录(可生成组件定义文件):

解决方案
Vue组件的TypeScript定义生成需要额外处理.vue文件的类型解析,以下是具体修改步骤:
1. 调整tsconfig.json配置
typeRoots用于指定类型包目录,不要直接放入.d.ts文件,将./shims-vue.d.ts移至include数组- 新增
.vue文件到include规则,确保TypeScript能解析Vue组件 - 修改
declarationDir为dist/types,让定义文件直接输出到dist目录下,对齐React项目结构
修改后的tsconfig.json:
{ "compilerOptions": { "target": "ESNext", "jsx": "preserve", "module": "ESNext", "moduleResolution": "node", "baseUrl": ".", "typeRoots": [ "../../node_modules/@types" ], "declaration": true, "emitDeclarationOnly": false, "sourceMap": true, "outDir": "dist", "declarationDir": "dist/types", "allowSyntheticDefaultImports": true, "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "strict": true, "skipLibCheck": true, "declarationMap": true }, "include": ["./components", "./**/*.ts", "./**/*.d.ts", "./**/*.vue"], "exclude": ["**/node_modules"] }
2. 升级Rollup插件并添加Vue类型处理
首先安装依赖:
npm install vue-tsc @vitejs/plugin-vue --save-dev
然后修改rollup.config.js,添加自定义插件处理Vue组件的类型声明:
import resolve from "@rollup/plugin-node-resolve"; import filesize from "rollup-plugin-filesize"; import typescript from "@rollup/plugin-typescript"; import vue from "@vitejs/plugin-vue"; import { compileFile } from "vue-tsc"; import fs from "fs"; import path from "path"; const packageJson = require("./package.json"); // 自定义插件:为每个Vue组件生成类型声明文件 const vueTypeDeclaration = () => { return { name: "vue-type-declaration", async generateBundle(options) { // 遍历所有Vue组件文件 const vueFiles = []; const walkDir = (dir) => { const files = fs.readdirSync(dir); files.forEach(file => { const fullPath = path.join(dir, file); if (fs.statSync(fullPath).isDirectory()) { walkDir(fullPath); } else if (fullPath.endsWith(".vue")) { vueFiles.push(fullPath); } }); }; walkDir("./components"); // 生成对应d.ts文件 for (const file of vueFiles) { const outputPath = path.join(options.dir || "", "types", path.relative(".", file).replace(".vue", ".d.ts")); const result = await compileFile(file, { declaration: true, emitDeclarationOnly: true, outDir: path.dirname(outputPath) }); if (result?.outputFiles) { fs.mkdirSync(path.dirname(outputPath), { recursive: true }); result.outputFiles.forEach(outputFile => { fs.writeFileSync(outputPath, outputFile.text); }); } } } }; }; export default [ { input: "./index.ts", output: [ { file: packageJson.main, format: "cjs", sourcemap: true, }, { file: packageJson.module, format: "esm", sourcemap: true, }, ], plugins: [ resolve(), vue(), typescript({ tsconfig: "./tsconfig.json" }), vueTypeDeclaration(), filesize(), ], external: ["vue"], }, ];
3. 调整入口文件index.ts
确保入口文件导出每个Vue组件,让TypeScript能追踪到组件的导出类型:
export { default as ComponentA } from './components/ComponentA.vue'; export { default as ComponentB } from './components/ComponentB.vue'; // 其他组件依次导出
4. 执行构建
运行构建命令后,dist目录下会生成types文件夹,其中包含每个Vue组件对应的.d.ts文件,实现和React项目一致的类型文件输出效果。
内容的提问来源于stack exchange,提问作者Morteza Sabihi
相关产品推荐
相关产品推荐

