Vue Macros: Enhanced SFC Syntax Sugar
Vue Macros is a collection of experimental and advanced compiler macros and syntax sugar designed to significantly enhance the development experience for Vue.js Single File Components (SFCs). It serves as a playground for new language features and proposals that extend Vue's capabilities beyond its official API, often simplifying boilerplate and improving reactivity patterns. The current stable version is 3.1.2, with an active release cadence reflecting ongoing development and frequent updates. Key differentiators include its modular nature, allowing developers to selectively enable specific macros, and its integration as an `unplugin`, providing broad compatibility across various build tools like Vite, Rollup, Webpack, and Nuxt. It brings features like `defineOptions`, `defineModels`, and `definePropsRefs` that streamline component definition and data flow, offering type safety and improved developer ergonomics.
Common errors
-
Error: Cannot find module 'unplugin-vue-macros/vite'
cause The `unplugin-vue-macros` package or its specific bundler integration was not installed or is incorrectly referenced.fixEnsure `unplugin-vue-macros` is installed as a development dependency: `npm install -D unplugin-vue-macros` or `yarn add -D unplugin-vue-macros`. Verify the import path in your build configuration matches your bundler (e.g., `unplugin-vue-macros/vite` for Vite). -
ESLint: 'defineOptions' is not defined. (no-undef)
cause ESLint is not configured to recognize global compiler macros introduced by Vue Macros, or the TypeScript environment isn't set up for global types.fixAdd `"unplugin-vue-macros/macros-global"` to the `types` array in your `tsconfig.json`. For ESLint, ensure `eslint-plugin-vue` is updated to at least v8 and configure your `.eslintrc` to recognize `vue/setup-compiler-macros` if still relevant for older setups. -
Syntax Error: Using 'defineModels' outside of <script setup>.
cause Many Vue Macros, especially those related to component options and reactivity, are designed exclusively for use within Vue's `<script setup>` block.fixRelocate the macro call (e.g., `defineModels`, `defineOptions`) into a `<script setup>` block in your Single File Component. These are compiler macros and are not intended for use in regular `<script>` blocks or JavaScript/TypeScript files.
Warnings
- breaking Vue Macros v3.x dropped official support for Vue 2, Webpack 4, and Node.js versions 16 and 18. Users on these older environments should remain on Vue Macros v2.x or upgrade their project dependencies.
- breaking Starting with Vue Macros v3.0.0-rc.0, the minimum required Node.js version is `20.19.0`. Running with older Node.js versions will result in errors.
- breaking The `shortEmits` macro is disabled by default in Vue 3.3 and later due to official integration or conflicts. If you relied on this specific macro, its behavior might change or require explicit re-enabling if supported.
- breaking The main package name was renamed in v3, and the CJS build was dropped for most packages, excluding volar-related ones. This impacts how packages are imported and bundled.
- gotcha Some macros introduce new syntax that IDEs and linters might not immediately understand without proper configuration. This can lead to false positive errors or lack of type inference.
Install
-
npm install vue-macros -
yarn add vue-macros -
pnpm add vue-macros
Imports
- VueMacros
import { VueMacros } from 'unplugin-vue-macros'import VueMacros from 'unplugin-vue-macros/vite'
- VueMacros
const VueMacros = require('unplugin-vue-macros/rollup')import VueMacros from 'unplugin-vue-macros/rollup'
- macros-global.d.ts
import 'unplugin-vue-macros/macros-global'
/// <reference types="unplugin-vue-macros/macros-global" />
Quickstart
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import VueMacros from 'unplugin-vue-macros/vite';
export default defineConfig({
plugins: [
VueMacros({
plugins: {
vue: vue(), // Required for Vue 3 projects
},
}),
],
});
// src/components/MyComponent.vue
<script setup lang="ts">
import { ref } from 'vue';
defineOptions({
name: 'MyComponent',
inheritAttrs: false,
});
const count = ref(0);
const increment = () => count.value++;
</script>
<template>
<div>
<h1>{{ defineOptions.name }} Example</h1>
<p>Count: {{ count }}</p>
<button @click="increment">Increment</button>
</div>
</template>
<style scoped>
div {
padding: 1em;
border: 1px solid #eee;
border-radius: 8px;
text-align: center;
}
button {
margin-top: 10px;
padding: 0.5em 1em;
font-size: 1em;
cursor: pointer;
}
</style>