{"id":12378,"library":"vite-plugin-vue-server-ref","title":"Vite Plugin for Vue Server-Side State Synchronization","description":"vite-plugin-vue-server-ref is a Vite plugin designed to facilitate the sharing of reactive state between multiple Vue clients and the Vite development server. It enables real-time synchronization of data across browser tabs or different client instances, utilizing Vue's reactivity system. The current stable version is v1.0.0, which notably transitioned to an ESM-only architecture, dropping CommonJS support. The package sees active development with regular updates addressing bug fixes and introducing minor features. Key differentiators include its tight integration with Vite's dev server, the use of virtual module imports (e.g., `server-ref:key`, `server-reactive:key`) for seamless state access, and features like granular synchronization control and incremental updates for reactive objects via diffing.","status":"active","version":"1.0.0","language":"javascript","source_language":"en","source_url":"https://github.com/antfu/vite-plugin-vue-server-ref","tags":["javascript","vite-plugin","typescript"],"install":[{"cmd":"npm install vite-plugin-vue-server-ref","lang":"bash","label":"npm"},{"cmd":"yarn add vite-plugin-vue-server-ref","lang":"bash","label":"yarn"},{"cmd":"pnpm add vite-plugin-vue-server-ref","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Peer dependency for Vite plugin functionality.","package":"vite","optional":false},{"reason":"Peer dependency for Vue 3 reactivity system integration.","package":"vue","optional":false}],"imports":[{"note":"Used for configuring the plugin in `vite.config.ts`. The package is ESM-only since v1.0.0, rendering `require()` incompatible.","wrong":"const ServerRef = require('vite-plugin-vue-server-ref')","symbol":"ServerRef","correct":"import ServerRef from 'vite-plugin-vue-server-ref'"},{"note":"This is a virtual module import that provides a Vue `Ref` object, which is treated as a default export.","wrong":"import { foo } from 'server-ref:foo'","symbol":"server-ref:key","correct":"import foo from 'server-ref:foo'"},{"note":"This is a virtual module import for sharing a reactive object, also treated as a default export.","wrong":"import { object } from 'server-reactive:object'","symbol":"server-reactive:key","correct":"import object from 'server-reactive:object'"},{"note":"Essential for providing correct TypeScript type inference for the virtual module imports, which default to `any`. Using `import type` ensures it's stripped from the runtime bundle.","wrong":"import { ServerRef, ServerReactive } from 'vite-plugin-vue-server-ref/client'","symbol":"ServerRef (type)","correct":"import type { ServerRef, ServerReactive } from 'vite-plugin-vue-server-ref/client'"}],"quickstart":{"code":"import { defineConfig } from 'vite';\nimport ServerRef from 'vite-plugin-vue-server-ref';\nimport Vue from '@vitejs/plugin-vue';\n\n// vite.config.ts\nexport default defineConfig({\n  plugins: [\n    Vue(),\n    ServerRef({\n      state: {\n        foo: 'bar',\n        object: {\n          count: 0,\n          message: 'Hello'\n        }\n      }\n    })\n  ]\n});\n\n// src/main.ts (or a Vue component)\nimport { createApp } from 'vue';\nimport App from './App.vue';\n\ncreateApp(App).mount('#app');\n\n// src/App.vue\n<script setup lang=\"ts\">\nimport { ref } from 'vue';\nimport type { ServerReactive, ServerRef } from 'vite-plugin-vue-server-ref/client';\n\nconst foo = (await import('server-ref:foo')).default as ServerRef<string>;\nconst object = (await import('server-reactive:object?diff')).default as ServerReactive<{ count: number; message: string }>;\n\nconsole.log('Initial foo:', foo.value); // Should log 'bar'\nconsole.log('Initial object:', object.count); // Should log 0\n\nfoo.value = 'updated string';\nobject.count++;\nobject.message = 'World';\n\n// You can also listen for changes from the server/other clients\nfoo.$onSet((newValue) => {\n  console.log(`Foo changed from server/client: ${newValue}`);\n});\n\n// Example of controlling sync direction\n// foo.$syncUp = false; // Makes it download-only\n// object.$syncDown = false; // Makes it upload-only\n\nconst localCount = ref(0);\nsetInterval(() => {\n  localCount.value++;\n  // This won't sync to server unless foo.$syncUp is true and value is changed\n  // console.log('Local count:', localCount.value);\n}, 1000);\n</script>\n\n<template>\n  <div>\n    <h1>Server Ref Demo</h1>\n    <p>Foo: {{ foo.value }}</p>\n    <p>Object Count: {{ object.count }}</p>\n    <p>Object Message: {{ object.message }}</p>\n    <p>Local Count: {{ localCount }}</p>\n  </div>\n</template>\n","lang":"typescript","description":"This quickstart demonstrates how to configure `vite-plugin-vue-server-ref` in `vite.config.ts` with initial state and then use `server-ref` and `server-reactive` virtual imports within a Vue component to access and synchronize state across multiple clients and the Vite development server, including type-safety with `import type`."},"warnings":[{"fix":"Ensure your project is configured for ESM, and replace `require()` statements with `import` statements. If using `vite.config.js`, rename it to `vite.config.mjs` or ensure your `package.json` has `\"type\": \"module\"`.","message":"Starting from v1.0.0, vite-plugin-vue-server-ref is exclusively an ESM (ECMAScript Module) package, dropping support for CommonJS. This requires using `import` statements in your `vite.config.ts` and any Node.js files that interact with the plugin.","severity":"breaking","affected_versions":">=1.0.0"},{"fix":"Similar to v1.0.0, ensure your project's module resolution properly handles ESM packages. For Node.js environments, use `import` syntax or configure transpilation if necessary.","message":"Version 0.4.0 also introduced a breaking change by moving to `type: module` in its `package.json`, which affected CommonJS compatibility prior to the full ESM-only transition in v1.0.0.","severity":"breaking","affected_versions":">=0.4.0 <1.0.0"},{"fix":"Always use `import type { ServerRef, ServerReactive } from 'vite-plugin-vue-server-ref/client'` and apply type assertions (e.g., `const foo = _foo as ServerRef<string>`) to ensure proper type inference and safety.","message":"Virtual module imports like `server-ref:key` and `server-reactive:key` return an `any` type by default in TypeScript. This leads to a lack of type safety when accessing their properties (e.g., `.value` or object keys).","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"For reactive objects where partial updates are desired, change your import from `import object from 'server-reactive:object'` to `import object from 'server-reactive:object?diff'`.","message":"When working with reactive objects, simply using `server-reactive:key` will send the entire object on every change. For incremental updates (deep diffing), you must append `?diff` to the virtual import path.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"Understand that `foo.$syncUp = false` means changes made locally *will not* be sent to the server, making it download-only. `foo.$syncDown = false` means changes from the server *will not* be received, making it upload-only (if `$syncUp` is true). Set these flags carefully according to your desired sync behavior.","message":"The plugin exposes `$syncUp` and `$syncDown` properties on the server ref/reactive objects to control synchronization direction. Misunderstanding or misusing these can lead to unexpected behavior where state changes are not propagated.","severity":"gotcha","affected_versions":">=0.1.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Change `const ServerRef = require('vite-plugin-vue-server-ref')` to `import ServerRef from 'vite-plugin-vue-server-ref'` and ensure your Node.js or Vite configuration supports ESM.","cause":"Attempting to `require()` `vite-plugin-vue-server-ref` in a CommonJS environment after it became ESM-only.","error":"ERR_REQUIRE_ESM"},{"fix":"Import the correct types and apply a type assertion: `import type { ServerRef } from 'vite-plugin-vue-server-ref/client'; const foo = _foo as ServerRef<string>;`","cause":"TypeScript's default type inference for virtual modules is `any`, leading to type errors when accessing properties like `.value` or specific keys on a reactive object.","error":"Property 'value' does not exist on type 'ServerRef<any>'"},{"fix":"Verify that `vite-plugin-vue-server-ref` is added to the `plugins` array in your `vite.config.ts`. Ensure your `vite.config.ts` is correctly named and located, and that Vite is running in development mode.","cause":"The `vite-plugin-vue-server-ref` plugin is not correctly configured or loaded in `vite.config.ts`, or the Vite dev server is not running.","error":"Failed to resolve import \"server-ref:foo\" from \"src/App.vue\". Does the file exist?"},{"fix":"Ensure the `state` object in your `vite.config.ts` has the key you are trying to access (e.g., `object.count`). If it's an asynchronous component, ensure proper loading states or fallbacks while the ref is being populated.","cause":"Accessing properties on a `server-reactive` object before it has been properly initialized or before the server has provided its state, or the key does not exist.","error":"TypeError: Cannot read properties of undefined (reading 'count')"}],"ecosystem":"npm"}