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.
Files changed (106) hide show
  1. package/.testRun.ts +32 -6
  2. package/boilerplate-react/package.json +3 -2
  3. package/boilerplate-react/pages/_error/+Page.jsx +27 -20
  4. package/boilerplate-react/pages/index/+Page.jsx +2 -2
  5. package/boilerplate-react/pages/index/Counter.jsx +2 -2
  6. package/boilerplate-react/pages/star-wars/@id/+Page.jsx +17 -0
  7. package/boilerplate-react/pages/star-wars/@id/+data.js +33 -0
  8. package/boilerplate-react/pages/star-wars/index/+Page.jsx +25 -0
  9. package/boilerplate-react/pages/star-wars/index/+data.js +35 -0
  10. package/boilerplate-react/renderer/+config.h.js +13 -5
  11. package/boilerplate-react/renderer/+onPageTransitionEnd.js +7 -0
  12. package/boilerplate-react/renderer/+onPageTransitionStart.js +7 -0
  13. package/boilerplate-react/renderer/+onRenderClient.jsx +24 -11
  14. package/boilerplate-react/renderer/+onRenderHtml.jsx +11 -8
  15. package/boilerplate-react/renderer/Link.jsx +4 -1
  16. package/boilerplate-react/renderer/PageShell.css +4 -16
  17. package/boilerplate-react/renderer/PageShell.jsx +24 -23
  18. package/boilerplate-react/renderer/css/code.css +6 -0
  19. package/boilerplate-react/renderer/css/index.css +4 -0
  20. package/boilerplate-react/renderer/css/links.css +3 -0
  21. package/boilerplate-react/renderer/css/page-transition-loading-animation/loading.svg +5 -0
  22. package/boilerplate-react/renderer/css/page-transition-loading-animation.css +26 -0
  23. package/boilerplate-react/renderer/css/reset.css +7 -0
  24. package/boilerplate-react/renderer/getPageTitle.js +12 -0
  25. package/boilerplate-react/renderer/useData.js +10 -0
  26. package/boilerplate-react/renderer/usePageContext.jsx +5 -6
  27. package/boilerplate-react/server/index.js +3 -0
  28. package/boilerplate-react-ts/package.json +3 -2
  29. package/boilerplate-react-ts/pages/_error/+Page.tsx +27 -15
  30. package/boilerplate-react-ts/pages/index/+Page.tsx +2 -2
  31. package/boilerplate-react-ts/pages/index/Counter.tsx +2 -2
  32. package/boilerplate-react-ts/pages/star-wars/@id/+Page.tsx +18 -0
  33. package/boilerplate-react-ts/pages/star-wars/@id/+data.ts +36 -0
  34. package/boilerplate-react-ts/pages/star-wars/index/+Page.tsx +26 -0
  35. package/boilerplate-react-ts/pages/star-wars/index/+data.ts +38 -0
  36. package/boilerplate-react-ts/pages/star-wars/types.ts +12 -0
  37. package/boilerplate-react-ts/renderer/+config.h.ts +13 -5
  38. package/boilerplate-react-ts/renderer/+onPageTransitionEnd.ts +9 -0
  39. package/boilerplate-react-ts/renderer/+onPageTransitionStart.ts +9 -0
  40. package/boilerplate-react-ts/renderer/+onRenderClient.tsx +23 -10
  41. package/boilerplate-react-ts/renderer/+onRenderHtml.tsx +10 -7
  42. package/boilerplate-react-ts/renderer/Link.tsx +5 -2
  43. package/boilerplate-react-ts/renderer/PageShell.css +4 -16
  44. package/boilerplate-react-ts/renderer/PageShell.tsx +23 -22
  45. package/boilerplate-react-ts/renderer/css/code.css +6 -0
  46. package/boilerplate-react-ts/renderer/css/index.css +4 -0
  47. package/boilerplate-react-ts/renderer/css/links.css +3 -0
  48. package/boilerplate-react-ts/renderer/css/page-transition-loading-animation/loading.svg +5 -0
  49. package/boilerplate-react-ts/renderer/css/page-transition-loading-animation.css +26 -0
  50. package/boilerplate-react-ts/renderer/css/reset.css +7 -0
  51. package/boilerplate-react-ts/renderer/getPageTitle.ts +14 -0
  52. package/boilerplate-react-ts/renderer/types.ts +16 -12
  53. package/boilerplate-react-ts/renderer/useData.ts +10 -0
  54. package/boilerplate-react-ts/renderer/usePageContext.tsx +5 -6
  55. package/boilerplate-react-ts/server/index.ts +3 -0
  56. package/boilerplate-vue/package.json +2 -1
  57. package/boilerplate-vue/pages/_error/+Page.vue +19 -8
  58. package/boilerplate-vue/pages/star-wars/@id/+Page.vue +13 -0
  59. package/boilerplate-vue/pages/star-wars/@id/+data.js +33 -0
  60. package/boilerplate-vue/pages/star-wars/index/+Page.vue +15 -0
  61. package/boilerplate-vue/pages/star-wars/index/+data.js +34 -0
  62. package/boilerplate-vue/renderer/+config.h.js +13 -5
  63. package/boilerplate-vue/renderer/+onPageTransitionEnd.js +7 -0
  64. package/boilerplate-vue/renderer/+onPageTransitionStart.js +7 -0
  65. package/boilerplate-vue/renderer/+onRenderClient.js +13 -6
  66. package/boilerplate-vue/renderer/+onRenderHtml.js +8 -8
  67. package/boilerplate-vue/renderer/Link.vue +10 -2
  68. package/boilerplate-vue/renderer/PageShell.vue +17 -19
  69. package/boilerplate-vue/renderer/app.js +31 -10
  70. package/boilerplate-vue/renderer/css/code.css +6 -0
  71. package/boilerplate-vue/renderer/css/index.css +4 -0
  72. package/boilerplate-vue/renderer/css/links.css +3 -0
  73. package/boilerplate-vue/renderer/css/page-transition-loading-animation/loading.svg +5 -0
  74. package/boilerplate-vue/renderer/css/page-transition-loading-animation.css +26 -0
  75. package/boilerplate-vue/renderer/css/reset.css +7 -0
  76. package/boilerplate-vue/renderer/getPageTitle.js +12 -0
  77. package/boilerplate-vue/renderer/useData.js +11 -0
  78. package/boilerplate-vue/renderer/usePageContext.js +5 -5
  79. package/boilerplate-vue/server/index.js +3 -0
  80. package/boilerplate-vue-ts/package.json +2 -1
  81. package/boilerplate-vue-ts/pages/_error/+Page.vue +19 -8
  82. package/boilerplate-vue-ts/pages/star-wars/@id/+Page.vue +14 -0
  83. package/boilerplate-vue-ts/pages/star-wars/@id/+data.ts +36 -0
  84. package/boilerplate-vue-ts/pages/star-wars/index/+Page.vue +16 -0
  85. package/boilerplate-vue-ts/pages/star-wars/index/+data.ts +37 -0
  86. package/boilerplate-vue-ts/pages/star-wars/types.ts +12 -0
  87. package/boilerplate-vue-ts/renderer/+config.h.ts +13 -5
  88. package/boilerplate-vue-ts/renderer/+onPageTransitionEnd.ts +9 -0
  89. package/boilerplate-vue-ts/renderer/+onPageTransitionStart.ts +9 -0
  90. package/boilerplate-vue-ts/renderer/+onRenderClient.ts +13 -6
  91. package/boilerplate-vue-ts/renderer/+onRenderHtml.ts +8 -8
  92. package/boilerplate-vue-ts/renderer/Link.vue +10 -2
  93. package/boilerplate-vue-ts/renderer/PageShell.vue +17 -19
  94. package/boilerplate-vue-ts/renderer/app.ts +38 -9
  95. package/boilerplate-vue-ts/renderer/css/code.css +6 -0
  96. package/boilerplate-vue-ts/renderer/css/index.css +4 -0
  97. package/boilerplate-vue-ts/renderer/css/links.css +3 -0
  98. package/boilerplate-vue-ts/renderer/css/page-transition-loading-animation/loading.svg +5 -0
  99. package/boilerplate-vue-ts/renderer/css/page-transition-loading-animation.css +26 -0
  100. package/boilerplate-vue-ts/renderer/css/reset.css +7 -0
  101. package/boilerplate-vue-ts/renderer/getPageTitle.ts +14 -0
  102. package/boilerplate-vue-ts/renderer/types.ts +18 -14
  103. package/boilerplate-vue-ts/renderer/useData.ts +11 -0
  104. package/boilerplate-vue-ts/renderer/usePageContext.ts +5 -6
  105. package/boilerplate-vue-ts/server/index.ts +3 -0
  106. package/package.json +1 -1
@@ -1,14 +1,25 @@
1
1
  <template>
2
- <div v-if="is404">
3
- <h1>404 Page Not Found</h1>
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
- defineProps(['is404'])
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
- /* To enable Client-side Routing:
3
+ // https://vike.dev/clientRouting
4
4
  clientRouting: true,
5
- // !! WARNING !! Before doing so, read https://vike.dev/clientRouting */
6
-
7
- // See https://vike.dev/data-fetching
8
- passToClient: ['pageProps', 'urlPathname']
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
  }
@@ -0,0 +1,7 @@
1
+ // https://vike.dev/onPageTransitionEnd
2
+ export { onPageTransitionEnd }
3
+
4
+ async function onPageTransitionEnd() {
5
+ console.log('Page transition end')
6
+ document.querySelector('body').classList.remove('page-is-transitioning')
7
+ }
@@ -0,0 +1,7 @@
1
+ // https://vike.dev/onPageTransitionStart
2
+ export { onPageTransitionStart }
3
+
4
+ function onPageTransitionStart() {
5
+ console.log('Page transition start')
6
+ document.querySelector('body').classList.add('page-is-transitioning')
7
+ }
@@ -2,12 +2,19 @@
2
2
  export { onRenderClient }
3
3
 
4
4
  import { createApp } from './app'
5
+ import { getPageTitle } from './getPageTitle'
5
6
 
6
- // This onRenderClient() hook only supports SSR, see https://vike.dev/render-modes for how to modify onRenderClient()
7
- // to support SPA
7
+ let app
8
8
  async function onRenderClient(pageContext) {
9
- const { Page, pageProps } = pageContext
10
- if (!Page) throw new Error('Client-side render() hook expects pageContext.Page to be defined')
11
- const app = createApp(Page, pageProps, pageContext)
12
- app.mount('#app')
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
- const app = createApp(Page, pageProps, pageContext)
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
- // See https://vike.dev/head
19
- const { documentProps } = pageContext.exports
20
- const title = (documentProps && documentProps.title) || 'Vite SSR app'
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 some `pageContext` here, which is useful if we want to do page redirection https://vike.dev/page-redirection
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: pageContext.urlPathname === $attrs.href }">
2
+ <a :class="{ active: isActive }">
3
3
  <slot />
4
4
  </a>
5
5
  </template>
6
6
  <style scoped>
7
7
  a {
8
- padding: 3px 10px;
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 class="layout">
3
- <div class="navigation">
4
- <a href="/" class="logo">
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="/">Home</Link>
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 class="content"><slot /></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
- body {
20
- margin: 0;
21
- font-family: sans-serif;
21
+ #sidebar a {
22
+ padding: 2px 10px;
23
+ margin-left: -10px;
22
24
  }
23
- * {
24
- box-sizing: border-box;
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
- .layout {
31
+ #page-container {
33
32
  display: flex;
34
33
  max-width: 900px;
35
34
  margin: auto;
36
35
  }
37
- .content {
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
- .navigation {
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
- .logo {
49
+ #logo-container {
52
50
  margin-top: 20px;
53
51
  margin-bottom: 10px;
54
52
  }
@@ -1,28 +1,49 @@
1
- import { createSSRApp, h } from 'vue'
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
- export { createApp }
7
+ function createApp(pageContext) {
8
+ const { Page } = pageContext
6
9
 
7
- function createApp(Page, pageProps, pageContext) {
8
- const PageWithLayout = {
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, pageProps || {})
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
- const app = createSSRApp(PageWithLayout)
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
- // We make pageContext available from any Vue component
25
- setPageContext(app, pageContext)
45
+ // Make pageContext available from any Vue component
46
+ setPageContext(app, pageContextReactive)
26
47
 
27
48
  return app
28
49
  }
@@ -0,0 +1,6 @@
1
+ code {
2
+ font-family: monospace;
3
+ background-color: #eaeaea;
4
+ padding: 3px 5px;
5
+ border-radius: 4px;
6
+ }
@@ -0,0 +1,4 @@
1
+ @import './reset.css';
2
+ @import './links.css';
3
+ @import './code.css';
4
+ @import './page-transition-loading-animation.css';
@@ -0,0 +1,3 @@
1
+ a {
2
+ text-decoration: none;
3
+ }
@@ -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,7 @@
1
+ body {
2
+ margin: 0;
3
+ font-family: sans-serif;
4
+ }
5
+ * {
6
+ box-sizing: border-box;
7
+ }
@@ -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
- // `usePageContext` allows us to access `pageContext` in any Vue component.
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 v-if="is404">
3
- <h1>404 Page Not Found</h1>
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
- defineProps(['is404'])
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>