渲染Vue应用
import { createSSRApp } from 'vue'import { renderToString } from 'vue/server-renderer'
// 创建一个 Vue 实例const app = createSSRApp({ template: ` <div> <h1>Hello, Server-Side Rendering!</h1> <p>{{ message }}</p> <button @click="count++">{{ count }}</button> </div> `, data: () => ({ count: 1, message: 'This is a server-side rendered page', }),})
const html = await renderToString(app)console.log(html)之后 node server.js 就能看到生成的 html 字符串:
> node server.js<div><h1>Hello, Server-Side Rendering!</h1><p>This is a server-side rendered page</p><button>1</button></div>搭建服务器
安装 express
pnpm install express然后修改 server.js,代码如下:
import { createSSRApp } from 'vue'import { renderToString } from 'vue/server-renderer'import express from 'express'
// 创建服务器实例const server = express()
// 创建一个 Vue 实例const app = createSSRApp({ template: ` <div> <h1>Hello, Server-Side Rendering!</h1> <p>{{ message }}</p> <button @click="count++">{{ count }}</button> </div> `, data: () => ({ count: 1, message: 'This is a server-side rendered page', }),})
server.get('/', async (req, res) => { try { const html = await renderToString(app) res.send(html) } catch (err) { res.status(500).send('Server Error') }})
server.listen(3000, () => { console.log('服务器启动成功,监听3000端口...')})为了方便,我们安装 nodemon 并且在 pacakge.json 中增加如下的脚本:
"scripts": { "start": "nodemon --watch server.js server.js"},之后就可以使用 pnpm start 来启动服务器,并且在 server.js 内容发生改变后自动重启服务器。
使用HTML模板
接下来继续,在浏览器中右键,点击 “View Page Source” 查看网页源码,可以看到目前拿到的就是渲染出来的那一段字符串,这显然是不太合适的。我们想要浏览器拿到的是一个完整的 HTML 文档,有 head、meta、body 这些元素。
此时我们可以指定一个 HTML 模板。在 demo 根目录下创建一个 index.html
<!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>{{ title }}</title> {{ meta }} </head> <body> <!-- 注意这里一定要保证挂载点和外层div在同一行,否则后面同构的时候会找不到挂载点 --> <div id="app"><!--vue-ssr-outlet--></div> </body></html>然后修改 server.js
import { createSSRApp } from 'vue'import { renderToString } from 'vue/server-renderer'import express from 'express'import fs from 'fs'
// 创建服务器实例const server = express()
// 创建一个 Vue 实例const app = createSSRApp({ template: ` <div> <h1>Hello, Server-Side Rendering!</h1> <p>{{ message }}</p> <button @click="count++">{{ count }}</button> </div> `, data: () => ({ count: 1, message: 'This is a server-side rendered page', }),})
// 定义一个配置对象,表示页面相关信息,title,metaconst desc = { title: '这是一个ssr页面', meta: '<meta name="description" content="服务器端渲染"></meta>',}
server.get('/', async (req, res) => { try { const content = await renderToString(app, desc) // 读取模板文件 const template = fs.readFileSync('./index.html', 'utf-8') // 插入渲染内容到模板中 const html = template .replace('{{ title }}', desc.title) .replace('{{ meta }}', desc.meta) .replace('<!--vue-ssr-outlet-->', content) res.send(html) } catch (err) { console.log(err, 'err') res.status(500).send('Server Error') }})
server.listen(3000, () => { console.log('服务器启动成功,监听3000端口...')})在上面的代码中,通过 node.js 的 fs 模块来读取 index.html 文件,读取到的内容是字符串的形式,之后使用字符串的 replace 方法进行内容替换,最后再返回给客户端。
-EOF-