You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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目录:
    Vue项目dist目录
  • React项目生成的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 22:45:42