unplugin-reactive-vue
v1.0.2
Published
Reactivity Transform on $-Prefixed Identifiers
Maintainers
Readme
unplugin-reactive-vue
This is an unplugin implementation of a Vue reactivity transform where local reactive variables are identified by a $ prefix.
Currently, the implementation has not been battle tested and may contain fixable edge cases. If you encounter such, please open an issue or submit a pull request.
Why this is better
The original proposal was rejected partially on the grounds that losing .value where a ref was used hid the reactive nature of related operations.
By instead prefixing the actual identifier its reactive nature is consistently indicated through the file, even in the template where there is already a "special case" in place that makes it so adding .value is generally not needed.
In other words, projects that consistently use this transform can expect fewer sources of errors regarding the accidental omission of .value and less verbose code without hiding sources of reactivity.
Semantics
Here are some examples of what the transformed code might look like:
let $x = 123->let $x = ref(123)use($x)->use($x.value)$x = 321->$x.value = 321$x++->$x.value++let $x = $(existingRef)binds an existing ref (e.g. fromcomputed(...)) to a reactive variable$$(...)disables the transform for an expression, allowing access to the underlying refs
Features
The transform seamlessly handles many complex reactivity scenarios out-of-the-box:
- Destructuring declarations:
let { $a } = $(useFeature())correctly tracks$aas a reactive reference. - Reactive function parameters:
function foo($a) { $a = 2; }automatically unwraps$ato$a.valueinside the function body. - Imported bindings:
import { $state } from './store'intelligently tracks and unwraps$stateon use.
It also uses magic-string to preserve source maps.
There are some caveats:
- Reactive variables cannot be the iteration variable in for..in or for..of loops.
- Destructuring a reactive object (e.g. from a store) using reactive variables requires the
$()macro (e.g.let { $count } = $(store)) to safely injecttoRefsand maintain reactivity. varis not supported and will lead to edge cases and undefined behavior if used. This allows the transform to occur in a single pass and not waste processing time for an anti-pattern.
Usage
Install in your project, e.G. pnpm install unplugin-reactive-vue, then add the plugin to your bundler configuration:
// vite.config.ts
import ReactiveVue from "unplugin-reactive-vue/vite";
import vue from "@vitejs/plugin-vue";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [ReactiveVue({}), vue()],
});Options
export interface ReactiveVueOptions {
include?: RegExp | RegExp[]; // Filter files to transform
exclude?: RegExp | RegExp[]; // Filter files to not transform
importSource?: string; // The import source for the reactivity APIs (default: 'vue')
prefix?: string; // The prefix for reactive variables (default: '$')
wrapCallee?: string; // The function name used to wrap an existing ref (default: '$')
escapeCallee?: string; // The function name used to escape the transform (default: '$$')
dts?: string; // Generate TypeScript declaration for macros (default: '').
}TypeScript
If you are using the default settings, you can simply add the pre-packaged macro typings to your tsconfig.json:
{
"compilerOptions": {
"types": ["unplugin-reactive-vue/types"]
}
}If you customize the wrapCallee and/or escapeCallee, you can enable the dts: true option in your plugin configuration to generate a custom reactive-macros.d.ts file automatically, and add it to your tsconfig.json's includes.
Alternatively, you can adapt macros-global.d.ts to your needs or add it to an existing type definitions file in your project, e.G. vite-env.d.ts.
Try it out!
This repository contains an example vue app demonstrating the basic functionality of the transform. Just poke around!
git clone https://git.ulra.eu/adro/unplugin-reactive-vue`
cd unplugin-reactive-vue
pnpm install && pnpm build
pnpm run dev # To run tests
cd example
pnpm install && pnpm run dev # To run the example with the vite development server