⚠️ The
vite-plugin-ssr
project has been renamed
Vike.
- If you are already using vite-plugin-ssr then migrate to Vike.
- For new projects, don't use vite-plugin-ssr but use Vike instead.
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:
- Basic apps:
onBeforeRender()
hook:
- Defined by page in
pages/
:
- Defined globally in
renderer/
:
- Pre-rendered app (that uses
prerender()
hooks):
- Custom exports to custom configs (see migration explanation at Custom hooks/exports):
pageContext.exports.documentProps
-> pageContext.config.title
:
pageContext.exports.Layout
-> pageContext.config.Layout
:
pageContext.exports.preloadStrategy
-> pageContext.config.preloadStrategy
:
- i18n (pre-rendered) app (that uses hooks
onBeforeRoute()
, onBeforePrerender()
, prerender()
):
- Domain-driven file structure (that uses
filesystemRoutingRoot
)
Renamed hooks
Old name | New name |
---|
render() in .page.client.js | onRenderClient() |
render() in .page.server.js | onRenderHtml() |
prerender() | onBeforePrerenderStart() |
onBeforePrerender() | onPrerenderStart() |
The hooks are equivalent: they just have a new name.
Also note that doNotPrerender
has been renamed:
Old name | New name |
---|
doNotPrerender: true | prerender: 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