@samveys/vue

Versi
1.0.35 Nov 2026
Pasang
pnpm add @samveys/vue

Dari packages/vue/README.md di repository framework.

Halaman ini belum diterjemahkan. Kamu sedang membaca versi bahasa Inggris.

Server-side rendering of Vue pages for @samveys/view.

Peer dependencies: vue and @vue/server-renderer (both ^3.5.44). Nothing else.

.vue files are not compiled here. Compiling single-file components needs @vue/compiler-sfc. Build your SFCs with Vite (@vitejs/plugin-vue) and pass the compiled components to the engine. Components written as plain objects with render functions (h()) work without any build step, which is what the examples below use.

Set up

ts
import { http } from '@samveys/http'
import { view } from '@samveys/view'
import { vite } from '@samveys/vite'
import { vue } from '@samveys/vue'
import { defineComponent, h } from 'vue'

const Home = defineComponent({
  props: { name: { type: String, required: true } },
  setup: (props) => () => h('main', [h('h1', `Hello ${props.name}`)]),
})

export const plugins = [http(), view(), vue({ components: { Home }, entry: 'resources/app.ts', title: 'My app' }), vite()]
OptionMeaning
componentsPage components by name
entryVite entry of the browser bundle; its tags are added to the page (needs @samveys/vite)
idId of the app element. Default app
title, head<title> (escaped) and extra <head> markup (trusted)

Render

ts
import type { Router } from '@samveys/http'

export function routes(router: Router): void {
  router.get('/', (ctx) => ctx.view.render('Home', { name: 'Ann' }))
}

The page is rendered with createSSRApp and renderToString, then wrapped in a shell:

html
<div id="app"><main><h1>Hello Ann</h1></main></div>
<script type="application/json" id="__SVS_STATE__">{"component":"Home","props":{"name":"Ann"}}</script>
<script type="module" src="/build/assets/app-abc123.js"></script>
ts
import { parseState, serializeState } from '@samveys/vue'

const text = serializeState({ component: 'Home', props: { name: '</script>' } })

export const roundTrips = text.includes('<') === false && parseState<{ props: { name: string } }>(text).props.name === '</script>'

The state is JSON with <, >, & and line separators written as \uXXXX, so </script> inside a value cannot end the element, and JSON.parse gives back exactly the props. serializeState and parseState do the two directions.

Hydrate in the browser

The browser entry (built by Vite) reads the state and mounts the same component on the server-rendered markup:

ts
import { createSSRApp } from 'vue'
import { parseState } from '@samveys/vue'
import Home from './pages/Home.vue'

const pages = { Home }
const state = parseState<{ component: keyof typeof pages; props: Record<string, unknown> }>(document.getElementById('__SVS_STATE__')!.textContent!)

createSSRApp(pages[state.component], state.props).mount('#app')