-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- 將專案改成 SSR 的渲染模式。
- Loading branch information
naremloa
committed
Mar 2, 2021
1 parent
3f13584
commit 213d088
Showing
7 changed files
with
604 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
/* eslint-disable import/no-extraneous-dependencies */ | ||
/* eslint-disable global-require */ | ||
/* eslint-disable import/no-unresolved */ | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const express = require('express'); | ||
|
||
const PORT = process.env.PORT || 8080; | ||
|
||
async function createServer( | ||
root = process.cwd(), | ||
isProd = process.env.NODE_ENV === 'production', | ||
) { | ||
const resolve = (p) => path.resolve(__dirname, p); | ||
|
||
const indexProd = isProd | ||
? fs.readFileSync(resolve('dist/client/index.html'), 'utf-8') | ||
: ''; | ||
|
||
const manifest = isProd | ||
? require('./dist/client/ssr-manifest.json') | ||
: {}; | ||
|
||
const app = express(); | ||
|
||
let vite; | ||
if (!isProd) { | ||
vite = await require('vite').createServer({ | ||
root, | ||
logLevel: 'info', | ||
server: { | ||
middlewareMode: true, | ||
}, | ||
}); | ||
app.use(vite.middlewares); | ||
} else { | ||
app.use(require('compression')()); | ||
app.use( | ||
require('serve-static')(resolve('dist/client'), { | ||
index: false, | ||
}), | ||
); | ||
} | ||
|
||
app.use('*', async (req, res) => { | ||
try { | ||
const url = req.originalUrl; | ||
|
||
let template; | ||
let render; | ||
if (!isProd) { | ||
// always read fresh template in dev | ||
template = fs.readFileSync(resolve('./index.html'), 'utf-8'); | ||
template = await vite.transformIndexHtml(url, template); | ||
render = (await vite.ssrLoadModule('/src/entry-server.js')).render; | ||
} else { | ||
template = indexProd; | ||
render = require('./dist/server/entry-server.js').render; | ||
} | ||
|
||
const [appHtml, preloadLinks] = await render(url, manifest); | ||
|
||
const html = template | ||
.replace('<!--preload-links-->', preloadLinks) | ||
.replace('<!--app-html-->', appHtml); | ||
|
||
res.status(200).set({ 'Content-Type': 'text/html' }).end(html); | ||
} catch (e) { | ||
if (vite) vite.ssrFixStacktrace(e); | ||
console.log(e.stack); | ||
res.status(500).end(e.stack); | ||
} | ||
}); | ||
|
||
return { app, vite }; | ||
} | ||
|
||
createServer().then(({ app }) => app.listen(PORT, () => { | ||
console.log(`App listening on port ${PORT}`); | ||
console.log('Press Ctrl+C to quit.'); | ||
})); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { createApp } from './main'; | ||
|
||
const { app, router } = createApp(); | ||
|
||
// wait until router is ready before mounting to ensure hydration match | ||
router.isReady().then(() => { | ||
app.mount('#app'); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
/* eslint-disable import/no-extraneous-dependencies */ | ||
import { renderToString } from '@vue/server-renderer'; | ||
import { createApp } from './main'; | ||
|
||
function renderPreloadLink(file) { | ||
if (file.endsWith('.js')) { | ||
return `<link rel="modulepreload" crossorigin href="${file}">`; | ||
} | ||
if (file.endsWith('.css')) { | ||
return `<link rel="stylesheet" href="${file}">`; | ||
} | ||
// TODO | ||
return ''; | ||
} | ||
|
||
function renderPreloadLinks(modules, manifest) { | ||
let links = ''; | ||
const seen = new Set(); | ||
modules.forEach((id) => { | ||
const files = manifest[id]; | ||
if (files) { | ||
files.forEach((file) => { | ||
if (!seen.has(file)) { | ||
seen.add(file); | ||
links += renderPreloadLink(file); | ||
} | ||
}); | ||
} | ||
}); | ||
return links; | ||
} | ||
|
||
export async function render(url, manifest) { | ||
const { app, router } = createApp(); | ||
|
||
// set the router to the desired URL before rendering | ||
router.push(url); | ||
await router.isReady(); | ||
|
||
// passing SSR context object which will be available via useSSRContext() | ||
// @vitejs/plugin-vue injects code into a component's setup() that registers | ||
// itself on ctx.modules. After the render, ctx.modules would contain all the | ||
// components that have been instantiated during this render call. | ||
const ctx = {}; | ||
const html = await renderToString(app, ctx); | ||
|
||
// the SSR manifest generated by Vite contains module -> chunk/asset mapping | ||
// which we can then use to determine what files need to be preloaded for this | ||
// request. | ||
const preloadLinks = renderPreloadLinks(ctx.modules, manifest); | ||
return [html, preloadLinks]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,22 @@ | ||
import { createApp } from 'vue'; | ||
import { createSSRApp } from 'vue'; | ||
import { createRouter } from './router'; | ||
import App from './App.vue'; | ||
import './styles/index.css'; | ||
|
||
import { worker } from './mocks/browser'; | ||
|
||
worker.start(); | ||
// SSR requires a fresh app instance per request, therefore we export a function | ||
// that creates a fresh app instance. If using Vuex, we'd also be creating a | ||
// fresh store here. | ||
|
||
const app = createApp(App); | ||
const router = createRouter(); | ||
app.use(router); | ||
app.mount('#app'); | ||
// import { worker } from './mocks/browser'; | ||
|
||
// worker.start(); | ||
|
||
export function createApp() { | ||
const app = createSSRApp(App); | ||
const router = createRouter(); | ||
app.use(router); | ||
return { app, router }; | ||
} |
Oops, something went wrong.