| | |

Vite 13 ⚡ Framework Plugins — React, Vue & Svelte integrations

⏱️ Estimated read: 10 min | |

Vite is framework-agnostic at its core. The framework-specific features—Fast Refresh for React, Single File Component compilation for Vue, and the Svelte compiler integration—are provided by official plugins that sit in the plugins array alongside any Rollup plugins. Each plugin wraps the framework’s compiler and wires it into Vite’s transform pipeline, dev server, and production build. The plugins are the reason a React project, a Vue project, and a Svelte project can all use the same Vite config file structure while getting framework-specific HMR and build behavior.

This chapter covers the three official framework plugins: @vitejs/plugin-react and its SWC variant, @vitejs/plugin-vue, and @sveltejs/vite-plugin-svelte. It explains the installation, the core options, and the framework-specific behavior each plugin injects.

Key point: The framework plugin is what makes HMR work for the framework’s components. @vitejs/plugin-react enables Fast Refresh, @vitejs/plugin-vue compiles SFCs into virtual modules, and @sveltejs/vite-plugin-svelte runs the Svelte compiler. Without the plugin, the framework’s component syntax is not transformed, and the dev server cannot apply updates at the component level.


Why framework plugins exist

The transform problem. Vite’s core transform handles JavaScript, TypeScript, CSS, and assets. It does not know how to compile a .vue file, which contains a <script>, a <template>, and a <style> block that each need separate compilation. It does not know how to inject the React Fast Refresh runtime into a module that exports a component. The framework plugin is the component that adds this knowledge to Vite’s pipeline.

The HMR problem. Generic HMR works at the module level. If a module changes, the module is replaced. For a framework component, the desired behavior is more specific: preserve the component’s state, re-render only the changed component, and update the styles without a reload. The framework plugin implements the HMR boundary that makes this possible. @vitejs/plugin-react injects the Fast Refresh runtime , @vitejs/plugin-vue splits the SFC into virtual modules that can be updated independently , and @sveltejs/vite-plugin-svelte handles the component update with a documented state-preservation caveat .

The production problem. During development, the plugin uses the fastest available transformer. During production, it uses the framework’s full compiler to produce the optimized output. @vitejs/plugin-react uses Oxc for the transform and only invokes Babel when custom plugins are configured . This distinction is why the plugin is fast in development and correct in production.


a. React: @vitejs/plugin-react

The React plugin is installed as a dev dependency and added to the plugins array.

// vite.config.js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
})

The plugin enables Fast Refresh in development, uses the automatic JSX runtime, and supports custom Babel plugins and presets . The include and exclude options control which files the plugin processes; the default includes .js, .jsx, .ts, and .tsx, and excludes node_modules . The jsxImportSource option points the JSX factory at a different library, such as @emotion/react. The jsxRuntime option can revert to the classic runtime when the automatic runtime causes issues . The babel option adds plugins and presets to the Babel transform, but when no Babel plugins are configured, only Oxc is used for production builds, which keeps the build fast .

For projects that need SWC instead of Oxc, @vitejs/plugin-react-swc replaces the transformer during development. The Vite documentation notes that for large projects that require custom plugins, cold start and HMR can be significantly faster if the plugin is also available for SWC . The SWC variant does not support the same Babel plugin configuration.

A third React plugin, @vitejs/plugin-rsc, provides React Server Components support through Vite’s Environment API. It is a lower-level primitive intended for frameworks, and a minimal standalone RSC application can be created with npm create vite@latest -- --template rsc .


b. Vue: @vitejs/plugin-vue

The Vue plugin compiles Vue 3 Single File Components. It is installed and added to the plugins array.

// vite.config.js
import vue from '@vitejs/plugin-vue'

export default {
  plugins: [vue()],
}

The plugin converts the asset URLs inside the <template> block into ESM imports, so an <img src="../image.png"> in the template becomes an imported module . The features option controls the compiler behavior: propsDestructure enables reactive destructure for defineProps, customElement transforms matched SFCs into custom elements, and optionsAPI can be set to false to drop the Options API support and reduce the production bundle . The script, template, and style options pass lower-level compiler options to the corresponding vue/compiler-sfc APIs .

For JSX and TSX support in Vue, the separate @vitejs/plugin-vue-jsx plugin is required . The Vue 2.7 line uses @vitejs/plugin-vue2 and its JSX variant .


c. Svelte: @sveltejs/vite-plugin-svelte

The Svelte plugin runs the Svelte compiler and reads the project’s svelte.config.js automatically.

// vite.config.js
import { svelte } from '@sveltejs/vite-plugin-svelte'

export default defineConfig({
  plugins: [svelte()],
})

The plugin merges options from three sources in order: the plugin defaults, the svelte.config.js file in the Vite root, and the inline options passed to the plugin . The compilerOptions, preprocess, extensions, and onwarn options are passed to the Svelte compiler. The preprocess option accepts a preprocessor group, such as svelte-preprocess for TypeScript support .

A known limitation: third-party Svelte libraries that use the lifecycle API (onMount, setContext) must be added to optimizeDeps.exclude in the Vite config. Vite’s dependency pre-bundling does not deduplicate the Svelte instance, and multiple instances cause errors like “Function called outside component initialization” . The plugin documentation also notes that local component state is not preserved on HMR updates for JS changes, to avoid unpredictable behavior; style-only updates do preserve state .


Complete Example Session

// ============================================
// PART 1: REACT PLUGIN
// ============================================
// vite.config.js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
})
// ============================================
// PART 2: REACT PLUGIN OPTIONS
// ============================================
react({
  include: /\.(mdx|js|jsx|ts|tsx)$/,
  jsxImportSource: '@emotion/react',
  babel: {
    plugins: ['babel-plugin-react-compiler'],
  },
})
// ============================================
// PART 3: REACT SWC VARIANT
// ============================================
import react from '@vitejs/plugin-react-swc'

export default defineConfig({
  plugins: [react()],
})
// ============================================
// PART 4: VUE PLUGIN
// ============================================
// vite.config.js
import vue from '@vitejs/plugin-vue'

export default {
  plugins: [vue()],
}
// ============================================
// PART 5: VUE PLUGIN OPTIONS
// ============================================
vue({
  features: {
    propsDestructure: true,
    optionsAPI: false,
  },
  template: {
    compilerOptions: {
      isCustomElement: (tag) => tag.startsWith('my-'),
    },
  },
})
// ============================================
// PART 6: VUE JSX
// ============================================
import vueJsx from '@vitejs/plugin-vue-jsx'

export default {
  plugins: [vue(), vueJsx()],
}
// ============================================
// PART 7: SVELTE PLUGIN
// ============================================
import { svelte } from '@sveltejs/vite-plugin-svelte'

export default defineConfig({
  plugins: [svelte()],
})
// ============================================
// PART 8: SVELTE CONFIG FILE
// ============================================
// svelte.config.js
export default {
  preprocess: [sveltePreprocess({ typescript: true })],
  compilerOptions: {},
}
// ============================================
// PART 9: SVELTE DEP EXCLUSION
// ============================================
export default defineConfig({
  plugins: [svelte()],
  optimizeDeps: {
    exclude: ['svelte-library'],
  },
})
// ============================================
// PART 10: THE COMPLETE REACT CONFIG
// ============================================
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [
    react({
      jsxImportSource: '@emotion/react',
    }),
  ],
})

The ten parts covered the React plugin, its options, the SWC variant, the Vue plugin, its options, Vue JSX, the Svelte plugin, the Svelte config file, the dependency exclusion, and the complete React config.


Quick Reference

Framework plugins

FrameworkPluginPurpose
React@vitejs/plugin-reactFast Refresh, JSX, Babel
React (SWC)@vitejs/plugin-react-swcSWC-based Fast Refresh
React (RSC)@vitejs/plugin-rscReact Server Components
Vue 3@vitejs/plugin-vueSFC compilation
Vue 3 JSX@vitejs/plugin-vue-jsxJSX/TSX support
Vue 2.7@vitejs/plugin-vue2Vue 2 SFC compilation
Svelte@sveltejs/vite-plugin-svelteSvelte compiler

React plugin options

OptionDefaultPurpose
include.js, .jsx, .ts, .tsxFiles to process
jsxImportSourcereactJSX factory source
jsxRuntimeautomaticJSX runtime
babel—Babel plugins/presets
reactRefreshHost—Module federation HMR

Vue plugin options

OptionDefaultPurpose
features.propsDestructurefalse (Vue 3.4), true (3.5+)Reactive defineProps destructure
features.customElement/\.ce\.vue$/Custom element mode
features.optionsAPItrueDrop Options API in production
script/template/style—Compiler options

Svelte plugin options

OptionDefaultPurpose
preprocess—Preprocessor groups
compilerOptions—Svelte compiler options
extensions['.svelte']File extensions
onwarn—Warning handler
configFilesvelte.config.jsConfig file path

Best Practices

✅ Do This:

// Install the plugin as a dev dependency
npm install -D @vitejs/plugin-react                       // ✅
// Add the plugin to the plugins array
plugins: [react()]                                          // ✅
// Use the SWC variant for large React projects
plugins: [react({ plugins: [] })]  // @vitejs/plugin-react-swc // ✅
// Exclude Svelte libraries that use lifecycle APIs
optimizeDeps: { exclude: ['svelte-library'] }               // ✅

❌ Don’t Do This:

// Use a framework plugin without installing it
plugins: [react()]  // ❌ (module not found)
// Use @vitejs/plugin-vue for Vue 2.7
plugins: [vue()]  // ❌ (use @vitejs/plugin-vue2)
// Assume Svelte state is preserved on JS HMR
// It is not preserved by design                              // ❌

Common Pitfalls

PitfallWhy It HappensFix
React Fast Refresh not workingPlugin not installed or not in pluginsAdd react() to the array
createContext error in ReactPlugin version mismatchUpdate @vitejs/plugin-react
Vue SFC not compiledPlugin missingAdd vue() to the array
Vue JSX not working@vitejs/plugin-vue-jsx not installedInstall and add the JSX plugin
Svelte lifecycle errorMultiple Svelte instancesAdd the library to optimizeDeps.exclude
Svelte state reset on HMRDesign limitation for JS updatesStyle-only updates preserve state

Real-World Examples

1. React plugin

plugins: [react()]

2. React with Emotion

plugins: [react({ jsxImportSource: '@emotion/react' })]

3. React SWC

plugins: [react()]  // from @vitejs/plugin-react-swc

4. Vue plugin

plugins: [vue()]

5. Vue with Options API dropped

plugins: [vue({ features: { optionsAPI: false } })]

6. Vue JSX

plugins: [vue(), vueJsx()]

7. Svelte plugin

plugins: [svelte()]

8. Svelte with preprocessor

plugins: [svelte({ preprocess: [sveltePreprocess()] })]

9. Svelte dep exclusion

optimizeDeps: { exclude: ['svelte-library'] }

10. The complete Vue config

import vue from '@vitejs/plugin-vue'
export default { plugins: [vue()] }

Visual

The framework plugin pipeline

┌─────────────────────────────────────────────────────────────┐
│  Vite core transform                                         │
│       │                                                      │
│       ▼                                                      │
│  Framework plugin                                            │
│    ├── React: Fast Refresh + JSX                             │
│    ├── Vue: SFC compiler                                     │
│    └── Svelte: Svelte compiler                               │
│       │                                                      │
│       ▼                                                      │
│  Module graph with framework-specific HMR boundaries         │
└─────────────────────────────────────────────────────────────┘

React Fast Refresh

┌─────────────────────────────────────────────────────────────┐
│  @vitejs/plugin-react                                        │
│    ├── injects Fast Refresh runtime                          │
│    ├── uses automatic JSX runtime                            │
│    └── uses Oxc for transform                                │
│                                                              │
│  Component changes ──► state preserved ──► re-render         │
└─────────────────────────────────────────────────────────────┘

Vue SFC compilation

┌─────────────────────────────────────────────────────────────┐
│  Component.vue                                               │
│    ├── <script> ──► JS module                                │
│    ├── <template> ──► render function                        │
│    └── <style> ──► CSS module                                │
│                                                              │
│  @vitejs/plugin-vue splits and compiles each block.          │
└─────────────────────────────────────────────────────────────┘

Svelte config resolution

┌─────────────────────────────────────────────────────────────┐
│  vite-plugin-svelte defaults                                 │
│       │                                                      │
│       ▼                                                      │
│  svelte.config.js in Vite root                               │
│       │                                                      │
│       ▼                                                      │
│  inline options in vite.config.js                            │
│                                                              │
│  Later sources override earlier ones.                        │
└─────────────────────────────────────────────────────────────┘

Summary

ItemValue
React plugin@vitejs/plugin-react
React SWC variant@vitejs/plugin-react-swc
React RSC plugin@vitejs/plugin-rsc
Vue plugin@vitejs/plugin-vue
Vue JSX plugin@vitejs/plugin-vue-jsx
Svelte plugin@sveltejs/vite-plugin-svelte
Svelte config filesvelte.config.js (auto-resolved)
Svelte dep exclusionoptimizeDeps.exclude for lifecycle libraries

Key takeaways:

  • The framework plugin is what makes the framework’s component syntax work in Vite. Vite’s core transform does not know how to compile a Vue SFC or inject the React Fast Refresh runtime. The plugin adds that knowledge to the transform pipeline.
  • @vitejs/plugin-react enables Fast Refresh and uses Oxc for the transform. The babel option adds custom Babel plugins when needed, but without them only Oxc is used, which keeps the build fast . The @vitejs/plugin-react-swc variant replaces Oxc with SWC for faster cold start and HMR in large projects .
  • @vitejs/plugin-vue compiles SFCs and converts template asset URLs into ESM imports. The features option controls the compiler behavior, including propsDestructure, customElement, and optionsAPI. The @vitejs/plugin-vue-jsx plugin is required for JSX support .
  • @sveltejs/vite-plugin-svelte runs the Svelte compiler and reads svelte.config.js automatically. The options are merged from the plugin defaults, the config file, and the inline options, in that order . The preprocess option accepts preprocessor groups for TypeScript and other languages .
  • Svelte libraries that use lifecycle APIs must be excluded from dependency pre-bundling. Vite’s pre-bundling does not deduplicate the Svelte instance, and multiple instances cause runtime errors. The optimizeDeps.exclude array is the fix .
  • Svelte local component state is not preserved on HMR for JS updates. The plugin disables state preservation to avoid unpredictable behavior. Style-only updates do preserve state .

Remember: A framework plugin is not optional for a framework project. It is the component that compiles the framework’s component format, injects the framework’s HMR runtime, and produces the optimized production output. React uses @vitejs/plugin-react (or the SWC variant), Vue uses @vitejs/plugin-vue (plus @vitejs/plugin-vue-jsx for JSX), and Svelte uses @sveltejs/vite-plugin-svelte. Each plugin has its own options, its own config file conventions, and its own limitations. Install the plugin, add it to the plugins array, and read its options when the default behavior does not match the project’s needs.

Was this helpful?


Stop using slow, ad-bloated tool sites! 🤮

🔎 Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)

⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free

🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!