# Vue Support Build Vue component libraries with tsdown. ## Overview tsdown provides first-class support for Vue libraries through integration with `unplugin-vue` and `rolldown-plugin-dts` for type generation. ## Quick Start ### Use Starter Template ```bash npx create-tsdown@latest -t vue ``` ## Basic Configuration ### Install Dependencies ```bash pnpm add -D unplugin-vue vue-tsc ``` ### Minimal Setup ```ts // tsdown.config.ts import { defineConfig } from 'tsdown' import Vue from 'unplugin-vue/rolldown' export default defineConfig({ entry: ['./src/index.ts'], format: ['esm', 'cjs'], platform: 'neutral', external: ['vue'], plugins: [ Vue({ isProduction: true }), ], dts: { vue: true, // Enable Vue type generation }, }) ``` ## How It Works ### unplugin-vue Compiles `.vue` single-file components: - Transforms template to render functions - Handles scoped styles - Processes script setup ### vue-tsc Generates TypeScript declarations: - Type-checks Vue components - Creates `.d.ts` files - Preserves component props types - Exports component types ## Component Example ### Single File Component ```vue ``` ### Export Components ```ts // src/index.ts export { default as Button } from './Button.vue' export { default as Input } from './Input.vue' export { default as Modal } from './Modal.vue' // Re-export types export type { ButtonProps } from './Button.vue' ``` ## Common Patterns ### Component Library ```ts export default defineConfig({ entry: ['src/index.ts'], format: ['esm', 'cjs'], platform: 'neutral', external: ['vue'], plugins: [ Vue({ isProduction: true, style: { trim: true, }, }), ], dts: { vue: true, }, clean: true, }) ``` ### Multiple Components ```ts export default defineConfig({ entry: { index: 'src/index.ts', Button: 'src/Button.vue', Input: 'src/Input.vue', Modal: 'src/Modal.vue', }, format: ['esm', 'cjs'], external: ['vue'], plugins: [Vue({ isProduction: true })], dts: { vue: true }, }) ``` ### With Composition Utilities ```ts // src/composables/useCounter.ts import { ref } from 'vue' export function useCounter(initial = 0) { const count = ref(initial) const increment = () => count.value++ const decrement = () => count.value-- return { count, increment, decrement } } ``` ```ts export default defineConfig({ entry: ['src/index.ts'], format: ['esm', 'cjs'], external: ['vue'], plugins: [Vue({ isProduction: true })], dts: { vue: true }, }) ``` ### TypeScript Configuration ```json // tsconfig.json { "compilerOptions": { "target": "ES2020", "module": "ESNext", "lib": ["ES2020", "DOM", "DOM.Iterable"], "jsx": "preserve", "moduleResolution": "bundler", "allowImportingTsExtensions": true, "strict": true, "isolatedDeclarations": true, "skipLibCheck": true }, "include": ["src"], "exclude": ["node_modules", "dist"] } ``` ### Package.json Configuration ```json { "name": "my-vue-library", "version": "1.0.0", "type": "module", "main": "./dist/index.cjs", "module": "./dist/index.mjs", "types": "./dist/index.d.ts", "exports": { ".": { "types": "./dist/index.d.ts", "import": "./dist/index.mjs", "require": "./dist/index.cjs" }, }, "files": ["dist"], "peerDependencies": { "vue": "^3.0.0" }, "devDependencies": { "tsdown": "^0.9.0", "typescript": "^5.0.0", "unplugin-vue": "^5.0.0", "vue": "^3.4.0", "vue-tsc": "^2.0.0" } } ``` ## Advanced Patterns ### With Vite Plugins Some Vite Vue plugins may work: ```ts import Vue from 'unplugin-vue/rolldown' import Components from 'unplugin-vue-components/rolldown' export default defineConfig({ entry: ['src/index.ts'], external: ['vue'], plugins: [ Vue({ isProduction: true }), Components({ dts: 'src/components.d.ts', }), ], dts: { vue: true }, }) ``` ### JSX Support ```ts export default defineConfig({ entry: ['src/index.ts'], format: ['esm', 'cjs'], external: ['vue'], plugins: [ Vue({ isProduction: true, script: { propsDestructure: true, }, }), ], inputOptions: { transform: { jsx: 'automatic', jsxImportSource: 'vue', }, }, dts: { vue: true }, }) ``` ### Monorepo Vue Packages ```ts export default defineConfig({ workspace: 'packages/*', entry: ['src/index.ts'], format: ['esm', 'cjs'], external: ['vue', /^@mycompany\//], plugins: [Vue({ isProduction: true })], dts: { vue: true }, }) ``` ## Plugin Options ### unplugin-vue Options ```ts Vue({ isProduction: true, script: { defineModel: true, propsDestructure: true, }, style: { trim: true, }, template: { compilerOptions: { isCustomElement: (tag) => tag.startsWith('custom-'), }, }, }) ``` ## Tips 1. **Always externalize Vue** - Don't bundle Vue itself 2. **Enable vue: true in dts** - For proper type generation 3. **Use platform: 'neutral'** - Maximum compatibility 4. **Install vue-tsc** - Required for type generation 5. **Set isProduction: true** - Optimize for production 6. **Add peer dependency** - Vue as peer dependency ## Troubleshooting ### Type Generation Fails Ensure vue-tsc is installed: ```bash pnpm add -D vue-tsc ``` Enable in config: ```ts dts: { vue: true } ``` ### Component Types Missing Check TypeScript config: ```json { "compilerOptions": { "jsx": "preserve", "moduleResolution": "bundler" } } ``` ### Vue Not Externalized Add to external: ```ts external: ['vue'] ``` ### SFC Compilation Errors Check unplugin-vue version: ```bash pnpm add -D unplugin-vue@latest ``` ## Related - [Plugins](advanced-plugins.md) - Plugin system - [Dependencies](option-dependencies.md) - External packages - [DTS](option-dts.md) - Type declarations - [React Recipe](recipe-react.md) - React component libraries