Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
b9c163fd06 | |||
2f6b3524c4 |
@ -55,5 +55,8 @@ jobs:
|
|||||||
|
|
||||||
- name: 上传产物到远程服务器
|
- name: 上传产物到远程服务器
|
||||||
run: |
|
run: |
|
||||||
scp output.zip default@10.0.0.3:/srv/publish/ao3-mirror-ssr/${{ steps.extract_tag.outputs.tag }}.zip
|
TAG=${{ steps.extract_tag.outputs.tag }}
|
||||||
|
scp output.zip default@10.0.0.3:/srv/publish/ao3-mirror-ssr/${TAG}.zip
|
||||||
|
ssh default@10.0.0.3 sh -c 'cd /srv/publish/ao3-mirror-ssr/; rm -f latest.zip; ln -s ${TAG}.zip latest.zip'
|
||||||
|
|
||||||
|
|
||||||
|
26
server.js
26
server.js
@ -16,6 +16,11 @@ const templateHtml = isProduction
|
|||||||
const app = express()
|
const app = express()
|
||||||
app.use(cookieParser());
|
app.use(cookieParser());
|
||||||
|
|
||||||
|
const MESSAGE = {
|
||||||
|
404: 'Not Found',
|
||||||
|
0: 'Unknown'
|
||||||
|
}
|
||||||
|
|
||||||
// Add Vite or respective production middlewares
|
// Add Vite or respective production middlewares
|
||||||
/** @type {import('vite').ViteDevServer | undefined} */
|
/** @type {import('vite').ViteDevServer | undefined} */
|
||||||
let vite
|
let vite
|
||||||
@ -42,19 +47,30 @@ app.use('*all', async (req, res) => {
|
|||||||
/** @type {string} */
|
/** @type {string} */
|
||||||
let template
|
let template
|
||||||
/** @type {import('./src/entry-server.js').render} */
|
/** @type {import('./src/entry-server.js').render} */
|
||||||
let render
|
let render, getRoute
|
||||||
if (!isProduction) {
|
if (!isProduction) {
|
||||||
// Always read fresh template in development
|
// Always read fresh template in development
|
||||||
template = await fs.readFile('./index.html', 'utf-8')
|
template = await fs.readFile('./index.html', 'utf-8')
|
||||||
template = await vite.transformIndexHtml(url, template)
|
template = await vite.transformIndexHtml(url, template)
|
||||||
render = (await vite.ssrLoadModule('/src/entry-server.js')).render
|
const module = await vite.ssrLoadModule('/src/entry-server.js')
|
||||||
|
render = module.render
|
||||||
|
getRoute = module.getRoute
|
||||||
} else {
|
} else {
|
||||||
template = templateHtml
|
template = templateHtml
|
||||||
render = (await import('./dist/server/entry-server.js')).render
|
const module = await import('./dist/server/entry-server.js')
|
||||||
|
render = module.render
|
||||||
|
getRoute = module.getRoute
|
||||||
}
|
}
|
||||||
const { stream, piniaState } = await render(url, req.cookies, req.headers.host)
|
const { router, code } = await getRoute(url)
|
||||||
|
if (code != 200 && !req.accepts('html')) {
|
||||||
|
res.status(code).set({ 'Content-Type': 'text/plain' })
|
||||||
|
res.write(MESSAGE[code] || MESSAGE[0])
|
||||||
|
res.end()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const { stream, piniaState } = await render(router, req.cookies, req.headers.host)
|
||||||
const [htmlStart, htmlEnd] = template.split('<!--app-html-->')
|
const [htmlStart, htmlEnd] = template.split('<!--app-html-->')
|
||||||
res.status(200).set({ 'Content-Type': 'text/html' })
|
res.status(code).set({ 'Content-Type': 'text/html' })
|
||||||
res.write(htmlStart)
|
res.write(htmlStart)
|
||||||
for await (const chunk of stream) {
|
for await (const chunk of stream) {
|
||||||
if (res.closed) break
|
if (res.closed) break
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
import { decompress } from 'compress-json'
|
import { decompress } from 'compress-json'
|
||||||
import './main.css'
|
import './main.css'
|
||||||
import { createApp } from './main'
|
|
||||||
|
|
||||||
const { app, pinia, router } = createApp()
|
import { createApp } from './main'
|
||||||
|
import { createSSRRouter } from './router.js'
|
||||||
|
|
||||||
|
const { app, pinia } = createApp()
|
||||||
|
const router = createSSRRouter()
|
||||||
|
|
||||||
|
app.use(router)
|
||||||
|
|
||||||
if (window.__PINIA_STATE__) {
|
if (window.__PINIA_STATE__) {
|
||||||
pinia.state.value = decompress(window.__PINIA_STATE__)
|
pinia.state.value = decompress(window.__PINIA_STATE__)
|
||||||
|
@ -1,19 +1,28 @@
|
|||||||
import { renderToWebStream, renderToString } from 'vue/server-renderer'
|
import { renderToWebStream, renderToString } from 'vue/server-renderer'
|
||||||
import { createApp } from './main'
|
import { createApp } from './main'
|
||||||
|
|
||||||
export async function render(_url, cookies, host) {
|
import { createSSRRouter } from './router.js'
|
||||||
const { app, pinia, router } = createApp()
|
|
||||||
|
export async function getRoute(_url) {
|
||||||
|
const router = createSSRRouter()
|
||||||
await router.push(_url)
|
await router.push(_url)
|
||||||
await router.isReady()
|
await router.isReady()
|
||||||
|
const route = router.currentRoute.value.matched[0]
|
||||||
|
const code = route.meta.code || 200
|
||||||
|
return { router, code }
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function render(router, cookies, host) {
|
||||||
|
const { app, pinia } = createApp()
|
||||||
|
|
||||||
|
app.use(router)
|
||||||
const ctx = {
|
const ctx = {
|
||||||
cookies,
|
cookies,
|
||||||
host,
|
host,
|
||||||
initialState: {}
|
initialState: {}
|
||||||
}
|
}
|
||||||
// await new Promise((resolve) => setTimeout(resolve, 0))
|
|
||||||
const stream = renderToWebStream(app, ctx)
|
const stream = renderToWebStream(app, ctx)
|
||||||
const initialState = ctx.initialStat
|
|
||||||
const piniaState = pinia.state.value
|
const piniaState = pinia.state.value
|
||||||
return { stream, initialState, piniaState }
|
return { stream, piniaState }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,19 +2,16 @@ import { createSSRApp } from 'vue'
|
|||||||
import { createPinia } from 'pinia'
|
import { createPinia } from 'pinia'
|
||||||
|
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import { createSSRRouter } from './router.js'
|
|
||||||
|
|
||||||
import ClientOnly from './ssr/ClientOnly.vue'
|
import ClientOnly from './ssr/ClientOnly.vue'
|
||||||
import Hr from './ui/BetterHr.vue'
|
import Hr from './ui/BetterHr.vue'
|
||||||
|
|
||||||
export function createApp() {
|
export function createApp() {
|
||||||
const app = createSSRApp(App)
|
const app = createSSRApp(App)
|
||||||
const router = createSSRRouter()
|
|
||||||
const pinia = createPinia()
|
const pinia = createPinia()
|
||||||
app.use(pinia)
|
app.use(pinia)
|
||||||
app.use(router)
|
|
||||||
app
|
app
|
||||||
.component('ClientOnly', ClientOnly)
|
.component('ClientOnly', ClientOnly)
|
||||||
.component('Hr', Hr)
|
.component('Hr', Hr)
|
||||||
return { app, pinia, router }
|
return { app, pinia }
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,8 @@ export function createSSRRouter() {
|
|||||||
component: () => import('./views/fallback/NotFound.vue'),
|
component: () => import('./views/fallback/NotFound.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
title: "页面未找到",
|
title: "页面未找到",
|
||||||
hidden: true
|
hidden: true,
|
||||||
|
code: 404
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]})
|
]})
|
||||||
|
Reference in New Issue
Block a user