create-vike 0.0.320 → 0.0.322
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.testRun.ts +32 -6
- package/boilerplate-react/package.json +3 -2
- package/boilerplate-react/pages/_error/+Page.jsx +27 -20
- package/boilerplate-react/pages/index/+Page.jsx +2 -2
- package/boilerplate-react/pages/index/Counter.jsx +2 -2
- package/boilerplate-react/pages/star-wars/@id/+Page.jsx +17 -0
- package/boilerplate-react/pages/star-wars/@id/+data.js +33 -0
- package/boilerplate-react/pages/star-wars/index/+Page.jsx +25 -0
- package/boilerplate-react/pages/star-wars/index/+data.js +35 -0
- package/boilerplate-react/renderer/+config.h.js +13 -5
- package/boilerplate-react/renderer/+onPageTransitionEnd.js +7 -0
- package/boilerplate-react/renderer/+onPageTransitionStart.js +7 -0
- package/boilerplate-react/renderer/+onRenderClient.jsx +24 -11
- package/boilerplate-react/renderer/+onRenderHtml.jsx +11 -8
- package/boilerplate-react/renderer/Link.jsx +4 -1
- package/boilerplate-react/renderer/PageShell.css +4 -16
- package/boilerplate-react/renderer/PageShell.jsx +24 -23
- package/boilerplate-react/renderer/css/code.css +6 -0
- package/boilerplate-react/renderer/css/index.css +4 -0
- package/boilerplate-react/renderer/css/links.css +3 -0
- package/boilerplate-react/renderer/css/page-transition-loading-animation/loading.svg +5 -0
- package/boilerplate-react/renderer/css/page-transition-loading-animation.css +26 -0
- package/boilerplate-react/renderer/css/reset.css +7 -0
- package/boilerplate-react/renderer/getPageTitle.js +12 -0
- package/boilerplate-react/renderer/useData.js +10 -0
- package/boilerplate-react/renderer/usePageContext.jsx +5 -6
- package/boilerplate-react/server/index.js +3 -0
- package/boilerplate-react-ts/package.json +3 -2
- package/boilerplate-react-ts/pages/_error/+Page.tsx +27 -15
- package/boilerplate-react-ts/pages/index/+Page.tsx +2 -2
- package/boilerplate-react-ts/pages/index/Counter.tsx +2 -2
- package/boilerplate-react-ts/pages/star-wars/@id/+Page.tsx +18 -0
- package/boilerplate-react-ts/pages/star-wars/@id/+data.ts +36 -0
- package/boilerplate-react-ts/pages/star-wars/index/+Page.tsx +26 -0
- package/boilerplate-react-ts/pages/star-wars/index/+data.ts +38 -0
- package/boilerplate-react-ts/pages/star-wars/types.ts +12 -0
- package/boilerplate-react-ts/renderer/+config.h.ts +13 -5
- package/boilerplate-react-ts/renderer/+onPageTransitionEnd.ts +9 -0
- package/boilerplate-react-ts/renderer/+onPageTransitionStart.ts +9 -0
- package/boilerplate-react-ts/renderer/+onRenderClient.tsx +23 -10
- package/boilerplate-react-ts/renderer/+onRenderHtml.tsx +10 -7
- package/boilerplate-react-ts/renderer/Link.tsx +5 -2
- package/boilerplate-react-ts/renderer/PageShell.css +4 -16
- package/boilerplate-react-ts/renderer/PageShell.tsx +23 -22
- package/boilerplate-react-ts/renderer/css/code.css +6 -0
- package/boilerplate-react-ts/renderer/css/index.css +4 -0
- package/boilerplate-react-ts/renderer/css/links.css +3 -0
- package/boilerplate-react-ts/renderer/css/page-transition-loading-animation/loading.svg +5 -0
- package/boilerplate-react-ts/renderer/css/page-transition-loading-animation.css +26 -0
- package/boilerplate-react-ts/renderer/css/reset.css +7 -0
- package/boilerplate-react-ts/renderer/getPageTitle.ts +14 -0
- package/boilerplate-react-ts/renderer/types.ts +16 -12
- package/boilerplate-react-ts/renderer/useData.ts +10 -0
- package/boilerplate-react-ts/renderer/usePageContext.tsx +5 -6
- package/boilerplate-react-ts/server/index.ts +3 -0
- package/boilerplate-vue/package.json +2 -1
- package/boilerplate-vue/pages/_error/+Page.vue +19 -8
- package/boilerplate-vue/pages/star-wars/@id/+Page.vue +13 -0
- package/boilerplate-vue/pages/star-wars/@id/+data.js +33 -0
- package/boilerplate-vue/pages/star-wars/index/+Page.vue +15 -0
- package/boilerplate-vue/pages/star-wars/index/+data.js +34 -0
- package/boilerplate-vue/renderer/+config.h.js +13 -5
- package/boilerplate-vue/renderer/+onPageTransitionEnd.js +7 -0
- package/boilerplate-vue/renderer/+onPageTransitionStart.js +7 -0
- package/boilerplate-vue/renderer/+onRenderClient.js +13 -6
- package/boilerplate-vue/renderer/+onRenderHtml.js +8 -8
- package/boilerplate-vue/renderer/Link.vue +10 -2
- package/boilerplate-vue/renderer/PageShell.vue +17 -19
- package/boilerplate-vue/renderer/app.js +31 -10
- package/boilerplate-vue/renderer/css/code.css +6 -0
- package/boilerplate-vue/renderer/css/index.css +4 -0
- package/boilerplate-vue/renderer/css/links.css +3 -0
- package/boilerplate-vue/renderer/css/page-transition-loading-animation/loading.svg +5 -0
- package/boilerplate-vue/renderer/css/page-transition-loading-animation.css +26 -0
- package/boilerplate-vue/renderer/css/reset.css +7 -0
- package/boilerplate-vue/renderer/getPageTitle.js +12 -0
- package/boilerplate-vue/renderer/useData.js +11 -0
- package/boilerplate-vue/renderer/usePageContext.js +5 -5
- package/boilerplate-vue/server/index.js +3 -0
- package/boilerplate-vue-ts/package.json +2 -1
- package/boilerplate-vue-ts/pages/_error/+Page.vue +19 -8
- package/boilerplate-vue-ts/pages/star-wars/@id/+Page.vue +14 -0
- package/boilerplate-vue-ts/pages/star-wars/@id/+data.ts +36 -0
- package/boilerplate-vue-ts/pages/star-wars/index/+Page.vue +16 -0
- package/boilerplate-vue-ts/pages/star-wars/index/+data.ts +37 -0
- package/boilerplate-vue-ts/pages/star-wars/types.ts +12 -0
- package/boilerplate-vue-ts/renderer/+config.h.ts +13 -5
- package/boilerplate-vue-ts/renderer/+onPageTransitionEnd.ts +9 -0
- package/boilerplate-vue-ts/renderer/+onPageTransitionStart.ts +9 -0
- package/boilerplate-vue-ts/renderer/+onRenderClient.ts +13 -6
- package/boilerplate-vue-ts/renderer/+onRenderHtml.ts +8 -8
- package/boilerplate-vue-ts/renderer/Link.vue +10 -2
- package/boilerplate-vue-ts/renderer/PageShell.vue +17 -19
- package/boilerplate-vue-ts/renderer/app.ts +38 -9
- package/boilerplate-vue-ts/renderer/css/code.css +6 -0
- package/boilerplate-vue-ts/renderer/css/index.css +4 -0
- package/boilerplate-vue-ts/renderer/css/links.css +3 -0
- package/boilerplate-vue-ts/renderer/css/page-transition-loading-animation/loading.svg +5 -0
- package/boilerplate-vue-ts/renderer/css/page-transition-loading-animation.css +26 -0
- package/boilerplate-vue-ts/renderer/css/reset.css +7 -0
- package/boilerplate-vue-ts/renderer/getPageTitle.ts +14 -0
- package/boilerplate-vue-ts/renderer/types.ts +18 -14
- package/boilerplate-vue-ts/renderer/useData.ts +11 -0
- package/boilerplate-vue-ts/renderer/usePageContext.ts +5 -6
- package/boilerplate-vue-ts/server/index.ts +3 -0
- package/package.json +1 -1
|
@@ -1,14 +1,25 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
3
|
-
<
|
|
4
|
-
<p>This page could not be found.</p>
|
|
5
|
-
</div>
|
|
6
|
-
<div v-else>
|
|
7
|
-
<h1>500 Internal Error</h1>
|
|
8
|
-
<p>Something went wrong.</p>
|
|
2
|
+
<div class="center">
|
|
3
|
+
<p>{{ abortReason }}</p>
|
|
9
4
|
</div>
|
|
10
5
|
</template>
|
|
11
6
|
|
|
12
7
|
<script setup>
|
|
13
|
-
|
|
8
|
+
import { usePageContext } from '../../renderer/usePageContext'
|
|
9
|
+
|
|
10
|
+
const pageContext = usePageContext()
|
|
11
|
+
let { is404, abortReason } = pageContext
|
|
12
|
+
if (!abortReason) {
|
|
13
|
+
abortReason = is404 ? 'Page not found.' : 'Something went wrong.'
|
|
14
|
+
}
|
|
14
15
|
</script>
|
|
16
|
+
|
|
17
|
+
<style>
|
|
18
|
+
.center {
|
|
19
|
+
height: calc(100vh - 100px);
|
|
20
|
+
display: flex;
|
|
21
|
+
font-size: 1.3em;
|
|
22
|
+
justify-content: center;
|
|
23
|
+
align-items: center;
|
|
24
|
+
}
|
|
25
|
+
</style>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<h1>{{ data.movie.title }}</h1>
|
|
3
|
+
Release Date: {{ data.movie.release_date }}
|
|
4
|
+
<br />
|
|
5
|
+
Director: {{ data.movie.director }}
|
|
6
|
+
<br />
|
|
7
|
+
Producer: {{ data.movie.producer }}
|
|
8
|
+
</template>
|
|
9
|
+
|
|
10
|
+
<script setup>
|
|
11
|
+
import { useData } from '../../../renderer/useData'
|
|
12
|
+
const data = useData()
|
|
13
|
+
</script>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// https://vike.dev/data
|
|
2
|
+
export { data }
|
|
3
|
+
|
|
4
|
+
// The node-fetch package (which only works on the server-side) can be used since
|
|
5
|
+
// this file always runs on the server-side, see https://vike.dev/data#server-side
|
|
6
|
+
import fetch from 'node-fetch'
|
|
7
|
+
|
|
8
|
+
const data = async (pageContext) => {
|
|
9
|
+
await sleep(300) // Simulate slow network
|
|
10
|
+
|
|
11
|
+
const response = await fetch(`https://brillout.github.io/star-wars/api/films/${pageContext.routeParams.id}.json`)
|
|
12
|
+
let movie = await response.json()
|
|
13
|
+
|
|
14
|
+
// We remove data we don't need because the data is passed to the client; we should
|
|
15
|
+
// minimize what is sent over the network.
|
|
16
|
+
movie = minimize(movie)
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
movie,
|
|
20
|
+
// The page's <title>
|
|
21
|
+
title: movie.title
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function minimize(movie) {
|
|
26
|
+
const { id, title, release_date, director, producer } = movie
|
|
27
|
+
movie = { id, title, release_date, director, producer }
|
|
28
|
+
return movie
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function sleep(milliseconds) {
|
|
32
|
+
return new Promise((r) => setTimeout(r, milliseconds))
|
|
33
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<h1>Star Wars Movies</h1>
|
|
3
|
+
<ol>
|
|
4
|
+
<li v-for="item in data.movies" :key="item.id">
|
|
5
|
+
<a :href="'/star-wars/' + item.id">{{ item.title }}</a> ({{ item.release_date }})
|
|
6
|
+
</li>
|
|
7
|
+
</ol>
|
|
8
|
+
<p>Source: <a href="https://brillout.github.io/star-wars/">brillout.github.io/star-wars</a>.</p>
|
|
9
|
+
<p>Data can be fetched by using the <code>data()</code> hook.</p>
|
|
10
|
+
</template>
|
|
11
|
+
|
|
12
|
+
<script setup>
|
|
13
|
+
import { useData } from '../../../renderer/useData'
|
|
14
|
+
const data = useData()
|
|
15
|
+
</script>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// https://vike.dev/data
|
|
2
|
+
export { data }
|
|
3
|
+
|
|
4
|
+
// The node-fetch package (which only works on the server-side) can be used since
|
|
5
|
+
// this file always runs on the server-side, see https://vike.dev/data#server-side
|
|
6
|
+
import fetch from 'node-fetch'
|
|
7
|
+
|
|
8
|
+
const data = async (pageContext) => {
|
|
9
|
+
await sleep(700) // Simulate slow network
|
|
10
|
+
|
|
11
|
+
const response = await fetch('https://brillout.github.io/star-wars/api/films.json')
|
|
12
|
+
const moviesData = await response.json()
|
|
13
|
+
|
|
14
|
+
// We remove data we don't need because the data is passed to the client; we should
|
|
15
|
+
// minimize what is sent over the network.
|
|
16
|
+
const movies = minimize(moviesData)
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
movies,
|
|
20
|
+
// The page's <title>
|
|
21
|
+
title: `${movies.length} Star Wars Movies`
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function minimize(movies) {
|
|
26
|
+
return movies.map((movie) => {
|
|
27
|
+
const { title, release_date, id } = movie
|
|
28
|
+
return { title, release_date, id }
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function sleep(milliseconds) {
|
|
33
|
+
return new Promise((r) => setTimeout(r, milliseconds))
|
|
34
|
+
}
|
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
// https://vike.dev/config
|
|
2
2
|
export default {
|
|
3
|
-
|
|
3
|
+
// https://vike.dev/clientRouting
|
|
4
4
|
clientRouting: true,
|
|
5
|
-
//
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
// https://vike.dev/meta
|
|
6
|
+
meta: {
|
|
7
|
+
// Define new setting 'title'
|
|
8
|
+
title: {
|
|
9
|
+
env: { server: true, client: true }
|
|
10
|
+
},
|
|
11
|
+
// Define new setting 'description'
|
|
12
|
+
description: {
|
|
13
|
+
env: { server: true }
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
hydrationCanBeAborted: true
|
|
9
17
|
}
|
|
@@ -2,12 +2,19 @@
|
|
|
2
2
|
export { onRenderClient }
|
|
3
3
|
|
|
4
4
|
import { createApp } from './app'
|
|
5
|
+
import { getPageTitle } from './getPageTitle'
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
// to support SPA
|
|
7
|
+
let app
|
|
8
8
|
async function onRenderClient(pageContext) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
// This onRenderClient() hook only supports SSR, see https://vike.dev/render-modes for how to modify onRenderClient()
|
|
10
|
+
// to support SPA
|
|
11
|
+
if (!pageContext.Page) throw new Error('My onRenderClient() hook expects pageContext.Page to be defined')
|
|
12
|
+
|
|
13
|
+
if (!app) {
|
|
14
|
+
app = createApp(pageContext)
|
|
15
|
+
app.mount('#app')
|
|
16
|
+
} else {
|
|
17
|
+
app.changePage(pageContext)
|
|
18
|
+
}
|
|
19
|
+
document.title = getPageTitle(pageContext)
|
|
13
20
|
}
|
|
@@ -5,20 +5,20 @@ import { renderToString as renderToString_ } from '@vue/server-renderer'
|
|
|
5
5
|
import { escapeInject, dangerouslySkipEscape } from 'vike/server'
|
|
6
6
|
import { createApp } from './app'
|
|
7
7
|
import logoUrl from './logo.svg'
|
|
8
|
+
import { getPageTitle } from './getPageTitle'
|
|
8
9
|
|
|
9
10
|
async function onRenderHtml(pageContext) {
|
|
10
|
-
const { Page, pageProps } = pageContext
|
|
11
11
|
// This onRenderHtml() hook only supports SSR, see https://vike.dev/render-modes for how to modify
|
|
12
12
|
// onRenderHtml() to support SPA
|
|
13
|
-
if (!Page) throw new Error('My render() hook expects pageContext.Page to be defined')
|
|
14
|
-
|
|
13
|
+
if (!pageContext.Page) throw new Error('My render() hook expects pageContext.Page to be defined')
|
|
14
|
+
|
|
15
|
+
const app = createApp(pageContext)
|
|
15
16
|
|
|
16
17
|
const appHtml = await renderToString(app)
|
|
17
18
|
|
|
18
|
-
//
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
const desc = (documentProps && documentProps.description) || 'App using Vite + Vike'
|
|
19
|
+
// https://vike.dev/head
|
|
20
|
+
const title = getPageTitle(pageContext)
|
|
21
|
+
const desc = pageContext.data?.description || pageContext.config.description || 'Demo of using Vike'
|
|
22
22
|
|
|
23
23
|
const documentHtml = escapeInject`<!DOCTYPE html>
|
|
24
24
|
<html lang="en">
|
|
@@ -37,7 +37,7 @@ async function onRenderHtml(pageContext) {
|
|
|
37
37
|
return {
|
|
38
38
|
documentHtml,
|
|
39
39
|
pageContext: {
|
|
40
|
-
// We can add
|
|
40
|
+
// We can add custom pageContext properties here, see https://vike.dev/pageContext#custom
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
}
|
|
@@ -1,17 +1,25 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<a :class="{ active:
|
|
2
|
+
<a :class="{ active: isActive }">
|
|
3
3
|
<slot />
|
|
4
4
|
</a>
|
|
5
5
|
</template>
|
|
6
6
|
<style scoped>
|
|
7
7
|
a {
|
|
8
|
-
padding:
|
|
8
|
+
padding: 2px 10px;
|
|
9
|
+
margin-left: -10px;
|
|
9
10
|
}
|
|
10
11
|
a.active {
|
|
11
12
|
background-color: #eee;
|
|
12
13
|
}
|
|
13
14
|
</style>
|
|
14
15
|
<script setup>
|
|
16
|
+
import { useAttrs, computed } from 'vue'
|
|
15
17
|
import { usePageContext } from './usePageContext'
|
|
18
|
+
|
|
16
19
|
const pageContext = usePageContext()
|
|
20
|
+
const { href } = useAttrs()
|
|
21
|
+
const isActive = computed(() => {
|
|
22
|
+
const { urlPathname } = pageContext
|
|
23
|
+
return href === '/' ? urlPathname === href : urlPathname.startsWith(href)
|
|
24
|
+
})
|
|
17
25
|
</script>
|
|
@@ -1,54 +1,52 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
3
|
-
<div
|
|
4
|
-
<a href="/"
|
|
2
|
+
<div id="page-container">
|
|
3
|
+
<div id="sidebar">
|
|
4
|
+
<a href="/" id="logo-container">
|
|
5
5
|
<img src="./logo.svg" height="64" width="64" alt="logo" />
|
|
6
6
|
</a>
|
|
7
|
-
<Link href="/">
|
|
7
|
+
<Link href="/">Welcome</Link>
|
|
8
8
|
<Link href="/about">About</Link>
|
|
9
|
+
<Link href="/star-wars">Data Fetching</Link>
|
|
9
10
|
</div>
|
|
10
|
-
<div
|
|
11
|
+
<div id="page-content"><slot /></div>
|
|
11
12
|
</div>
|
|
12
13
|
</template>
|
|
13
14
|
|
|
14
15
|
<script setup>
|
|
15
16
|
import Link from './Link.vue'
|
|
17
|
+
import './css/index.css'
|
|
16
18
|
</script>
|
|
17
19
|
|
|
18
20
|
<style>
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
#sidebar a {
|
|
22
|
+
padding: 2px 10px;
|
|
23
|
+
margin-left: -10px;
|
|
22
24
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
a {
|
|
27
|
-
text-decoration: none;
|
|
25
|
+
#sidebar a.is-active {
|
|
26
|
+
background-color: #eee;
|
|
28
27
|
}
|
|
29
28
|
</style>
|
|
30
29
|
|
|
31
30
|
<style scoped>
|
|
32
|
-
|
|
31
|
+
#page-container {
|
|
33
32
|
display: flex;
|
|
34
33
|
max-width: 900px;
|
|
35
34
|
margin: auto;
|
|
36
35
|
}
|
|
37
|
-
|
|
36
|
+
#page-content {
|
|
38
37
|
padding: 20px;
|
|
39
|
-
border-left: 2px solid #eee;
|
|
40
38
|
padding-bottom: 50px;
|
|
41
39
|
min-height: 100vh;
|
|
42
40
|
}
|
|
43
|
-
|
|
41
|
+
#sidebar {
|
|
44
42
|
padding: 20px;
|
|
45
43
|
flex-shrink: 0;
|
|
46
44
|
display: flex;
|
|
47
45
|
flex-direction: column;
|
|
48
|
-
align-items: center;
|
|
49
46
|
line-height: 1.8em;
|
|
47
|
+
border-right: 2px solid #eee;
|
|
50
48
|
}
|
|
51
|
-
|
|
49
|
+
#logo-container {
|
|
52
50
|
margin-top: 20px;
|
|
53
51
|
margin-bottom: 10px;
|
|
54
52
|
}
|
|
@@ -1,28 +1,49 @@
|
|
|
1
|
-
|
|
1
|
+
export { createApp }
|
|
2
|
+
|
|
3
|
+
import { createSSRApp, defineComponent, h, markRaw, reactive } from 'vue'
|
|
2
4
|
import PageShell from './PageShell.vue'
|
|
3
5
|
import { setPageContext } from './usePageContext'
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
function createApp(pageContext) {
|
|
8
|
+
const { Page } = pageContext
|
|
6
9
|
|
|
7
|
-
|
|
8
|
-
const
|
|
10
|
+
let rootComponent
|
|
11
|
+
const PageWithShell = defineComponent({
|
|
12
|
+
data: () => ({
|
|
13
|
+
Page: markRaw(Page)
|
|
14
|
+
}),
|
|
15
|
+
created() {
|
|
16
|
+
rootComponent = this
|
|
17
|
+
},
|
|
9
18
|
render() {
|
|
10
19
|
return h(
|
|
11
20
|
PageShell,
|
|
12
21
|
{},
|
|
13
22
|
{
|
|
14
|
-
default() {
|
|
15
|
-
return h(Page
|
|
23
|
+
default: () => {
|
|
24
|
+
return h(this.Page)
|
|
16
25
|
}
|
|
17
26
|
}
|
|
18
27
|
)
|
|
19
28
|
}
|
|
20
|
-
}
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
const app = createSSRApp(PageWithShell)
|
|
32
|
+
|
|
33
|
+
// We use `app.changePage()` to do Client Routing, see `+onRenderClient.ts`
|
|
34
|
+
Object.assign(app, {
|
|
35
|
+
changePage: (pageContext) => {
|
|
36
|
+
Object.assign(pageContextReactive, pageContext)
|
|
37
|
+
rootComponent.Page = markRaw(pageContext.Page)
|
|
38
|
+
}
|
|
39
|
+
})
|
|
21
40
|
|
|
22
|
-
|
|
41
|
+
// When doing Client Routing, we mutate pageContext (see usage of `app.changePage()` in `+onRenderClient.ts`).
|
|
42
|
+
// We therefore use a reactive pageContext.
|
|
43
|
+
const pageContextReactive = reactive(pageContext)
|
|
23
44
|
|
|
24
|
-
//
|
|
25
|
-
setPageContext(app,
|
|
45
|
+
// Make pageContext available from any Vue component
|
|
46
|
+
setPageContext(app, pageContextReactive)
|
|
26
47
|
|
|
27
48
|
return app
|
|
28
49
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
<svg version="1.1" id="L9" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 0 0" xml:space="preserve">
|
|
2
|
+
<path fill="#aaa" d="M73,50c0-12.7-10.3-23-23-23S27,37.3,27,50 M30.9,50c0-10.5,8.5-19.1,19.1-19.1S69.1,39.5,69.1,50">
|
|
3
|
+
<animateTransform attributeName="transform" attributeType="XML" type="rotate" dur="1s" from="0 50 50" to="360 50 50" repeatCount="indefinite"></animateTransform>
|
|
4
|
+
</path>
|
|
5
|
+
</svg>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#page-container {
|
|
2
|
+
position: relative;
|
|
3
|
+
width: 100%;
|
|
4
|
+
}
|
|
5
|
+
#page-container::before {
|
|
6
|
+
content: '';
|
|
7
|
+
position: absolute;
|
|
8
|
+
width: 100%;
|
|
9
|
+
height: 100%;
|
|
10
|
+
z-index: 999;
|
|
11
|
+
background: no-repeat url('./page-transition-loading-animation/loading.svg');
|
|
12
|
+
background-size: 100px;
|
|
13
|
+
background-position: center center;
|
|
14
|
+
pointer-events: none;
|
|
15
|
+
opacity: 0;
|
|
16
|
+
}
|
|
17
|
+
body.page-is-transitioning #page-container::before {
|
|
18
|
+
opacity: 1;
|
|
19
|
+
}
|
|
20
|
+
#page-content,
|
|
21
|
+
#page-container::before {
|
|
22
|
+
transition: opacity 0.5s ease-in-out;
|
|
23
|
+
}
|
|
24
|
+
body.page-is-transitioning #page-content {
|
|
25
|
+
opacity: 0.17;
|
|
26
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { getPageTitle }
|
|
2
|
+
|
|
3
|
+
function getPageTitle(pageContext) {
|
|
4
|
+
const title =
|
|
5
|
+
// Title defined dynamically by data()
|
|
6
|
+
pageContext.data?.title ||
|
|
7
|
+
// Title defined statically by /pages/some-page/+title.js (or by `export default { title }` in /pages/some-page/+config.js)
|
|
8
|
+
// The setting 'pageContext.config.title' is a custom setting we defined at ./+config.ts
|
|
9
|
+
pageContext.config.title ||
|
|
10
|
+
'Vike Demo'
|
|
11
|
+
return title
|
|
12
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// https://vike.dev/useData
|
|
2
|
+
export { useData }
|
|
3
|
+
|
|
4
|
+
import { computed } from 'vue'
|
|
5
|
+
import { usePageContext } from './usePageContext'
|
|
6
|
+
|
|
7
|
+
/** https://vike.dev/useData */
|
|
8
|
+
function useData() {
|
|
9
|
+
const data = computed(() => usePageContext().data)
|
|
10
|
+
return data
|
|
11
|
+
}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
//
|
|
2
|
-
// See https://vike.dev/pageContext-anywhere
|
|
3
|
-
|
|
4
|
-
import { inject } from 'vue'
|
|
5
|
-
|
|
1
|
+
// https://vike.dev/usePageContext
|
|
6
2
|
export { usePageContext }
|
|
7
3
|
export { setPageContext }
|
|
8
4
|
|
|
5
|
+
import { inject } from 'vue'
|
|
6
|
+
|
|
9
7
|
const key = Symbol()
|
|
10
8
|
|
|
9
|
+
/** https://vike.dev/usePageContext */
|
|
11
10
|
function usePageContext() {
|
|
12
11
|
const pageContext = inject(key)
|
|
12
|
+
if (!pageContext) throw new Error('setPageContext() not called in parent')
|
|
13
13
|
return pageContext
|
|
14
14
|
}
|
|
15
15
|
|
|
@@ -55,6 +55,9 @@ async function startServer() {
|
|
|
55
55
|
urlOriginal: req.originalUrl
|
|
56
56
|
}
|
|
57
57
|
const pageContext = await renderPage(pageContextInit)
|
|
58
|
+
if (pageContext.errorWhileRendering) {
|
|
59
|
+
// Install error tracking here, see https://vike.dev/errors
|
|
60
|
+
}
|
|
58
61
|
const { httpResponse } = pageContext
|
|
59
62
|
if (!httpResponse) {
|
|
60
63
|
return next()
|
|
@@ -17,11 +17,12 @@
|
|
|
17
17
|
"compression": "^1.7.4",
|
|
18
18
|
"cross-env": "^7.0.3",
|
|
19
19
|
"express": "^4.18.2",
|
|
20
|
+
"node-fetch": "^3.3.2",
|
|
20
21
|
"sirv": "^2.0.3",
|
|
21
22
|
"ts-node": "^10.9.1",
|
|
22
23
|
"typescript": "^5.3.3",
|
|
24
|
+
"vike": "^0.4.157",
|
|
23
25
|
"vite": "^5.0.10",
|
|
24
|
-
"vike": "^0.4.156",
|
|
25
26
|
"vue": "^3.3.10"
|
|
26
27
|
},
|
|
27
28
|
"type": "module"
|
|
@@ -1,14 +1,25 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
3
|
-
<
|
|
4
|
-
<p>This page could not be found.</p>
|
|
5
|
-
</div>
|
|
6
|
-
<div v-else>
|
|
7
|
-
<h1>500 Internal Error</h1>
|
|
8
|
-
<p>Something went wrong.</p>
|
|
2
|
+
<div class="center">
|
|
3
|
+
<p>{{ abortReason }}</p>
|
|
9
4
|
</div>
|
|
10
5
|
</template>
|
|
11
6
|
|
|
12
7
|
<script lang="ts" setup>
|
|
13
|
-
|
|
8
|
+
import { usePageContext } from '../../renderer/usePageContext'
|
|
9
|
+
|
|
10
|
+
const pageContext = usePageContext()
|
|
11
|
+
let { is404, abortReason } = pageContext
|
|
12
|
+
if (!abortReason) {
|
|
13
|
+
abortReason = is404 ? 'Page not found.' : 'Something went wrong.'
|
|
14
|
+
}
|
|
14
15
|
</script>
|
|
16
|
+
|
|
17
|
+
<style>
|
|
18
|
+
.center {
|
|
19
|
+
height: calc(100vh - 100px);
|
|
20
|
+
display: flex;
|
|
21
|
+
font-size: 1.3em;
|
|
22
|
+
justify-content: center;
|
|
23
|
+
align-items: center;
|
|
24
|
+
}
|
|
25
|
+
</style>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<h1>{{ data.movie.title }}</h1>
|
|
3
|
+
Release Date: {{ data.movie.release_date }}
|
|
4
|
+
<br />
|
|
5
|
+
Director: {{ data.movie.director }}
|
|
6
|
+
<br />
|
|
7
|
+
Producer: {{ data.movie.producer }}
|
|
8
|
+
</template>
|
|
9
|
+
|
|
10
|
+
<script lang="ts" setup>
|
|
11
|
+
import type { Data } from './+data'
|
|
12
|
+
import { useData } from '../../../renderer/useData'
|
|
13
|
+
const data = useData<Data>()
|
|
14
|
+
</script>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// https://vike.dev/data
|
|
2
|
+
export { data }
|
|
3
|
+
export type Data = Awaited<ReturnType<typeof data>>
|
|
4
|
+
|
|
5
|
+
// The node-fetch package (which only works on the server-side) can be used since
|
|
6
|
+
// this file always runs on the server-side, see https://vike.dev/data#server-side
|
|
7
|
+
import fetch from 'node-fetch'
|
|
8
|
+
import type { MovieDetails } from '../types'
|
|
9
|
+
import type { PageContextServer } from 'vike/types'
|
|
10
|
+
|
|
11
|
+
const data = async (pageContext: PageContextServer) => {
|
|
12
|
+
await sleep(300) // Simulate slow network
|
|
13
|
+
|
|
14
|
+
const response = await fetch(`https://brillout.github.io/star-wars/api/films/${pageContext.routeParams!.id}.json`)
|
|
15
|
+
let movie = (await response.json()) as MovieDetails
|
|
16
|
+
|
|
17
|
+
// We remove data we don't need because the data is passed to the client; we should
|
|
18
|
+
// minimize what is sent over the network.
|
|
19
|
+
movie = minimize(movie)
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
movie,
|
|
23
|
+
// The page's <title>
|
|
24
|
+
title: movie.title
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function minimize(movie: MovieDetails & Record<string, unknown>): MovieDetails {
|
|
29
|
+
const { id, title, release_date, director, producer } = movie
|
|
30
|
+
movie = { id, title, release_date, director, producer }
|
|
31
|
+
return movie
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function sleep(milliseconds: number) {
|
|
35
|
+
return new Promise((r) => setTimeout(r, milliseconds))
|
|
36
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<h1>Star Wars Movies</h1>
|
|
3
|
+
<ol>
|
|
4
|
+
<li v-for="item in data.movies" :key="item.id">
|
|
5
|
+
<a :href="'/star-wars/' + item.id">{{ item.title }}</a> ({{ item.release_date }})
|
|
6
|
+
</li>
|
|
7
|
+
</ol>
|
|
8
|
+
<p>Source: <a href="https://brillout.github.io/star-wars/">brillout.github.io/star-wars</a>.</p>
|
|
9
|
+
<p>Data can be fetched by using the <code>data()</code> hook.</p>
|
|
10
|
+
</template>
|
|
11
|
+
|
|
12
|
+
<script lang="ts" setup>
|
|
13
|
+
import type { Data } from './+data'
|
|
14
|
+
import { useData } from '../../../renderer/useData'
|
|
15
|
+
const data = useData<Data>()
|
|
16
|
+
</script>
|