Skip to content
This repository was archived by the owner on Aug 16, 2024. It is now read-only.
/ vue-ssr Public archive

Minimalistic wrapper to develop and run SSR Vue apps πŸ”—

License

Notifications You must be signed in to change notification settings

bistroo/vue-ssr

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Jan 29, 2024
32cdc40 Β· Jan 29, 2024

History

68 Commits
Apr 28, 2023
Apr 27, 2023
Aug 1, 2023
Jan 29, 2024
Apr 16, 2023
Apr 16, 2023
Jun 17, 2023
May 2, 2023
Jun 20, 2023
Jan 29, 2024
Aug 1, 2023
Apr 27, 2023
Apr 27, 2023
Apr 27, 2023

Repository files navigation

SSR for Vue

Minimalistic wrapper to run SSR Vue apps, based on Vite

Features

  • HMR support
  • Vue Router
  • State management
  • Teleports
  • Document head management (powered by @vueuse/head)

Quick Setup

Installation

pnpm install @bistroo/vue-ssr -D

Add the following scripts

"scripts": {
  "dev": "vue-ssr",
  "build": "vue-ssr build",
  "start": "vue-ssr start"
},

The vue-ssr command creates a dev server with HMR enabled. To create a production ready build, use vue-ssr build. After creating a build, use vue-ssr start to serve the build with Express.

Configuration

Create a vue-ssr.config.ts

import { defineConfig } from '@bistroo/vue-ssr'
import { fileURLToPath } from 'node:url'

export default defineConfig({
  vite: {
    resolve: {
      alias: {
        '@': fileURLToPath(new URL('./src', import.meta.url)),
      },
    },
  },
})

Use the vite property with caution.

Usage

import { vueSSR } from '@bistroo/vue-ssr'

import App from '@/App.vue'

const Counter = () => import('@/Counter.vue')

const routes = [
  {
    path: '/',
    name: 'counter',
    component: Counter,
  }
]

export default vueSSR(App, { routes })

The main.ts file should export the imported vueSSR function.

Pinia is supported by using the app and state property inside the callback.

export default vueSSR(App, { routes }, ({ app, state }) => {
  const pinia = createPinia()

  app.use(pinia)

  if (import.meta.env.SSR) {
    state.value = pinia.state.value
  } else {
    pinia.state.value = state.value
  }
})

The state will be persisted on window.__INITIAL_STATE__ property and serialized using @nuxt/devalue

It's possible to make changes to the router, use the router property in the callback.

export default vueSSR(App, { routes }, ({ router }) => {
  router.beforeEach(async (to, from) => {
    if (
      !isAuthenticated &&
      to.name !== 'Login'
    ) {
      return { name: 'Login' }
    }
  })
})

The Express request and response objects are accessible from the callback. Make sure to wrap them in import.meta.env.SSR.

export default vueSSR(App, { routes }, ({ request, response }) => {
  if (import.meta.env.SSR) {
    console.log(request?.originalUrl)
  }
})

Or use useSSRContext.

const { request, response } = useSSRContext()

if (import.meta.env.SSR) {
  console.log(request?.originalUrl)
}

Using Teleport is supported, but requires a little bit of setup. Targeting body is not supported, use #teleports instead.

<template>
  <Teleport to="#teleports">
    <button @click="store.increment">Increment</button>
  </Teleport>
</template>

During SSR, the Teleport component will be rendered as a div with the id set to the to property.

License

MIT