From 066f94188afdd41c4d19a655109f340b84d49e67 Mon Sep 17 00:00:00 2001 From: Pacharapol Withayasakpunt Date: Sat, 7 May 2022 19:28:04 +0700 Subject: [PATCH] test vite ssr --- __packages__/www/.gitignore | 2 + __packages__/www/package.json | 32 +++++++++++ __packages__/www/pages/about/index.page.vue | 11 ++++ __packages__/www/pages/index/Counter.vue | 8 +++ __packages__/www/pages/index/index.page.vue | 12 ++++ __packages__/www/renderer/Link.vue | 17 ++++++ __packages__/www/renderer/PageShell.vue | 55 +++++++++++++++++++ .../www/renderer/_default.page.client.ts | 14 +++++ .../www/renderer/_default.page.server.ts | 41 ++++++++++++++ __packages__/www/renderer/_error.page.vue | 14 +++++ __packages__/www/renderer/app.ts | 30 ++++++++++ __packages__/www/renderer/logo.svg | 36 ++++++++++++ __packages__/www/renderer/types.ts | 11 ++++ __packages__/www/renderer/usePageContext.ts | 21 +++++++ __packages__/www/server/index.ts | 43 +++++++++++++++ __packages__/www/tsconfig.json | 19 +++++++ __packages__/www/vite.config.ts | 9 +++ __packages__/www/vue.d.ts | 4 ++ __packages__/www/yarn.lock | 4 ++ wk-extra.code-workspace | 23 ++++++++ 20 files changed, 406 insertions(+) create mode 100644 __packages__/www/.gitignore create mode 100644 __packages__/www/package.json create mode 100644 __packages__/www/pages/about/index.page.vue create mode 100644 __packages__/www/pages/index/Counter.vue create mode 100644 __packages__/www/pages/index/index.page.vue create mode 100644 __packages__/www/renderer/Link.vue create mode 100644 __packages__/www/renderer/PageShell.vue create mode 100644 __packages__/www/renderer/_default.page.client.ts create mode 100644 __packages__/www/renderer/_default.page.server.ts create mode 100644 __packages__/www/renderer/_error.page.vue create mode 100644 __packages__/www/renderer/app.ts create mode 100644 __packages__/www/renderer/logo.svg create mode 100644 __packages__/www/renderer/types.ts create mode 100644 __packages__/www/renderer/usePageContext.ts create mode 100644 __packages__/www/server/index.ts create mode 100644 __packages__/www/tsconfig.json create mode 100644 __packages__/www/vite.config.ts create mode 100644 __packages__/www/vue.d.ts create mode 100644 __packages__/www/yarn.lock create mode 100644 wk-extra.code-workspace diff --git a/__packages__/www/.gitignore b/__packages__/www/.gitignore new file mode 100644 index 0000000..b947077 --- /dev/null +++ b/__packages__/www/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +dist/ diff --git a/__packages__/www/package.json b/__packages__/www/package.json new file mode 100644 index 0000000..95fce80 --- /dev/null +++ b/__packages__/www/package.json @@ -0,0 +1,32 @@ +{ + "name": "@wk-extra/www", + "private": true, + "version": "1.0.0", + "license": "MIT", + "scripts": { + "dev": "yarn server", + "prod": "yarn build && yarn server:prod", + "build": "vite build && vite build --ssr", + "render": "yarn build && vite-plugin-ssr prerender", + "server": "ts-node ./server", + "server:prod": "cross-env NODE_ENV=production ts-node ./server" + }, + "dependencies": { + "@vitejs/plugin-vue": "^2.2.2", + "@vue/compiler-sfc": "^3.2.31", + "@vue/server-renderer": "^3.2.31", + "compression": "^1.7.4", + "cross-env": "^7.0.3", + "express": "^4.17.3", + "vite": "^2.8.4", + "vite-plugin-ssr": "^0.3.64", + "vue": "^3.2.31" + }, + "devDependencies": { + "@types/compression": "^1.7.2", + "@types/express": "^4.17.13", + "@types/node": "^17.0.19", + "ts-node": "^10.5.0", + "typescript": "^4.5.5" + } +} diff --git a/__packages__/www/pages/about/index.page.vue b/__packages__/www/pages/about/index.page.vue new file mode 100644 index 0000000..a2c9306 --- /dev/null +++ b/__packages__/www/pages/about/index.page.vue @@ -0,0 +1,11 @@ + + + diff --git a/__packages__/www/pages/index/Counter.vue b/__packages__/www/pages/index/Counter.vue new file mode 100644 index 0000000..e4e5119 --- /dev/null +++ b/__packages__/www/pages/index/Counter.vue @@ -0,0 +1,8 @@ + + + diff --git a/__packages__/www/pages/index/index.page.vue b/__packages__/www/pages/index/index.page.vue new file mode 100644 index 0000000..9c3fb53 --- /dev/null +++ b/__packages__/www/pages/index/index.page.vue @@ -0,0 +1,12 @@ + + + diff --git a/__packages__/www/renderer/Link.vue b/__packages__/www/renderer/Link.vue new file mode 100644 index 0000000..fdca43e --- /dev/null +++ b/__packages__/www/renderer/Link.vue @@ -0,0 +1,17 @@ + + + diff --git a/__packages__/www/renderer/PageShell.vue b/__packages__/www/renderer/PageShell.vue new file mode 100644 index 0000000..2b5f439 --- /dev/null +++ b/__packages__/www/renderer/PageShell.vue @@ -0,0 +1,55 @@ + + + + + + + diff --git a/__packages__/www/renderer/_default.page.client.ts b/__packages__/www/renderer/_default.page.client.ts new file mode 100644 index 0000000..d9f5841 --- /dev/null +++ b/__packages__/www/renderer/_default.page.client.ts @@ -0,0 +1,14 @@ +import { getPage } from 'vite-plugin-ssr/client' +import { createApp } from './app' +import type { PageContext } from './types' +import type { PageContextBuiltInClient } from 'vite-plugin-ssr/client' + +hydrate() + +async function hydrate() { + // We do Server Routing, but we can also do Client Routing by using `useClientRouter()` + // instead of `getPage()`, see https://vite-plugin-ssr.com/useClientRouter + const pageContext = await getPage() + const app = createApp(pageContext) + app.mount('#app') +} diff --git a/__packages__/www/renderer/_default.page.server.ts b/__packages__/www/renderer/_default.page.server.ts new file mode 100644 index 0000000..c4e0581 --- /dev/null +++ b/__packages__/www/renderer/_default.page.server.ts @@ -0,0 +1,41 @@ +import { renderToString } from '@vue/server-renderer' +import { escapeInject, dangerouslySkipEscape } from 'vite-plugin-ssr' +import { createApp } from './app' +import logoUrl from './logo.svg' +import type { PageContext } from './types' +import type { PageContextBuiltIn } from 'vite-plugin-ssr' + +export { render } +// See https://vite-plugin-ssr.com/data-fetching +export const passToClient = ['pageProps', 'urlPathname'] + +async function render(pageContext: PageContextBuiltIn & PageContext) { + const app = createApp(pageContext) + const appHtml = await renderToString(app) + + // See https://vite-plugin-ssr.com/head + const { documentProps } = pageContext + const title = (documentProps && documentProps.title) || 'Vite SSR app' + const desc = (documentProps && documentProps.description) || 'App using Vite + vite-plugin-ssr' + + const documentHtml = escapeInject` + + + + + + + ${title} + + +
${dangerouslySkipEscape(appHtml)}
+ + ` + + return { + documentHtml, + pageContext: { + // We can add some `pageContext` here, which is useful if we want to do page redirection https://vite-plugin-ssr.com/page-redirection + }, + } +} diff --git a/__packages__/www/renderer/_error.page.vue b/__packages__/www/renderer/_error.page.vue new file mode 100644 index 0000000..4b587f1 --- /dev/null +++ b/__packages__/www/renderer/_error.page.vue @@ -0,0 +1,14 @@ + + + diff --git a/__packages__/www/renderer/app.ts b/__packages__/www/renderer/app.ts new file mode 100644 index 0000000..1d261ba --- /dev/null +++ b/__packages__/www/renderer/app.ts @@ -0,0 +1,30 @@ +import { createSSRApp, defineComponent, h } from 'vue' +import PageShell from './PageShell.vue' +import { setPageContext } from './usePageContext' +import type { PageContext } from './types' + +export { createApp } + +function createApp(pageContext: PageContext) { + const { Page, pageProps } = pageContext + const PageWithLayout = defineComponent({ + render() { + return h( + PageShell, + {}, + { + default() { + return h(Page, pageProps || {}) + }, + }, + ) + }, + }) + + const app = createSSRApp(PageWithLayout) + + // Make `pageContext` available from any Vue component + setPageContext(app, pageContext) + + return app +} diff --git a/__packages__/www/renderer/logo.svg b/__packages__/www/renderer/logo.svg new file mode 100644 index 0000000..94d3caa --- /dev/null +++ b/__packages__/www/renderer/logo.svg @@ -0,0 +1,36 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/__packages__/www/renderer/types.ts b/__packages__/www/renderer/types.ts new file mode 100644 index 0000000..55f7e10 --- /dev/null +++ b/__packages__/www/renderer/types.ts @@ -0,0 +1,11 @@ +export type PageProps = {} +// The `pageContext` that are available in both on the server-side and browser-side +export type PageContext = { + Page: any + pageProps?: PageProps + documentProps?: { + title?: string + description?: string + } + urlPathname?: string +} diff --git a/__packages__/www/renderer/usePageContext.ts b/__packages__/www/renderer/usePageContext.ts new file mode 100644 index 0000000..790132e --- /dev/null +++ b/__packages__/www/renderer/usePageContext.ts @@ -0,0 +1,21 @@ +// Hook `usePageContext()` to make `pageContext` available from any Vue component. +// See https://vite-plugin-ssr.com/pageContext-anywhere + +import { inject } from 'vue' +import type { App, InjectionKey } from 'vue' +import { PageContext } from './types' + +export { usePageContext } +export { setPageContext } + +const key: InjectionKey = Symbol() + +function usePageContext() { + const pageContext = inject(key) + if (!pageContext) throw new Error("setPageContext() not called in parent") + return pageContext +} + +function setPageContext(app: App, pageContext: PageContext) { + app.provide(key, pageContext) +} diff --git a/__packages__/www/server/index.ts b/__packages__/www/server/index.ts new file mode 100644 index 0000000..bb9a720 --- /dev/null +++ b/__packages__/www/server/index.ts @@ -0,0 +1,43 @@ +import express from 'express' +import compression from 'compression' +import { createPageRenderer } from 'vite-plugin-ssr' + +const isProduction = process.env.NODE_ENV === 'production' +const root = `${__dirname}/..` + +startServer() + +async function startServer() { + const app = express() + + app.use(compression()) + + let viteDevServer + if (isProduction) { + app.use(express.static(`${root}/dist/client`)) + } else { + const vite = require('vite') + viteDevServer = await vite.createServer({ + root, + server: { middlewareMode: 'ssr' }, + }) + app.use(viteDevServer.middlewares) + } + + const renderPage = createPageRenderer({ viteDevServer, isProduction, root }) + app.get('*', async (req, res, next) => { + const url = req.originalUrl + const pageContextInit = { + url, + } + const pageContext = await renderPage(pageContextInit) + const { httpResponse } = pageContext + if (!httpResponse) return next() + const { body, statusCode, contentType } = httpResponse + res.status(statusCode).type(contentType).send(body) + }) + + const port = process.env.PORT || 3000 + app.listen(port) + console.log(`Server running at http://localhost:${port}`) +} diff --git a/__packages__/www/tsconfig.json b/__packages__/www/tsconfig.json new file mode 100644 index 0000000..55a0adb --- /dev/null +++ b/__packages__/www/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "strict": true, + "module": "ES2020", + "moduleResolution": "Node", + "target": "ES2017", + "lib": ["DOM", "DOM.Iterable", "ESNext"], + "types": ["vite/client"], + "skipLibCheck": true, + "esModuleInterop": true, + "jsx": "preserve" + }, + "ts-node": { + "transpileOnly": true, + "compilerOptions": { + "module": "CommonJS" + } + } +} diff --git a/__packages__/www/vite.config.ts b/__packages__/www/vite.config.ts new file mode 100644 index 0000000..b358df4 --- /dev/null +++ b/__packages__/www/vite.config.ts @@ -0,0 +1,9 @@ +import vue from '@vitejs/plugin-vue' +import ssr from 'vite-plugin-ssr/plugin' +import { UserConfig } from 'vite' + +const config: UserConfig = { + plugins: [vue(), ssr()], +} + +export default config diff --git a/__packages__/www/vue.d.ts b/__packages__/www/vue.d.ts new file mode 100644 index 0000000..80b70b7 --- /dev/null +++ b/__packages__/www/vue.d.ts @@ -0,0 +1,4 @@ +declare module '*.vue' { + const Component: any + export default Component +} diff --git a/__packages__/www/yarn.lock b/__packages__/www/yarn.lock new file mode 100644 index 0000000..fb57ccd --- /dev/null +++ b/__packages__/www/yarn.lock @@ -0,0 +1,4 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + diff --git a/wk-extra.code-workspace b/wk-extra.code-workspace new file mode 100644 index 0000000..f07933d --- /dev/null +++ b/wk-extra.code-workspace @@ -0,0 +1,23 @@ +{ + "folders": [ + { + "path": "." + }, + { + "path": "__packages__/server" + }, + { + "path": "__packages__/www" + } + ], + "settings": { + "files.associations": { + ".husky/*": "shell" + }, + "sort-imports.on-save": true, + "editor.tabSize": 2, + "vetur.validation.template": false, + "vetur.validation.script": false, + "vetur.validation.style": false, + } +}