Initial commit. Files are uploaded to the filesystem.
This commit is contained in:
19
renderer/+config.ts
Normal file
19
renderer/+config.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import type { Config } from 'vike/types'
|
||||
|
||||
// https://vike.dev/config
|
||||
export default {
|
||||
// https://vike.dev/clientRouting
|
||||
clientRouting: true,
|
||||
// https://vike.dev/meta
|
||||
meta: {
|
||||
// Define new setting 'title'
|
||||
title: {
|
||||
env: { server: true, client: true }
|
||||
},
|
||||
// Define new setting 'description'
|
||||
description: {
|
||||
env: { server: true }
|
||||
}
|
||||
},
|
||||
hydrationCanBeAborted: true
|
||||
} satisfies Config
|
||||
9
renderer/+onPageTransitionEnd.ts
Normal file
9
renderer/+onPageTransitionEnd.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
// https://vike.dev/onPageTransitionEnd
|
||||
export { onPageTransitionEnd }
|
||||
|
||||
import type { OnPageTransitionEndAsync } from 'vike/types'
|
||||
|
||||
const onPageTransitionEnd: OnPageTransitionEndAsync = async (): ReturnType<OnPageTransitionEndAsync> => {
|
||||
console.log('Page transition end')
|
||||
document.querySelector('body')!.classList.remove('page-is-transitioning')
|
||||
}
|
||||
9
renderer/+onPageTransitionStart.ts
Normal file
9
renderer/+onPageTransitionStart.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
// https://vike.dev/onPageTransitionStart
|
||||
export { onPageTransitionStart }
|
||||
|
||||
import type { OnPageTransitionStartAsync } from 'vike/types'
|
||||
|
||||
const onPageTransitionStart: OnPageTransitionStartAsync = async (): ReturnType<OnPageTransitionStartAsync> => {
|
||||
console.log('Page transition start')
|
||||
document.querySelector('body')!.classList.add('page-is-transitioning')
|
||||
}
|
||||
21
renderer/+onRenderClient.ts
Normal file
21
renderer/+onRenderClient.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
// https://vike.dev/onRenderClient
|
||||
export { onRenderClient }
|
||||
|
||||
import { createVueApp } from './createVueApp'
|
||||
import { getPageTitle } from './getPageTitle'
|
||||
import type { OnRenderClientAsync } from 'vike/types'
|
||||
|
||||
let app: ReturnType<typeof createVueApp>
|
||||
const onRenderClient: OnRenderClientAsync = async (pageContext): ReturnType<OnRenderClientAsync> => {
|
||||
// This onRenderClient() hook only supports SSR, see https://vike.dev/render-modes for how to modify onRenderClient()
|
||||
// to support SPA
|
||||
if (!pageContext.Page) throw new Error('My onRenderClient() hook expects pageContext.Page to be defined')
|
||||
|
||||
if (!app) {
|
||||
app = createVueApp(pageContext)
|
||||
app.mount('#app')
|
||||
} else {
|
||||
app.changePage(pageContext)
|
||||
}
|
||||
document.title = getPageTitle(pageContext)
|
||||
}
|
||||
55
renderer/+onRenderHtml.ts
Normal file
55
renderer/+onRenderHtml.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
// https://vike.dev/onRenderHtml
|
||||
export { onRenderHtml }
|
||||
|
||||
import { renderToString as renderToString_ } from '@vue/server-renderer'
|
||||
import type { App } from 'vue'
|
||||
import { escapeInject, dangerouslySkipEscape } from 'vike/server'
|
||||
import { createVueApp } from './createVueApp'
|
||||
import logoUrl from '../assets/img/logo.svg'
|
||||
import type { OnRenderHtmlAsync } from 'vike/types'
|
||||
import { getPageTitle } from './getPageTitle'
|
||||
|
||||
const onRenderHtml: OnRenderHtmlAsync = async (pageContext): ReturnType<OnRenderHtmlAsync> => {
|
||||
// This onRenderHtml() hook only supports SSR, see https://vike.dev/render-modes for how to modify
|
||||
// onRenderHtml() to support SPA
|
||||
if (!pageContext.Page) throw new Error('My render() hook expects pageContext.Page to be defined')
|
||||
|
||||
const app = createVueApp(pageContext)
|
||||
|
||||
const appHtml = await renderToString(app)
|
||||
|
||||
const title = getPageTitle(pageContext)
|
||||
const desc = pageContext.data?.description || pageContext.config.description || 'Demo of using Vike'
|
||||
|
||||
const documentHtml = escapeInject`<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="${logoUrl}" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="description" content="${desc}" />
|
||||
<title>${title}</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app">${dangerouslySkipEscape(appHtml)}</div>
|
||||
</body>
|
||||
</html>`
|
||||
|
||||
return {
|
||||
documentHtml,
|
||||
pageContext: {
|
||||
// We can add custom pageContext properties here, see https://vike.dev/pageContext#custom
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function renderToString(app: App) {
|
||||
let err: unknown
|
||||
// Workaround: renderToString_() swallows errors in production, see https://github.com/vuejs/core/issues/7876
|
||||
app.config.errorHandler = (err_) => {
|
||||
err = err_
|
||||
}
|
||||
const appHtml = await renderToString_(app)
|
||||
if (err) throw err
|
||||
return appHtml
|
||||
}
|
||||
30
renderer/createVueApp.ts
Normal file
30
renderer/createVueApp.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { createSSRApp, h, shallowRef } from 'vue'
|
||||
import { setPageContext } from './usePageContext'
|
||||
import { setData } from './useData'
|
||||
import type { PageContext } from 'vike/types'
|
||||
import { objectAssign } from './utils'
|
||||
|
||||
// import Layout from './Layout.vue'
|
||||
|
||||
export function createVueApp(pageContext: PageContext) {
|
||||
const pageContextRef = shallowRef(pageContext)
|
||||
const dataRef = shallowRef(pageContext.data)
|
||||
const pageRef = shallowRef(pageContext.Page)
|
||||
|
||||
// const RootComponent = () => h(Layout, null, () => h(pageRef.value))
|
||||
const RootComponent = () => h(pageContext.config.Layout, null, () => h(pageRef.value))
|
||||
const app = createSSRApp(RootComponent)
|
||||
setPageContext(app, pageContextRef)
|
||||
setData(app, dataRef)
|
||||
|
||||
// app.changePage() is called upon navigation, see +onRenderClient.ts
|
||||
objectAssign(app, {
|
||||
changePage: (pageContext: PageContext) => {
|
||||
pageContextRef.value = pageContext
|
||||
dataRef.value = pageContext.data
|
||||
pageRef.value = pageContext.Page
|
||||
}
|
||||
})
|
||||
|
||||
return app
|
||||
}
|
||||
14
renderer/getPageTitle.ts
Normal file
14
renderer/getPageTitle.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
export { getPageTitle }
|
||||
|
||||
import type { PageContext } from 'vike/types'
|
||||
|
||||
function getPageTitle(pageContext: PageContext): string {
|
||||
const title =
|
||||
// Title defined dynamically by data()
|
||||
pageContext.data?.title ||
|
||||
// Title defined statically by /pages/some-page/+title.js (or by `export default { title }` in /pages/some-page/+config.js)
|
||||
// The setting 'pageContext.config.title' is a custom setting we defined at ./+config.ts
|
||||
pageContext.config.title ||
|
||||
'Vike Demo'
|
||||
return title
|
||||
}
|
||||
29
renderer/types.ts
Normal file
29
renderer/types.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
export type { Component }
|
||||
|
||||
import type { ComponentPublicInstance } from 'vue'
|
||||
|
||||
type Component = ComponentPublicInstance // https://stackoverflow.com/questions/63985658/how-to-type-vue-instance-out-of-definecomponent-in-vue-3/63986086#63986086
|
||||
type Page = Component
|
||||
|
||||
// https://vike.dev/pageContext#typescript
|
||||
declare global {
|
||||
namespace Vike {
|
||||
interface PageContext {
|
||||
Page: Page
|
||||
data?: {
|
||||
/** Value for <title> defined dynamically by by /pages/some-page/+data.js */
|
||||
title?: string
|
||||
/** Value for <meta name="description"> defined dynamically */
|
||||
description?: string
|
||||
}
|
||||
config: {
|
||||
/** Value for <title> defined statically by /pages/some-page/+title.js (or by `export default { title }` in /pages/some-page/+config.js) */
|
||||
title?: string
|
||||
/** Value for <meta name="description"> defined statically */
|
||||
description?: string
|
||||
}
|
||||
/** https://vike.dev/render */
|
||||
abortReason?: string
|
||||
}
|
||||
}
|
||||
}
|
||||
19
renderer/useData.ts
Normal file
19
renderer/useData.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
// https://vike.dev/useData
|
||||
export { useData }
|
||||
export { setData }
|
||||
|
||||
import { inject } from 'vue'
|
||||
import type { App, InjectionKey, Ref } from 'vue'
|
||||
|
||||
const key: InjectionKey<Ref<unknown>> = Symbol()
|
||||
|
||||
/** https://vike.dev/useData */
|
||||
function useData<Data>(): Ref<Data> {
|
||||
const data = inject(key)
|
||||
if (!data) throw new Error('setData() not called')
|
||||
return data as Ref<Data>
|
||||
}
|
||||
|
||||
function setData(app: App, data: Ref<unknown>): void {
|
||||
app.provide(key, data)
|
||||
}
|
||||
20
renderer/usePageContext.ts
Normal file
20
renderer/usePageContext.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
// https://vike.dev/usePageContext
|
||||
export { usePageContext }
|
||||
export { setPageContext }
|
||||
|
||||
import { inject } from 'vue'
|
||||
import type { App, InjectionKey, Ref } from 'vue'
|
||||
import type { PageContext } from 'vike/types'
|
||||
|
||||
const key: InjectionKey<Ref<PageContext>> = Symbol()
|
||||
|
||||
/** https://vike.dev/usePageContext */
|
||||
function usePageContext(): Ref<PageContext> {
|
||||
const pageContext = inject(key)
|
||||
if (!pageContext) throw new Error('setPageContext() not called in parent')
|
||||
return pageContext
|
||||
}
|
||||
|
||||
function setPageContext(app: App, pageContext: Ref<PageContext>): void {
|
||||
app.provide(key, pageContext)
|
||||
}
|
||||
7
renderer/utils.ts
Normal file
7
renderer/utils.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
// Same as Object.assign() but with type inference
|
||||
export function objectAssign<Obj extends object, ObjAddendum>(
|
||||
obj: Obj,
|
||||
objAddendum: ObjAddendum
|
||||
): asserts obj is Obj & ObjAddendum {
|
||||
Object.assign(obj, objAddendum)
|
||||
}
|
||||
Reference in New Issue
Block a user