Vue Define Options Macro Unplugin
unplugin-vue-define-options is a build tool macro that enables the use of the `defineOptions` API within Vue 3's `<script setup>` syntax. This macro allows developers to define component options like `name`, `props`, `emits`, and `render` directly within the setup script, bridging the gap between Options API and Composition API for certain configurations. It is currently at version 3.1.2 and is part of the broader Vue Macros project, which sees frequent updates and feature additions, often with minor version bumps and occasional major releases (like v3.0.0) that introduce breaking changes. Its key differentiators include broad bundler support (Vite, Webpack, Rollup, esbuild via unplugin), full TypeScript compatibility, and support for both Vue 2.7 (though dropping in v3) and Vue 3.
Common errors
-
ReferenceError: defineOptions is not defined
cause The `unplugin-vue-define-options` plugin is not correctly configured or loaded by the bundler, preventing the `defineOptions` macro from being transformed during compilation.fixDouble-check your bundler configuration (e.g., `vite.config.ts`, `webpack.config.js`) to ensure the `DefineOptions()` plugin is imported from the correct bundler-specific path and added to the `plugins` array. For Vite, ensure `@vitejs/plugin-vue` is also present and correctly configured. -
Error: Node.js 16.x is not supported by Vue Macros v3. Please upgrade to Node.js >=20.19.0.
cause Attempting to use `unplugin-vue-define-options` version 3 or later with an unsupported Node.js version.fixUpgrade your Node.js environment to version `20.19.0` or higher. Alternatively, downgrade `unplugin-vue-define-options` to a `^2.x` version which supports Node.js 16/18. -
[Vue warn]: Component provided a 'name' option that is already set. This is most likely due to a compiler error where 'name' is being set twice.
cause The component is already receiving a `name` property from another source (e.g., a build tool setting it automatically, or another macro), and `defineOptions` is attempting to set it again.fixReview your build configuration and other Vue macros. Ensure only one source is providing the `name` option. If you are using `unplugin-vue-macros` in combination, ensure there are no conflicting options being set for component names.
Warnings
- breaking Version 3.0.0 introduced significant breaking changes, including dropping support for Vue 2, Webpack 4, Node.js 16, and Node.js 18. Projects relying on these older environments must remain on v2 or earlier.
- breaking The `shortEmits` feature was disabled in Vue 3.3 by this package due to changes in Vue itself, which might affect projects relying on that specific macro behavior.
- gotcha This package is an 'unplugin', meaning its integration method differs based on your bundler (Vite, Webpack, Rollup, etc.). Incorrect import paths or plugin registration can lead to the macro not being processed.
- gotcha The `defineOptions` macro, while syntactically similar to standard JavaScript, is a compile-time transformation. It will not work without the unplugin correctly configured in your build setup, leading to runtime errors if Vue encounters an unrecognized global function.
Install
-
npm install unplugin-vue-define-options -
yarn add unplugin-vue-define-options -
pnpm add unplugin-vue-define-options
Imports
- DefineOptions
import { DefineOptions } from 'unplugin-vue-define-options'import DefineOptions from 'unplugin-vue-define-options/vite'
- defineOptions
defineOptions({ name: 'MyComponent' }) - VueMacros
import VueMacros from 'unplugin-vue-macros'
Quickstart
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import DefineOptions from 'unplugin-vue-define-options/vite';
export default defineConfig({
plugins: [
vue(),
DefineOptions()
]
});
// src/components/MyComponent.vue
// <script setup lang="ts">
// import { ref } from 'vue';
//
// defineOptions({
// name: 'MyComponent',
// inheritAttrs: false,
// customOption: 'hello'
// });
//
// const count = ref(0);
//
// const increment = () => {
// count.value++;
// };
//
// </script>
//
// <template>
// <div>
// <p>Count: {{ count }}</p>
// <button @click="increment">Increment</button>
// </div>
// </template>