# React Support Build React component libraries with tsdown. ## Overview tsdown provides first-class support for React libraries. Rolldown natively supports JSX/TSX, so no additional plugins are required for basic React components. ## Quick Start ### Use Starter Template ```bash # Basic React library npx create-tsdown@latest -t react # With React Compiler npx create-tsdown@latest -t react-compiler ``` ## Basic Configuration ### Minimal Setup ```ts // tsdown.config.ts export default defineConfig({ entry: ['./src/index.ts'], format: ['esm', 'cjs'], platform: 'neutral', external: ['react', 'react-dom'], dts: true, }) ``` ### Component Example ```tsx // src/MyButton.tsx import React from 'react' interface MyButtonProps { type?: 'primary' | 'secondary' onClick?: () => void } export const MyButton: React.FC = ({ type = 'primary', onClick }) => { return ( ) } ``` ```ts // src/index.ts export { MyButton } from './MyButton' ``` ## JSX Transform ### Automatic (Default) Modern JSX transform (React 17+): ```ts export default defineConfig({ entry: ['src/index.tsx'], // Automatic JSX is default }) ``` **Characteristics:** - No `import React` needed - Smaller bundle size - React 17+ required ### Classic Legacy JSX transform: ```ts export default defineConfig({ entry: ['src/index.tsx'], inputOptions: { transform: { jsx: 'react', // Classic transform }, }, }) ``` **Characteristics:** - Requires `import React from 'react'` - Compatible with older React versions ## React Compiler React Compiler automatically optimizes React code at build time. ### Install Dependencies ```bash pnpm add -D @rollup/plugin-babel babel-plugin-react-compiler ``` ### Configure ```ts import pluginBabel from '@rollup/plugin-babel' export default defineConfig({ entry: ['src/index.tsx'], format: ['esm', 'cjs'], external: ['react', 'react-dom'], plugins: [ pluginBabel({ babelHelpers: 'bundled', parserOpts: { sourceType: 'module', plugins: ['jsx', 'typescript'], }, plugins: ['babel-plugin-react-compiler'], extensions: ['.js', '.jsx', '.ts', '.tsx'], }), ], dts: true, }) ``` ## Common Patterns ### Component Library ```ts export default defineConfig({ entry: ['src/index.ts'], format: ['esm', 'cjs'], platform: 'neutral', external: [ 'react', 'react-dom', /^react\//, // react/jsx-runtime, etc. ], dts: true, clean: true, }) ``` ### Multiple Components ```ts export default defineConfig({ entry: { index: 'src/index.ts', Button: 'src/Button.tsx', Input: 'src/Input.tsx', Modal: 'src/Modal.tsx', }, format: ['esm', 'cjs'], external: ['react', 'react-dom'], dts: true, }) ``` ### Hooks Library ```ts export default defineConfig({ entry: ['src/index.ts'], format: ['esm', 'cjs'], platform: 'neutral', external: ['react'], // Only React needed dts: true, treeshake: true, }) ``` ### Monorepo React Packages ```ts export default defineConfig({ workspace: 'packages/*', entry: ['src/index.ts'], format: ['esm', 'cjs'], external: [ 'react', 'react-dom', /^@mycompany\//, // Other workspace packages ], dts: true, }) ``` ## TypeScript Configuration ### Recommended tsconfig.json ```json { "compilerOptions": { "target": "ES2020", "module": "ESNext", "lib": ["ES2020", "DOM", "DOM.Iterable"], "jsx": "react-jsx", // or "react" for classic "moduleResolution": "bundler", "allowImportingTsExtensions": true, "strict": true, "isolatedDeclarations": true, // Fast DTS generation "skipLibCheck": true }, "include": ["src"] } ``` ## Package.json Configuration ```json { "name": "my-react-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": { "react": "^18.0.0", "react-dom": "^18.0.0" }, "devDependencies": { "@types/react": "^18.0.0", "@types/react-dom": "^18.0.0", "react": "^18.0.0", "react-dom": "^18.0.0", "tsdown": "^0.9.0", "typescript": "^5.0.0" } } ``` ## Advanced Patterns ### With Fast Refresh (Development) ```ts import react from '@vitejs/plugin-react' export default defineConfig((options) => ({ entry: ['src/index.ts'], format: ['esm'], external: ['react', 'react-dom'], plugins: options.watch ? [ // @ts-expect-error Vite plugin react({ fastRefresh: true }), ] : [], })) ``` ## Tips 1. **Always externalize React** - Don't bundle React/ReactDOM 2. **Use automatic JSX** - Smaller bundles with React 17+ 3. **Enable DTS generation** - TypeScript support essential 4. **Use platform: 'neutral'** - For maximum compatibility 5. **Add peer dependencies** - Let users provide React 6. **Enable tree shaking** - Reduce bundle size 7. **Use React Compiler** - Better runtime performance ## Troubleshooting ### React Hook Errors Ensure React is externalized: ```ts external: ['react', 'react-dom', /^react\//] ``` ### Type Errors with JSX Check `tsconfig.json`: ```json { "compilerOptions": { "jsx": "react-jsx" // or "react" } } ``` ### Duplicate React Add to external patterns: ```ts external: [ 'react', 'react-dom', 'react/jsx-runtime', 'react/jsx-dev-runtime', ] ``` ## Related - [Plugins](advanced-plugins.md) - Extend functionality - [Dependencies](option-dependencies.md) - External packages - [DTS](option-dts.md) - Type declarations - [Vue Recipe](recipe-vue.md) - Vue component libraries