⚠
vite-plugin-ssr has been renamed Vike, see migration guide.

V1 Design Migration

⚠
The V1 design is in beta.

The overall architecture stays the same: the V1 design only replaces .page.js files with + files: +config.h.js, +Page.js, +route.js, ...

Despite being simple, it introduces new foundational capabilities. If you're curious: Why the V1 design?

The migration is straightforward and usually quick to implement. We encourage to migrate sooner rather than later.

Don't hesitate to reach out if you run into any issue.

Main migration

Make sure to update vite-plugin-ssr to its latest version.

You need to either fully use the V1 design, or fully use the old design. You cannot mix both.

Most of the migration boils down to the following two steps.

1. Migrate /renderer/*.page.*

Move your renderer/ hooks to + files:

- // /renderer/_default.page.client.js
+ // /renderer/+onRenderClient.js

- export { render }
+ export default render
- // /renderer/_default.page.server.js
+ // /renderer/+onRenderHtml.js

- export { render }
+ export default render

If you've defined a global onBeforeRender() hook and/or passToClient:

- // /renderer/_default.page.server.js
+ // /renderer/+onBeforeRender.js

- export { onBeforeRender }
- export const passToClient = ['pageProps']
+ export default onBeforeRender
+ // /renderer/+config.h.js
+ 
+ export default {
+   passToClient: ['pageProps']
+ }

See +config.h.js for more information about what + and .h.js means.

The suffixes such as .page.server.js and .page.client.js don't exist anymore. After the feature request #744 is implemented, you'll be able to use .server.js and .client.js suffixes again but note that they'll serve another purpose.

Move /renderer/ configurations to /renderer/+config.h.ts:

- // /renderer/_default.page.client.ts

- export { clientRouting }
- export { hydrationCanBeAborted }
// /renderer/+config.h.ts

import type { Config } from 'vite-plugin-ssr/types'

export default {
  clientRouting: true,
  hydrationCanBeAborted: true
} satisfies Config

Move your error page (if you defined one):

- // /renderer/_error.page.js
+ // /pages/_error/+Page.js

- export { Page }
+ export default Page

2. Migrate /pages/**/*.page.*

- // /pages/some-page/index.page.ts
+ // /pages/some-page/+Page.ts

- export { Page }
+ export default Page
- // /pages/some-page/index.page.server.ts
+ // /pages/some-page/+onBeforeRender.ts

- export { onBeforeRender }
+ export default onBeforeRender
- // /pages/some-page/index.page.route.ts
+ // /pages/some-page/+route.ts

export default route

Each page now lives in its own directory.

# ✅ V1 design
$ ls pages/**/*
/pages/some-page/+Page.js
/pages/some-other-page/+Page.js
# ❌ This isn't possible anymore: each page now needs to create a new directory
$ ls pages/**/*
/pages/some.page.js
/pages/some-other.page.js

Apply following additional steps if you've defined:

Examples

All official examples have been migrated, see examples/*-v1.

Notable migrations:

Renamed hooks

Old nameNew name
render() in .page.client.jsonRenderClient()
render() in .page.server.jsonRenderHtml()
prerender()onBeforePrerenderStart()
onBeforePrerender()onPrerenderStart()

The hooks are equivalent: they just have a new name.

Also note that doNotPrerender has been renamed:

Old nameNew name
doNotPrerender: trueprerender: false
// /pages/news.page.server.js

- export const doNotPrerender = true
// /pages/news/+config.h.js

  export default {
+   prerender: false
  }

Custom hooks/exports

If you use custom hooks/exports, then replace them with custom configs.

You define custom configs by using meta:

// /renderer/+config.h.ts

import type { Config } from 'vite-plugin-ssr/types'

export default {
  meta: {
    // We define a new config 'title'
    title: {
      // The value of 'title' should only be loaded on the server
      env: 'server-only'
    }
  }
} satisfies Config
// /renderer/+onRenderHtml.js

export default function(pageContext) {
  // Config values are available at pageContext.config
  const { title } = pageContext.config
  return escapeInject`<html>
    <head>
      <title>${title}</title>
    </head>
    <!-- ... -->
  </html>`
}
// /pages/about/+config.h.js

export default {
  title: 'Demo showcasing the V1 design'
}

See:

onBeforeRender in .page.js

If you've defined onBeforeRender() hooks in .page.js (instead of .page.server.js):

// /renderer/+config.h.ts

import type { Config } from 'vite-plugin-ssr/types'

export default {
  meta: {
    onBeforeRender: {
      // We tell vite-plugin-ssr to load and execute onBeforeRender()
      // not only on the server-side but also on the client-side.
      env: 'server-and-client'
    }
  }
} satisfies Config

For convenience, you can use meta in order to create a new config onBeforeRenderIsomorph: boolean for a page-per-page toggle.

Client init code

The new config client allows you to define client-side initialization code.

You can also keep using onHydrationEnd().

// +config.h.js
export default {
  client: './some-client-code.js'
}
// some-client-code.js
console.log("I'm run when the client-side JavaScript is loaded.")

See also