create-vike 0.0.4 → 0.0.304
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 +118 -0
- package/boilerplate-react/.eslintrc.cjs +17 -0
- package/boilerplate-react/.test-dev.test.ts +2 -0
- package/boilerplate-react/.test-prod.test.ts +2 -0
- package/boilerplate-react/.testCiJob.json +1 -0
- package/boilerplate-react/_gitignore +2 -0
- package/boilerplate-react/package.json +27 -0
- package/boilerplate-react/pages/about/code.css +6 -0
- package/boilerplate-react/pages/about/index.page.jsx +14 -0
- package/{files/js/react → boilerplate-react}/pages/index/Counter.jsx +4 -4
- package/{files/js/react → boilerplate-react}/pages/index/index.page.jsx +3 -4
- package/boilerplate-react/renderer/Link.jsx +14 -0
- package/boilerplate-react/renderer/PageShell.css +19 -0
- package/{files/js/react/renderer/PageWrapper.jsx → boilerplate-react/renderer/PageShell.jsx} +36 -21
- package/boilerplate-react/renderer/PropTypeValues.js +3 -0
- package/boilerplate-react/renderer/_default.page.client.jsx +22 -0
- package/boilerplate-react/renderer/_default.page.server.jsx +45 -0
- package/{files/js/react → boilerplate-react}/renderer/_error.page.jsx +8 -5
- package/boilerplate-react/renderer/logo.svg +36 -0
- package/boilerplate-react/renderer/usePageContext.jsx +25 -0
- package/boilerplate-react/server/index.js +74 -0
- package/boilerplate-react/server/root.js +8 -0
- package/boilerplate-react/vite.config.js +6 -0
- package/boilerplate-react-ts/.eslintrc.cjs +19 -0
- package/boilerplate-react-ts/.test-dev.test.ts +2 -0
- package/boilerplate-react-ts/.test-prod.test.ts +2 -0
- package/boilerplate-react-ts/.testCiJob.json +1 -0
- package/boilerplate-react-ts/_gitignore +2 -0
- package/boilerplate-react-ts/package.json +36 -0
- package/boilerplate-react-ts/pages/about/code.css +6 -0
- package/boilerplate-react-ts/pages/about/index.page.tsx +14 -0
- package/{files/ts/react → boilerplate-react-ts}/pages/index/Counter.tsx +4 -4
- package/{files/ts/react → boilerplate-react-ts}/pages/index/index.page.tsx +3 -4
- package/boilerplate-react-ts/renderer/Link.tsx +9 -0
- package/{files/ts/react/renderer/PageWrapper.tsx → boilerplate-react-ts/renderer/PageShell.tsx} +22 -28
- package/boilerplate-react-ts/renderer/_default.page.client.tsx +23 -0
- package/boilerplate-react-ts/renderer/_default.page.server.tsx +46 -0
- package/{files/ts/react → boilerplate-react-ts}/renderer/_error.page.tsx +4 -6
- package/boilerplate-react-ts/renderer/types.ts +35 -0
- package/boilerplate-react-ts/renderer/usePageContext.tsx +20 -0
- package/boilerplate-react-ts/server/index.ts +74 -0
- package/boilerplate-react-ts/server/root.ts +8 -0
- package/boilerplate-react-ts/server/tsconfig.json +9 -0
- package/boilerplate-react-ts/tsconfig.json +22 -0
- package/boilerplate-react-ts/vite.config.ts +9 -0
- package/boilerplate-vue/.test-dev.test.ts +2 -0
- package/boilerplate-vue/.test-prod.test.ts +2 -0
- package/boilerplate-vue/.testCiJob.json +1 -0
- package/boilerplate-vue/_gitignore +2 -0
- package/boilerplate-vue/package.json +22 -0
- package/boilerplate-vue/pages/about/index.page.vue +13 -0
- package/boilerplate-vue/pages/index/Counter.vue +8 -0
- package/{files/js/vue → boilerplate-vue}/pages/index/index.page.vue +1 -1
- package/{files/js/vue → boilerplate-vue}/renderer/Link.vue +2 -2
- package/{files/js/vue/renderer/PageWrapper.vue → boilerplate-vue/renderer/PageShell.vue} +1 -1
- package/boilerplate-vue/renderer/_default.page.client.js +15 -0
- package/boilerplate-vue/renderer/_default.page.server.js +54 -0
- package/{files/js/vue → boilerplate-vue}/renderer/_error.page.vue +2 -2
- package/boilerplate-vue/renderer/app.js +28 -0
- package/boilerplate-vue/renderer/logo.svg +36 -0
- package/boilerplate-vue/renderer/usePageContext.js +18 -0
- package/boilerplate-vue/server/index.js +74 -0
- package/boilerplate-vue/server/root.js +8 -0
- package/boilerplate-vue/vite.config.js +6 -0
- package/boilerplate-vue-ts/.test-dev.test.ts +2 -0
- package/boilerplate-vue-ts/.test-prod.test.ts +2 -0
- package/boilerplate-vue-ts/.testCiJob.json +1 -0
- package/boilerplate-vue-ts/_gitignore +2 -0
- package/boilerplate-vue-ts/package.json +28 -0
- package/boilerplate-vue-ts/pages/about/index.page.vue +13 -0
- package/boilerplate-vue-ts/pages/index/Counter.vue +8 -0
- package/{files/ts/vue → boilerplate-vue-ts}/pages/index/index.page.vue +1 -1
- package/{files/ts/vue → boilerplate-vue-ts}/renderer/Link.vue +2 -2
- package/{files/ts/vue/renderer/PageWrapper.vue → boilerplate-vue-ts/renderer/PageShell.vue} +1 -1
- package/boilerplate-vue-ts/renderer/_default.page.client.ts +16 -0
- package/boilerplate-vue-ts/renderer/_default.page.server.ts +56 -0
- package/{files/ts/vue → boilerplate-vue-ts}/renderer/_error.page.vue +2 -2
- package/boilerplate-vue-ts/renderer/app.ts +29 -0
- package/boilerplate-vue-ts/renderer/logo.svg +36 -0
- package/boilerplate-vue-ts/renderer/types.ts +38 -0
- package/boilerplate-vue-ts/renderer/usePageContext.ts +21 -0
- package/boilerplate-vue-ts/server/index.ts +74 -0
- package/boilerplate-vue-ts/server/root.ts +8 -0
- package/boilerplate-vue-ts/server/tsconfig.json +9 -0
- package/boilerplate-vue-ts/tsconfig.json +21 -0
- package/boilerplate-vue-ts/vite.config.ts +9 -0
- package/boilerplate-vue-ts/vue.d.ts +4 -0
- package/index.js +222 -0
- package/package.json +13 -52
- package/README.md +0 -30
- package/create-vike.js +0 -2
- package/dist/index.js +0 -402
- package/files/js/react/pages/about/index.page.jsx +0 -13
- package/files/js/react/renderer/Link.jsx +0 -15
- package/files/js/react/renderer/_default.page.client.jsx +0 -19
- package/files/js/react/renderer/_default.page.server.jsx +0 -47
- package/files/js/react/renderer/usePageContext.jsx +0 -18
- package/files/js/react+client-router/renderer/_default.page.client.jsx +0 -43
- package/files/js/react+client-router/renderer/types.js +0 -1
- package/files/js/vike/server/index.js +0 -40
- package/files/js/vue/pages/about/index.page.vue +0 -11
- package/files/js/vue/pages/index/Counter.vue +0 -10
- package/files/js/vue/renderer/_default.page.client.js +0 -12
- package/files/js/vue/renderer/_default.page.server.js +0 -41
- package/files/js/vue/renderer/app.js +0 -29
- package/files/js/vue/renderer/usePageContext.js +0 -18
- package/files/js/vue+client-router/renderer/_default.page.client.js +0 -23
- package/files/js/vue+client-router/renderer/app.js +0 -36
- package/files/js/vue+client-router/renderer/types.js +0 -1
- package/files/shared/.prettierrc +0 -1
- package/files/shared/react/pages/about/index.css +0 -4
- package/files/shared/vike/_gitignore +0 -121
- package/files/ts/react/pages/about/index.page.tsx +0 -13
- package/files/ts/react/renderer/Link.tsx +0 -19
- package/files/ts/react/renderer/_default.page.client.tsx +0 -21
- package/files/ts/react/renderer/_default.page.server.tsx +0 -49
- package/files/ts/react/renderer/types.ts +0 -11
- package/files/ts/react/renderer/usePageContext.tsx +0 -25
- package/files/ts/react+client-router/renderer/_default.page.client.tsx +0 -44
- package/files/ts/react+client-router/renderer/types.ts +0 -12
- package/files/ts/vike/server/index.ts +0 -40
- package/files/ts/vue/pages/about/index.page.vue +0 -11
- package/files/ts/vue/pages/index/Counter.vue +0 -10
- package/files/ts/vue/renderer/_default.page.client.ts +0 -14
- package/files/ts/vue/renderer/_default.page.server.ts +0 -43
- package/files/ts/vue/renderer/app.ts +0 -30
- package/files/ts/vue/renderer/types.ts +0 -10
- package/files/ts/vue/renderer/usePageContext.ts +0 -20
- package/files/ts/vue/vue.d.ts +0 -4
- package/files/ts/vue+client-router/renderer/_default.page.client.ts +0 -24
- package/files/ts/vue+client-router/renderer/app.ts +0 -37
- package/files/ts/vue+client-router/renderer/types.ts +0 -11
- /package/{files/shared/react/renderer/PageWrapper.css → boilerplate-react-ts/renderer/PageShell.css} +0 -0
- /package/{files/shared/vike → boilerplate-react-ts}/renderer/logo.svg +0 -0
package/.testRun.ts
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
export { testRun }
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
page,
|
|
5
|
+
run,
|
|
6
|
+
partRegex,
|
|
7
|
+
autoRetry,
|
|
8
|
+
fetchHtml,
|
|
9
|
+
getServerUrl,
|
|
10
|
+
expectLog,
|
|
11
|
+
editFile,
|
|
12
|
+
editFileRevert,
|
|
13
|
+
sleep,
|
|
14
|
+
test,
|
|
15
|
+
expect
|
|
16
|
+
} from '@brillout/test-e2e'
|
|
17
|
+
import assert from 'assert'
|
|
18
|
+
|
|
19
|
+
function testRun(
|
|
20
|
+
cmd: 'npm run dev' | 'npm run prod' | 'npm run preview',
|
|
21
|
+
{
|
|
22
|
+
uiFramewok,
|
|
23
|
+
lang
|
|
24
|
+
}: {
|
|
25
|
+
uiFramewok: 'react' | 'vue' | 'preact' | 'solid'
|
|
26
|
+
lang?: 'ts'
|
|
27
|
+
isSPA?: true
|
|
28
|
+
}
|
|
29
|
+
) {
|
|
30
|
+
run(cmd)
|
|
31
|
+
|
|
32
|
+
const isProd = cmd === 'npm run prod' || cmd === 'npm run preview'
|
|
33
|
+
const isDev = !isProd
|
|
34
|
+
|
|
35
|
+
test('page content is rendered to HTML', async () => {
|
|
36
|
+
const html = await fetchHtml('/')
|
|
37
|
+
// Solid injects attribute: <h1 data-hk="0-0-2-1-0">Welcome</h1>
|
|
38
|
+
expect(html).toMatch(partRegex`<h1${/[^\>]*/}>Welcome</h1>`)
|
|
39
|
+
// Vue injects: `<!--[-->Home<!--]-->`
|
|
40
|
+
expect(html).toMatch(partRegex`<a ${/[^\>]+/}>${/.*/}Home${/.*/}</a>`)
|
|
41
|
+
expect(html).toMatch(partRegex`<a ${/[^\>]+/}>${/.*/}About${/.*/}</a>`)
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
test('page is rendered to the DOM and interactive', async () => {
|
|
45
|
+
await page.goto(getServerUrl() + '/')
|
|
46
|
+
expect(await page.textContent('h1')).toBe('Welcome')
|
|
47
|
+
expect(await page.textContent('button')).toBe('Counter 0')
|
|
48
|
+
// autoRetry() because browser-side code may not be loaded yet
|
|
49
|
+
await autoRetry(async () => {
|
|
50
|
+
await page.click('button')
|
|
51
|
+
if (uiFramewok === 'solid') {
|
|
52
|
+
expect(await page.textContent('button')).not.toBe('Counter 0')
|
|
53
|
+
} else {
|
|
54
|
+
expect(await page.textContent('button')).toBe('Counter 1')
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
if (isDev && (uiFramewok === 'react' || uiFramewok === 'vue')) {
|
|
60
|
+
test('HMR', async () => {
|
|
61
|
+
const file = (() => {
|
|
62
|
+
if (uiFramewok === 'vue') {
|
|
63
|
+
return './pages/index/index.page.vue'
|
|
64
|
+
}
|
|
65
|
+
if (uiFramewok === 'react') {
|
|
66
|
+
if (lang === 'ts') {
|
|
67
|
+
return './pages/index/index.page.tsx'
|
|
68
|
+
} else {
|
|
69
|
+
return './pages/index/index.page.jsx'
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
assert(false)
|
|
73
|
+
})()
|
|
74
|
+
expect(await page.textContent('button')).toBe('Counter 1')
|
|
75
|
+
expect(await page.textContent('h1')).toBe('Welcome')
|
|
76
|
+
await sleep(2 * 1000) // timeout can probably be decreased
|
|
77
|
+
editFile(file, (s) => s.replace('Welcome', 'Welcome !'))
|
|
78
|
+
await autoRetry(async () => {
|
|
79
|
+
expect(await page.textContent('h1')).toBe('Welcome !')
|
|
80
|
+
})
|
|
81
|
+
expect(await page.textContent('button')).toBe('Counter 1')
|
|
82
|
+
await sleep(300)
|
|
83
|
+
editFileRevert()
|
|
84
|
+
await autoRetry(async () => {
|
|
85
|
+
expect(await page.textContent('h1')).toBe('Welcome')
|
|
86
|
+
})
|
|
87
|
+
expect(await page.textContent('button')).toBe('Counter 1')
|
|
88
|
+
})
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
test('about page', async () => {
|
|
92
|
+
await page.click('a[href="/about"]')
|
|
93
|
+
await autoRetry(async () => {
|
|
94
|
+
const title = await page.textContent('h1')
|
|
95
|
+
expect(title).toBe('About')
|
|
96
|
+
})
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
test('active links', async () => {
|
|
100
|
+
// Not sure why `autoRetry()` is needed here; isn't the CSS loading already awaited for in the previous `test()` call?
|
|
101
|
+
await autoRetry(async () => {
|
|
102
|
+
expect(await page.$eval('a[href="/about"]', (e) => getComputedStyle(e).backgroundColor)).toBe(
|
|
103
|
+
'rgb(238, 238, 238)'
|
|
104
|
+
)
|
|
105
|
+
expect(await page.$eval('a[href="/"]', (e) => getComputedStyle(e).backgroundColor)).toBe('rgba(0, 0, 0, 0)')
|
|
106
|
+
})
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
test('error page', async () => {
|
|
110
|
+
await page.goto(getServerUrl() + '/does-not-exist')
|
|
111
|
+
expect(await page.textContent('h1')).toBe('404 Page Not Found')
|
|
112
|
+
expect(await page.textContent('p')).toBe('This page could not be found.')
|
|
113
|
+
expectLog(
|
|
114
|
+
'Failed to load resource: the server responded with a status of 404 (Not Found)',
|
|
115
|
+
(log) => log.logSource === 'Browser Error' && partRegex`http://${/[^\/]+/}:3000/does-not-exist`.test(log.logText)
|
|
116
|
+
)
|
|
117
|
+
})
|
|
118
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
rules: {
|
|
3
|
+
'react-refresh/only-export-components': 'warn'
|
|
4
|
+
},
|
|
5
|
+
reportUnusedDisableDirectives: true,
|
|
6
|
+
ignorePatterns: ['dist/*'],
|
|
7
|
+
env: { browser: true, es2020: true, node: true },
|
|
8
|
+
parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
|
|
9
|
+
settings: { react: { version: 'detect' } },
|
|
10
|
+
plugins: ['react-refresh'],
|
|
11
|
+
extends: [
|
|
12
|
+
'eslint:recommended',
|
|
13
|
+
'plugin:react/recommended',
|
|
14
|
+
'plugin:react/jsx-runtime',
|
|
15
|
+
'plugin:react-hooks/recommended'
|
|
16
|
+
]
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "name": "Boilerplates" }
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"scripts": {
|
|
3
|
+
"dev": "npm run server:dev",
|
|
4
|
+
"prod": "npm run lint && npm run build && npm run server:prod",
|
|
5
|
+
"build": "vite build",
|
|
6
|
+
"server:dev": "node ./server",
|
|
7
|
+
"server:prod": "cross-env NODE_ENV=production node ./server",
|
|
8
|
+
"lint": "eslint . --max-warnings 0"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@vitejs/plugin-react": "^4.0.4",
|
|
12
|
+
"compression": "^1.7.4",
|
|
13
|
+
"cross-env": "^7.0.3",
|
|
14
|
+
"eslint": "^8.47.0",
|
|
15
|
+
"eslint-plugin-react": "^7.33.1",
|
|
16
|
+
"eslint-plugin-react-hooks": "^4.6.0",
|
|
17
|
+
"eslint-plugin-react-refresh": "^0.4.3",
|
|
18
|
+
"express": "^4.18.2",
|
|
19
|
+
"prop-types": "15.8.1",
|
|
20
|
+
"react": "^18.2.0",
|
|
21
|
+
"react-dom": "^18.2.0",
|
|
22
|
+
"sirv": "^2.0.3",
|
|
23
|
+
"vite": "^4.4.9",
|
|
24
|
+
"vike": "^0.4.142"
|
|
25
|
+
},
|
|
26
|
+
"type": "module"
|
|
27
|
+
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useState } from 'react'
|
|
2
2
|
|
|
3
|
-
export { Counter }
|
|
3
|
+
export { Counter }
|
|
4
4
|
|
|
5
5
|
function Counter() {
|
|
6
|
-
const [count, setCount] = useState(0)
|
|
6
|
+
const [count, setCount] = useState(0)
|
|
7
7
|
return (
|
|
8
8
|
<button type="button" onClick={() => setCount((count) => count + 1)}>
|
|
9
9
|
Counter {count}
|
|
10
10
|
</button>
|
|
11
|
-
)
|
|
11
|
+
)
|
|
12
12
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { Counter } from "./Counter";
|
|
1
|
+
import { Counter } from './Counter'
|
|
3
2
|
|
|
4
|
-
export { Page }
|
|
3
|
+
export { Page }
|
|
5
4
|
|
|
6
5
|
function Page() {
|
|
7
6
|
return (
|
|
@@ -15,5 +14,5 @@ function Page() {
|
|
|
15
14
|
</li>
|
|
16
15
|
</ul>
|
|
17
16
|
</>
|
|
18
|
-
)
|
|
17
|
+
)
|
|
19
18
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import PropTypes from 'prop-types'
|
|
2
|
+
import { usePageContext } from './usePageContext'
|
|
3
|
+
|
|
4
|
+
export { Link }
|
|
5
|
+
|
|
6
|
+
Link.propTypes = {
|
|
7
|
+
className: PropTypes.string,
|
|
8
|
+
href: PropTypes.string.isRequired
|
|
9
|
+
}
|
|
10
|
+
function Link(props) {
|
|
11
|
+
const pageContext = usePageContext()
|
|
12
|
+
const className = [props.className, pageContext.urlPathname === props.href && 'is-active'].filter(Boolean).join(' ')
|
|
13
|
+
return <a {...props} className={className} />
|
|
14
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/* This CSS is common to all pages */
|
|
2
|
+
|
|
3
|
+
body {
|
|
4
|
+
margin: 0;
|
|
5
|
+
font-family: sans-serif;
|
|
6
|
+
}
|
|
7
|
+
* {
|
|
8
|
+
box-sizing: border-box;
|
|
9
|
+
}
|
|
10
|
+
a {
|
|
11
|
+
text-decoration: none;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.navitem {
|
|
15
|
+
padding: 3px 10px;
|
|
16
|
+
}
|
|
17
|
+
.navitem.is-active {
|
|
18
|
+
background-color: #eee;
|
|
19
|
+
}
|
package/{files/js/react/renderer/PageWrapper.jsx → boilerplate-react/renderer/PageShell.jsx}
RENAMED
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import PropTypes from 'prop-types'
|
|
3
|
+
import logo from './logo.svg'
|
|
4
|
+
import './PageShell.css'
|
|
5
|
+
import { PageContextProvider } from './usePageContext'
|
|
6
|
+
import { Link } from './Link'
|
|
7
|
+
import { childrenPropType } from './PropTypeValues'
|
|
6
8
|
|
|
7
|
-
export {
|
|
9
|
+
export { PageShell }
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
PageShell.propTypes = {
|
|
12
|
+
pageContext: PropTypes.any,
|
|
13
|
+
children: childrenPropType
|
|
14
|
+
}
|
|
15
|
+
function PageShell({ pageContext, children }) {
|
|
10
16
|
return (
|
|
11
17
|
<React.StrictMode>
|
|
12
18
|
<PageContextProvider pageContext={pageContext}>
|
|
@@ -24,53 +30,62 @@ function PageWrapper({ children, pageContext }) {
|
|
|
24
30
|
</Layout>
|
|
25
31
|
</PageContextProvider>
|
|
26
32
|
</React.StrictMode>
|
|
27
|
-
)
|
|
33
|
+
)
|
|
28
34
|
}
|
|
29
35
|
|
|
36
|
+
Layout.propTypes = {
|
|
37
|
+
children: childrenPropType
|
|
38
|
+
}
|
|
30
39
|
function Layout({ children }) {
|
|
31
40
|
return (
|
|
32
41
|
<div
|
|
33
42
|
style={{
|
|
34
|
-
display:
|
|
43
|
+
display: 'flex',
|
|
35
44
|
maxWidth: 900,
|
|
36
|
-
margin:
|
|
45
|
+
margin: 'auto'
|
|
37
46
|
}}
|
|
38
47
|
>
|
|
39
48
|
{children}
|
|
40
49
|
</div>
|
|
41
|
-
)
|
|
50
|
+
)
|
|
42
51
|
}
|
|
43
52
|
|
|
53
|
+
Sidebar.propTypes = {
|
|
54
|
+
children: childrenPropType
|
|
55
|
+
}
|
|
44
56
|
function Sidebar({ children }) {
|
|
45
57
|
return (
|
|
46
58
|
<div
|
|
47
59
|
style={{
|
|
48
60
|
padding: 20,
|
|
49
61
|
flexShrink: 0,
|
|
50
|
-
display:
|
|
51
|
-
flexDirection:
|
|
52
|
-
alignItems:
|
|
53
|
-
lineHeight:
|
|
62
|
+
display: 'flex',
|
|
63
|
+
flexDirection: 'column',
|
|
64
|
+
alignItems: 'center',
|
|
65
|
+
lineHeight: '1.8em'
|
|
54
66
|
}}
|
|
55
67
|
>
|
|
56
68
|
{children}
|
|
57
69
|
</div>
|
|
58
|
-
)
|
|
70
|
+
)
|
|
59
71
|
}
|
|
60
72
|
|
|
73
|
+
Content.propTypes = {
|
|
74
|
+
children: childrenPropType
|
|
75
|
+
}
|
|
61
76
|
function Content({ children }) {
|
|
62
77
|
return (
|
|
63
78
|
<div
|
|
64
79
|
style={{
|
|
65
80
|
padding: 20,
|
|
66
81
|
paddingBottom: 50,
|
|
67
|
-
borderLeft:
|
|
68
|
-
minHeight:
|
|
82
|
+
borderLeft: '2px solid #eee',
|
|
83
|
+
minHeight: '100vh'
|
|
69
84
|
}}
|
|
70
85
|
>
|
|
71
86
|
{children}
|
|
72
87
|
</div>
|
|
73
|
-
)
|
|
88
|
+
)
|
|
74
89
|
}
|
|
75
90
|
|
|
76
91
|
function Logo() {
|
|
@@ -78,12 +93,12 @@ function Logo() {
|
|
|
78
93
|
<div
|
|
79
94
|
style={{
|
|
80
95
|
marginTop: 20,
|
|
81
|
-
marginBottom: 10
|
|
96
|
+
marginBottom: 10
|
|
82
97
|
}}
|
|
83
98
|
>
|
|
84
99
|
<a href="/">
|
|
85
100
|
<img src={logo} height={64} width={64} alt="logo" />
|
|
86
101
|
</a>
|
|
87
102
|
</div>
|
|
88
|
-
)
|
|
103
|
+
)
|
|
89
104
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export { render }
|
|
2
|
+
|
|
3
|
+
import { hydrateRoot } from 'react-dom/client'
|
|
4
|
+
import { PageShell } from './PageShell'
|
|
5
|
+
|
|
6
|
+
// This render() hook only supports SSR, see https://vike.dev/render-modes for how to modify render() to support SPA
|
|
7
|
+
async function render(pageContext) {
|
|
8
|
+
const { Page, pageProps } = pageContext
|
|
9
|
+
if (!Page) throw new Error('Client-side render() hook expects pageContext.Page to be defined')
|
|
10
|
+
const root = document.getElementById('react-root')
|
|
11
|
+
if (!root) throw new Error('DOM element #react-root not found')
|
|
12
|
+
hydrateRoot(
|
|
13
|
+
root,
|
|
14
|
+
<PageShell pageContext={pageContext}>
|
|
15
|
+
<Page {...pageProps} />
|
|
16
|
+
</PageShell>
|
|
17
|
+
)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/* To enable Client-side Routing:
|
|
21
|
+
export const clientRouting = true
|
|
22
|
+
// !! WARNING !! Before doing so, read https://vike.dev/clientRouting */
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export { render }
|
|
2
|
+
// See https://vike.dev/data-fetching
|
|
3
|
+
export const passToClient = ['pageProps', 'urlPathname']
|
|
4
|
+
|
|
5
|
+
import ReactDOMServer from 'react-dom/server'
|
|
6
|
+
import { PageShell } from './PageShell'
|
|
7
|
+
import { escapeInject, dangerouslySkipEscape } from 'vike/server'
|
|
8
|
+
import logoUrl from './logo.svg'
|
|
9
|
+
|
|
10
|
+
async function render(pageContext) {
|
|
11
|
+
const { Page, pageProps } = pageContext
|
|
12
|
+
// This render() hook only supports SSR, see https://vike.dev/render-modes for how to modify render() to support SPA
|
|
13
|
+
if (!Page) throw new Error('My render() hook expects pageContext.Page to be defined')
|
|
14
|
+
const pageHtml = ReactDOMServer.renderToString(
|
|
15
|
+
<PageShell pageContext={pageContext}>
|
|
16
|
+
<Page {...pageProps} />
|
|
17
|
+
</PageShell>
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
// See https://vike.dev/head
|
|
21
|
+
const { documentProps } = pageContext.exports
|
|
22
|
+
const title = (documentProps && documentProps.title) || 'Vite SSR app'
|
|
23
|
+
const desc = (documentProps && documentProps.description) || 'App using Vite + Vike'
|
|
24
|
+
|
|
25
|
+
const documentHtml = escapeInject`<!DOCTYPE html>
|
|
26
|
+
<html lang="en">
|
|
27
|
+
<head>
|
|
28
|
+
<meta charset="UTF-8" />
|
|
29
|
+
<link rel="icon" href="${logoUrl}" />
|
|
30
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
31
|
+
<meta name="description" content="${desc}" />
|
|
32
|
+
<title>${title}</title>
|
|
33
|
+
</head>
|
|
34
|
+
<body>
|
|
35
|
+
<div id="react-root">${dangerouslySkipEscape(pageHtml)}</div>
|
|
36
|
+
</body>
|
|
37
|
+
</html>`
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
documentHtml,
|
|
41
|
+
pageContext: {
|
|
42
|
+
// We can add some `pageContext` here, which is useful if we want to do page redirection https://vike.dev/page-redirection
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import PropTypes from 'prop-types'
|
|
2
2
|
|
|
3
|
-
export { Page }
|
|
3
|
+
export { Page }
|
|
4
4
|
|
|
5
|
+
Page.propTypes = {
|
|
6
|
+
is404: PropTypes.bool
|
|
7
|
+
}
|
|
5
8
|
function Page({ is404 }) {
|
|
6
9
|
if (is404) {
|
|
7
10
|
return (
|
|
@@ -9,13 +12,13 @@ function Page({ is404 }) {
|
|
|
9
12
|
<h1>404 Page Not Found</h1>
|
|
10
13
|
<p>This page could not be found.</p>
|
|
11
14
|
</>
|
|
12
|
-
)
|
|
15
|
+
)
|
|
13
16
|
} else {
|
|
14
17
|
return (
|
|
15
18
|
<>
|
|
16
|
-
<h1>500 Internal
|
|
19
|
+
<h1>500 Internal Error</h1>
|
|
17
20
|
<p>Something went wrong.</p>
|
|
18
21
|
</>
|
|
19
|
-
)
|
|
22
|
+
)
|
|
20
23
|
}
|
|
21
24
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<svg width="175" height="175" fill="none" version="1.1" viewBox="0 0 175 175" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
|
3
|
+
<metadata>
|
|
4
|
+
<rdf:RDF>
|
|
5
|
+
<cc:Work rdf:about="">
|
|
6
|
+
<dc:format>image/svg+xml</dc:format>
|
|
7
|
+
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
|
8
|
+
<dc:title/>
|
|
9
|
+
</cc:Work>
|
|
10
|
+
</rdf:RDF>
|
|
11
|
+
</metadata>
|
|
12
|
+
<defs>
|
|
13
|
+
<linearGradient id="linearGradient880" x1="108.64" x2="115.51" y1="88.726" y2="136.2" gradientTransform="matrix(1.0498 0 0 1.0498 -2.9171 -2.9658)" gradientUnits="userSpaceOnUse">
|
|
14
|
+
<stop stop-color="#ffea83" offset="0"/>
|
|
15
|
+
<stop stop-color="#FFDD35" offset=".083333"/>
|
|
16
|
+
<stop stop-color="#FFA800" offset="1"/>
|
|
17
|
+
</linearGradient>
|
|
18
|
+
<linearGradient id="paint2_linear" x1="48.975" x2="61.299" y1="3.9232" y2="158.04" gradientTransform="translate(-2.832e-5)" gradientUnits="userSpaceOnUse">
|
|
19
|
+
<stop stop-color="#FFEA83" offset="0"/>
|
|
20
|
+
<stop stop-color="#FFDD35" offset=".083333"/>
|
|
21
|
+
<stop stop-color="#FFA800" offset="1"/>
|
|
22
|
+
</linearGradient>
|
|
23
|
+
<linearGradient id="paint0_linear-6" x1="-1.4492" x2="116.62" y1="-5.8123" y2="137.08" gradientTransform="translate(-2.832e-5)" gradientUnits="userSpaceOnUse">
|
|
24
|
+
<stop stop-color="#41D1FF" offset="0"/>
|
|
25
|
+
<stop stop-color="#BD34FE" offset="1"/>
|
|
26
|
+
</linearGradient>
|
|
27
|
+
</defs>
|
|
28
|
+
<circle cx="87.5" cy="87.5" r="87.5" fill="#c4c4c4"/>
|
|
29
|
+
<circle cx="87.5" cy="87.5" r="87.5" fill="url(#paint0_linear-6)"/>
|
|
30
|
+
<g transform="translate(632.92 54.355)" fill="#d38787" stroke-width="1.0614">
|
|
31
|
+
<path d="m-549.75 68.457c-5.7533-3.1217-6.1166-5.2295-6.1166-35.489 0-30.458 0.35464-32.448 6.3339-35.54 3.9943-2.0655 24.279-2.2805 26.735-0.28333 0.89718 0.72974 6.7203 6.6637 12.94 13.187l11.309 11.86v19.575c0 18.473-0.12956 19.74-2.3011 22.5-4.0223 5.1136-7.558 5.8565-27.65 5.8099-14.15-0.03287-19.008-0.40294-21.25-1.6191zm42.473-6.3594c2.27-1.59 2.359-2.2909 2.359-18.575v-16.923h-6.9521c-12.443 0-16.4-4.0845-16.4-16.93v-7.4828h-8.9464c-6.7178 0-9.3619 0.41549-10.614 1.668-2.5031 2.5031-2.5031 55.724 0 58.228 2.4502 2.4502 37.058 2.4636 40.553 0.01609zm-1.8867-42.165c0-0.16422-2.8659-3.1346-6.3686-6.6008l-6.3686-6.3022v4.9328c0 6.3185 1.8955 8.2687 8.0366 8.2687 2.5854 0 4.7007-0.13434 4.7007-0.29859zm-57.57 44.279c-5.6185-3.0486-6.1166-5.593-6.1166-31.243 0-18.891 0.31331-24.063 1.6101-26.571 1.809-3.4981 6.5048-6.3339 10.489-6.3339 2.4847 0 2.5814 0.19984 1.541 3.1843-0.61054 1.7514-1.7457 3.1843-2.5226 3.1843-0.77686 0-2.1631 0.75059-3.0805 1.668-2.4923 2.4923-2.4923 47.244 0 49.736 0.91739 0.9174 2.3036 1.668 3.0805 1.668 0.77688 0 1.912 1.4329 2.5226 3.1843 1.0562 3.0298 0.97108 3.1822-1.7537 3.1418-1.575-0.02331-4.1713-0.75194-5.7694-1.6191zm-16.983-4.2458c-5.4392-2.9512-6.1166-5.9415-6.1166-26.997 0-15.096 0.345-19.878 1.6101-22.325 1.7476-3.3796 6.4758-6.3339 10.137-6.3339 1.8666 0 2.1789 0.44955 1.6594 2.3882-0.35184 1.3135-0.64655 2.7465-0.65453 3.1843-8e-3 0.43784-0.69682 0.79608-1.5308 0.79608-0.83399 0-2.2669 0.75059-3.1843 1.668-2.4767 2.4767-2.4767 38.768 0 41.244 0.91741 0.91739 2.2946 1.668 3.0605 1.668 1.196 0 2.6402 2.995 2.6871 5.5726 0.0241 1.3294-4.5804 0.80962-7.6676-0.8655z" style="mix-blend-mode:lighten"/>
|
|
32
|
+
<path d="m-552.2 68.911c-5.7533-3.1217-6.1166-5.2295-6.1166-35.489 0-30.458 0.35463-32.448 6.3339-35.54 3.9943-2.0655 24.279-2.2805 26.735-0.28333 0.89718 0.72974 6.7203 6.6637 12.94 13.187l11.309 11.86v19.575c0 18.473-0.12957 19.74-2.3011 22.5-4.0223 5.1136-7.558 5.8565-27.65 5.8099-14.15-0.03287-19.008-0.40294-21.25-1.6191zm42.473-6.3594c2.27-1.59 2.359-2.2909 2.359-18.575v-16.923h-6.952c-12.443 0-16.4-4.0845-16.4-16.93v-7.4828h-8.9464c-6.7179 0-9.3619 0.41549-10.614 1.668-2.5031 2.5031-2.5031 55.724 0 58.228 2.4502 2.4502 37.058 2.4636 40.553 0.01609zm-1.8867-42.165c0-0.16422-2.8659-3.1346-6.3686-6.6008l-6.3686-6.3022v4.9328c0 6.3185 1.8955 8.2688 8.0366 8.2688 2.5854 0 4.7007-0.13434 4.7007-0.29859zm-57.57 44.279c-5.6185-3.0486-6.1166-5.593-6.1166-31.243 0-18.891 0.31331-24.063 1.6101-26.571 1.809-3.4981 6.5048-6.3339 10.489-6.3339 2.4847 0 2.5814 0.19984 1.541 3.1843-0.61054 1.7514-1.7457 3.1843-2.5226 3.1843-0.77687 0-2.1631 0.75059-3.0805 1.668-2.4923 2.4923-2.4923 47.244 0 49.736 0.91741 0.91739 2.3036 1.668 3.0805 1.668 0.77686 0 1.912 1.4329 2.5226 3.1843 1.0562 3.0298 0.97107 3.1822-1.7537 3.1418-1.575-0.02331-4.1713-0.75194-5.7694-1.6191zm-16.983-4.2458c-5.4392-2.9512-6.1166-5.9415-6.1166-26.997 0-15.096 0.34502-19.878 1.6101-22.325 1.7476-3.3796 6.4758-6.3339 10.137-6.3339 1.8666 0 2.1789 0.44955 1.6594 2.3882-0.35182 1.3135-0.64653 2.7465-0.65452 3.1843-8e-3 0.43784-0.69683 0.79608-1.5308 0.79608-0.83397 0-2.2669 0.75059-3.1843 1.668-2.4767 2.4767-2.4767 38.768 0 41.245 0.9174 0.91739 2.2946 1.668 3.0605 1.668 1.196 0 2.6402 2.995 2.6871 5.5726 0.0241 1.3294-4.5804 0.80962-7.6676-0.8655z" fill-opacity=".47466" style="mix-blend-mode:lighten"/>
|
|
33
|
+
</g>
|
|
34
|
+
<path d="m128.48 88.913-24.027 4.6784c-0.39475 0.07685-0.68766 0.40944-0.71076 0.80849l-1.4782 24.805c-0.0347 0.58371 0.50497 1.0372 1.0792 0.90602l6.6886-1.5338c0.62676-0.14383 1.1916 0.40419 1.0635 1.0299l-1.9874 9.6702c-0.13438 0.65091 0.48084 1.2073 1.1202 1.0142l4.1322-1.2472c0.64041-0.19317 1.2556 0.36535 1.1202 1.0162l-3.158 15.191c-0.19842 0.95011 1.074 1.4677 1.6042 0.653l0.35485-0.54382 19.578-38.827c0.32755-0.64985-0.23727-1.391-0.95641-1.2535l-6.8849 1.3207c-0.6467 0.12389-1.1979-0.47453-1.0152-1.1034l4.4944-15.482c0.18266-0.63012-0.36955-1.2295-1.0173-1.1034z" fill="url(#linearGradient880)" stroke-width="1.0498"/>
|
|
35
|
+
<rect x="3" y="3" width="169" height="169" rx="84.5" stroke="url(#paint2_linear)" stroke-width="6" style="mix-blend-mode:soft-light"/>
|
|
36
|
+
</svg>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// `usePageContext` allows us to access `pageContext` in any React component.
|
|
2
|
+
// See https://vike.dev/pageContext-anywhere
|
|
3
|
+
|
|
4
|
+
import React, { useContext } from 'react'
|
|
5
|
+
import PropTypes from 'prop-types'
|
|
6
|
+
import { childrenPropType } from './PropTypeValues'
|
|
7
|
+
|
|
8
|
+
export { PageContextProvider }
|
|
9
|
+
// eslint-disable-next-line react-refresh/only-export-components
|
|
10
|
+
export { usePageContext }
|
|
11
|
+
|
|
12
|
+
const Context = React.createContext(undefined)
|
|
13
|
+
|
|
14
|
+
PageContextProvider.propTypes = {
|
|
15
|
+
pageContext: PropTypes.any,
|
|
16
|
+
children: childrenPropType
|
|
17
|
+
}
|
|
18
|
+
function PageContextProvider({ pageContext, children }) {
|
|
19
|
+
return <Context.Provider value={pageContext}>{children}</Context.Provider>
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function usePageContext() {
|
|
23
|
+
const pageContext = useContext(Context)
|
|
24
|
+
return pageContext
|
|
25
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// This file isn't processed by Vite, see https://github.com/vikejs/vike/issues/562
|
|
2
|
+
// Consequently:
|
|
3
|
+
// - When changing this file, you needed to manually restart your server for your changes to take effect.
|
|
4
|
+
// - To use your environment variables defined in your .env files, you need to install dotenv, see https://vike.dev/env
|
|
5
|
+
// - To use your path aliases defined in your vite.config.js, you need to tell Node.js about them, see https://vike.dev/path-aliases
|
|
6
|
+
|
|
7
|
+
// If you want Vite to process your server code then use one of these:
|
|
8
|
+
// - vavite (https://github.com/cyco130/vavite)
|
|
9
|
+
// - See vavite + Vike examples at https://github.com/cyco130/vavite/tree/main/examples
|
|
10
|
+
// - vite-node (https://github.com/antfu/vite-node)
|
|
11
|
+
// - HatTip (https://github.com/hattipjs/hattip)
|
|
12
|
+
// - You can use Bati (https://batijs.github.io/) to scaffold a vike + HatTip app. Note that Bati generates apps that use the V1 design (https://vike.dev/migration/v1-design) and Vike packages (https://vike.dev/vike-packages)
|
|
13
|
+
|
|
14
|
+
import express from 'express'
|
|
15
|
+
import compression from 'compression'
|
|
16
|
+
import { renderPage } from 'vike/server'
|
|
17
|
+
import { root } from './root.js'
|
|
18
|
+
const isProduction = process.env.NODE_ENV === 'production'
|
|
19
|
+
|
|
20
|
+
startServer()
|
|
21
|
+
|
|
22
|
+
async function startServer() {
|
|
23
|
+
const app = express()
|
|
24
|
+
|
|
25
|
+
app.use(compression())
|
|
26
|
+
|
|
27
|
+
// Vite integration
|
|
28
|
+
if (isProduction) {
|
|
29
|
+
// In production, we need to serve our static assets ourselves.
|
|
30
|
+
// (In dev, Vite's middleware serves our static assets.)
|
|
31
|
+
const sirv = (await import('sirv')).default
|
|
32
|
+
app.use(sirv(`${root}/dist/client`))
|
|
33
|
+
} else {
|
|
34
|
+
// We instantiate Vite's development server and integrate its middleware to our server.
|
|
35
|
+
// ⚠️ We instantiate it only in development. (It isn't needed in production and it
|
|
36
|
+
// would unnecessarily bloat our production server.)
|
|
37
|
+
const vite = await import('vite')
|
|
38
|
+
const viteDevMiddleware = (
|
|
39
|
+
await vite.createServer({
|
|
40
|
+
root,
|
|
41
|
+
server: { middlewareMode: true }
|
|
42
|
+
})
|
|
43
|
+
).middlewares
|
|
44
|
+
app.use(viteDevMiddleware)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// ...
|
|
48
|
+
// Other middlewares (e.g. some RPC middleware such as Telefunc)
|
|
49
|
+
// ...
|
|
50
|
+
|
|
51
|
+
// Vike middleware. It should always be our last middleware (because it's a
|
|
52
|
+
// catch-all middleware superseding any middleware placed after it).
|
|
53
|
+
app.get('*', async (req, res, next) => {
|
|
54
|
+
const pageContextInit = {
|
|
55
|
+
urlOriginal: req.originalUrl
|
|
56
|
+
}
|
|
57
|
+
const pageContext = await renderPage(pageContextInit)
|
|
58
|
+
const { httpResponse } = pageContext
|
|
59
|
+
if (!httpResponse) {
|
|
60
|
+
return next()
|
|
61
|
+
} else {
|
|
62
|
+
const { body, statusCode, headers, earlyHints } = httpResponse
|
|
63
|
+
if (res.writeEarlyHints) res.writeEarlyHints({ link: earlyHints.map((e) => e.earlyHintLink) })
|
|
64
|
+
headers.forEach(([name, value]) => res.setHeader(name, value))
|
|
65
|
+
res.status(statusCode)
|
|
66
|
+
// For HTTP streams use httpResponse.pipe() instead, see https://vike.dev/stream
|
|
67
|
+
res.send(body)
|
|
68
|
+
}
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
const port = process.env.PORT || 3000
|
|
72
|
+
app.listen(port)
|
|
73
|
+
console.log(`Server running at http://localhost:${port}`)
|
|
74
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { root }
|
|
2
|
+
|
|
3
|
+
// https://stackoverflow.com/questions/46745014/alternative-for-dirname-in-node-when-using-the-experimental-modules-flag/50052194#50052194
|
|
4
|
+
|
|
5
|
+
import { dirname } from 'path'
|
|
6
|
+
import { fileURLToPath } from 'url'
|
|
7
|
+
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
8
|
+
const root = `${__dirname}/..`
|