小举人 Manuals

↑↓ to choose Enter to open Esc to close

Vite Plugins

Vite plugins I use day to day: auto-import, components, pages, layouts and more.

4 min read
On this page

Here are some of the Vite plugins I use day to day.

#unplugin-auto-import

Automatically imports Vue 3 APIs. Supports auto-importing from vue, vue-router, vue-i18n, @vueuse/head, @vueuse/core and more.

What it looks like

// Before
import { ref, computed } from 'vue'
const count = ref(0)
const doubled = computed(() => count.value * 2)

// After
const count = ref(0)
const doubled = computed(() => count.value * 2)

// Before
import { useState } from 'react'
export function Counter() {
  const [count, setCount] = useState(0)
  return <div>{count}</div>
}

// After
export function Counter() {
  const [count, setCount] = useState(0)
  return <div>{count}</div>
}

Install

npm i -D unplugin-auto-import

Full configuration

import { defineConfig } from 'vite'
import AutoImport from 'unplugin-auto-import/vite'

export default defineConfig({
  plugins: [
    AutoImport({
      imports: ['vue', 'vue-router', 'vue-i18n', '@vueuse/head', '@vueuse/core'],
      dts: 'src/auto-import.d.ts',
      // You can choose where auto-import.d.ts is generated (the root directory by default). I recommend setting it to 'src/auto-import.d.ts'
    }),
  ],
})

How it works: it automatically generates an auto-imports.d.ts file for code hints, like this

// Generated by 'unplugin-auto-import'
// We suggest you to commit this file into source control
declare global {
  const ref: typeof import('vue')['ref']
  const reactive: typeof import('vue')['reactive']
  const computed: typeof import('vue')['computed']
  const createApp: typeof import('vue')['createApp']
  const watch: typeof import('vue')['watch']
  const customRef: typeof import('vue')['customRef']
  const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
}
export {}

caution Note that since there are no local imports, "go to definition" jumps to auto-imports.d.ts first, and then to the original definition.

#Reactivity syntax sugar

Reactivity Transform | Vue.js (vuejs.org)

With $ref, you don't need .value when you use it. Here's a demo

import { $ref, $$ } from 'vue/macros' // $ref comes from the vue/macros package

// bind ref as a variable
let count = $ref(0)

// assignments are reactive
count++

// get the actual ref
console.log($$(count)) // { value: 1 }
  • You can use $() to destructure a reactive object, so you don't have to write .value
  • You can use $$() to get the original ref object

Add reactivityTransform: true in the vite.config.ts file

plugins: [
  vue({
    reactivityTransform: true,
  }),
]

You can use vue/macros from unplugin-auto-import, so there's no need to import it manually.

AutoImport({
  imports: ['vue/macros'],
  dts: true,
})

#unplugin-vue-components

Automatically imports UI libraries on demand. Many component libraries recommend this way of importing, such as Element Plus and Ant Design Vue.

Install

npm install unplugin-vue-components -D
import { defineConfig } from 'vite'
import Components from 'unplugin-vue-components/vite'
import {
  ElementPlusResolver,
  AntDesignVueResolver,
  VantResolver,
  HeadlessUiResolver,
  ElementUiResolver
} from 'unplugin-vue-components/resolvers'

export default defineConfig({
  plugins: [
    Components({
      // UI library resolvers; you can also write your own
      resolvers: [
        ElementPlusResolver(),
        AntDesignVueResolver(),
        VantResolver(),
        HeadlessUiResolver(),
        ElementUiResolver()
      ]
    })
  ]

The plugin generates a components.d.ts file for UI library components and their paths, like this

// generated by unplugin-vue-components
// We suggest you to commit this file into source control
// Read more: https://github.com/vuejs/vue-next/pull/3399

declare module 'vue' {
  export interface GlobalComponents {
    ElAside: typeof import('element-plus/es')['ElAside']
    ElButton: typeof import('element-plus/es')['ElButton']
    ElContainer: typeof import('element-plus/es')['ElContainer']
    ElHeader: typeof import('element-plus/es')['ElHeader']
    ElIcon: typeof import('element-plus/es')['ElIcon']
    ElMain: typeof import('element-plus/es')['ElMain']
  }
}

export {}

Any component you use gets imported automatically, and you can also import your own components.

import { defineConfig } from 'vite'
import Components from 'unplugin-vue-components/vite'

export default defineConfig({
  plugins: [
    Components({
      // Where to look for components; defaults to src/components
      dirs: ['src/components'],
      extensions: ['vue'],
      // Where to generate the config file
      dts: 'src/components.d.ts',
    }),
  ],
})

#unplugin-vue-define-options/vite

Lets you define component name, inheritAttrs, props and emits with defineOptions in the script setup syntax sugar.

Install

npm i unplugin-vue-define-options
import { defineConfig } from 'vite'
import DefineOptions from 'unplugin-vue-define-options/vite'
import vue from '@vitejs/plugin-vue'

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

Set types in tsconfig.json as shown below:

{
  "compilerOptions": {
    "types": ["unplugin-vue-define-options"]
  }
}

Otherwise, in a TS project you'll get the error Cannot find name 'defineOptions'. Usage looks like this

<script setup lang="ts">
import { useSlots } from 'vue'
defineOptions({
  name: 'Foo',
  inheritAttrs: false,
  props: {
    msg: { type: String, default: 'bar' },
  },
  emits: ['change', 'update'],
})
const slots = useSlots()
</script>

Output

<script lang="ts">
export default {
  name: 'Foo',
  inheritAttrs: false,
  props: {
    msg: { type: String, default: 'bar' },
  },
  emits: ['change', 'update'],
}
</script>

<script setup>
const slots = useSlots()
</script>

If all you want is to set the component name, the plugin vite-plugin-vue-setup-extend may be a better fit. You just add a name attribute to the script tag.

<template>
  <div>hello world {{ a }}</div>
</template>

<script lang="ts" setup name="App">
const a = 1
</script>

#vite-plugin-mock

Provides mock services for local development and production.

Install

npm i mockjs vite-plugin-mock
import { UserConfigExport, ConfigEnv } from 'vite'

import { viteMockServe } from 'vite-plugin-mock'
import vue from '@vitejs/plugin-vue'

export default ({ command }: ConfigEnv): UserConfigExport => {
  return {
    plugins: [
      vue(),
      viteMockServe({
        // default
        mockPath: 'mock',
        localEnabled: command === 'serve',
      }),
    ],
  }
}

#vite-plugin-pages

File-system-based dynamic routing.

Install

npm install -D vite-plugin-pages
npm install vue-router
import Pages from 'vite-plugin-pages'

export default {
  plugins: [
    Pages({
      dirs: 'src/views',
    }),
  ],
}

The traditional way to write routes

// 1. Define route components.
const Home = { template: '<div>Home</div>' }
const About = { template: '<div>About</div>' }

// 2. Define some routes
const routes = [
  { path: '/', component: Home },
  { path: '/about', component: About },
]

// 3. Create the router instance and pass the `routes` option
const router = VueRouter.createRouter({
  routes,
})

This plugin instead imports all the vue files under pages (views) as routes, with its own routing rules, similar to nuxt.js

import { createRouter } from 'vue-router'
import routes from '~pages'

const router = createRouter({
  // ...
  routes,
})

#vite-plugin-vue-layouts

Used together with vite-plugin-pages, it adds dynamic layouts on top of the generated page routes.

Install

npm install -D vite-plugin-vue-layouts
import Vue from '@vitejs/plugin-vue'
import Pages from 'vite-plugin-pages'
import Layouts from 'vite-plugin-vue-layouts'

export default {
  plugins: [Vue(), Pages(), Layouts()],
}

Add a layout setting in the corresponding single-file page component, and the route will switch to that layout, embedding the page inside it.

<route lang="yaml">
meta:
  layout: users
</route>

#vite-plugin-purge-icons

An easy way to use Iconify icons.

Install

 pnpm add @iconify/iconify
 pnpm add vite-plugin-purge-icons @iconify/json -D
import PurgeIcons from 'vite-plugin-purge-icons'

export default {
  plugins: [
    PurgeIcons({
      /* PurgeIcons Options */
    }),
  ],
}

Import @purge-icons/generated in main.js

import { createApp } from 'vue'
import App from './App.vue'

import '@iconify/iconify'
import '@purge-icons/generated'

createApp(App).mount('#app')

Usage

In an HTML file, set the class to iconify and data-icon to the icon you want from Iconify (just copy it from the official site)

<span class="iconify" data-icon="system-uicons:browser-alt" data-inline="false" />

Of course, you can also wrap it in your own Icon component, like this.

<Icon icon="ion:settings-outline" :size="30" />

Or use Iconify for Vue, the Vue 3 version.

#vite-plugin-windicss

Install

npm i -D vite-plugin-windicss windicss
import WindiCSS from 'vite-plugin-windicss'

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

The main reason I use Windi CSS is that attributify mode is just too good (I expect it to become a trend). Attributify is optional by default, and you can enable it in your windi config.

import { defineConfig } from 'windicss/helpers'

export default defineConfig({
  attributify: true,
})

Then use them as needed:

<button bg="blue-400 hover:blue-500 dark:blue-500 dark:hover:blue-600" text="sm white" font="mono light" p="y-2 x-4" border="2 rounded blue-200">Button</button>

Syntax

(variant[:-]{1})*key? = "((variant:)*value)*"

#vite-plugin-node

Lets you use Vite as a Node.js development server.

I haven't really tested this one yet. I just thought it was interesting.

#Summary

I've been developing with Vite for a while now, and I'm very happy with the developer experience. The plugins above are surely a big part of why. This time I went through a few projects to see how these plugins are used. This is only a roundup of the common ones. For more, check out awesome-vite.

References:

Evan You's favorite tool, unplugin-vue-components: stop importing things by hand (components, UI libraries like Element-ui, Vue hooks, etc.) - Juejin (juejin.cn)

Vite 2 common plugins (part 3) - advanced plugins - Juejin (juejin.cn)

Recommended efficient Vite plugins - Juejin (juejin.cn)

vitejs/awesome-vite: ⚡️ A curated list of awesome things related to Vite.js (github.com)