vue实现ssr渲染
Vue SSR 基础实现
Vue SSR(Server-Side Rendering)通过服务端生成完整的 HTML 字符串,提升首屏加载速度和 SEO 友好性。核心依赖 vue-server-renderer 和 Node.js 服务器。
安装必要依赖:
npm install vue vue-server-renderer express
创建服务端入口文件(server.js):
const Vue = require('vue')
const server = require('express')()
const renderer = require('vue-server-renderer').createRenderer()
server.get('*', (req, res) => {
const app = new Vue({
data: { url: req.url },
template: `<div>访问的URL是:{{ url }}</div>`
})
renderer.renderToString(app, (err, html) => {
if (err) {
res.status(500).end('Internal Server Error')
return
}
res.end(`
<!DOCTYPE html>
<html>
<head><title>Vue SSR</title></head>
<body>${html}</body>
</html>
`)
})
})
server.listen(8080)
项目结构优化
典型 SSR 项目结构应分离客户端和服务端代码:
src/
├── entry-client.js # 客户端入口
├── entry-server.js # 服务端入口
├── App.vue # 根组件
└── router.js # 路由配置
服务端入口示例(entry-server.js):
import { createApp } from './app'
export default context => {
return new Promise((resolve, reject) => {
const { app, router } = createApp()
router.push(context.url)
router.onReady(() => {
const matchedComponents = router.getMatchedComponents()
if (!matchedComponents.length) {
return reject({ code: 404 })
}
resolve(app)
}, reject)
})
}
数据预取与状态同步
使用 vuex 实现服务端数据预取:

// store.js
export function createStore() {
return new Vuex.Store({
state: { items: [] },
actions: {
fetchItems({ commit }) {
return apiCall().then(items => commit('setItems', items))
}
}
})
}
// 组件内定义serverPrefetch
export default {
serverPrefetch() {
return this.$store.dispatch('fetchItems')
}
}
客户端混合时同步状态:
// entry-client.js
if (window.__INITIAL_STATE__) {
store.replaceState(window.__INITIAL_STATE__)
}
构建配置
需要分别生成服务端和客户端构建包:
// webpack.server.config.js
module.exports = {
target: 'node',
output: {
libraryTarget: 'commonjs2'
}
}
// webpack.client.config.js
module.exports = {
entry: { app: './src/entry-client.js' }
}
生产环境优化
使用 LRU 缓存页面:

const microCache = LRU({
max: 100,
maxAge: 1000 * 60 // 1分钟缓存
})
server.get('*', (req, res) => {
const hit = microCache.get(req.url)
if (hit) return res.end(hit)
// ...渲染逻辑
microCache.set(req.url, html)
})
启用 bundleRenderer 提升性能:
const { createBundleRenderer } = require('vue-server-renderer')
const renderer = createBundleRenderer(serverBundle, {
runInNewContext: false,
template: fs.readFileSync('./index.template.html', 'utf-8')
})
常见问题解决
处理客户端激活警告:
确保客户端构建包含 vue-template-compiler,版本与服务端 Vue 一致。
静态资源路径问题:
使用 publicPath 配置:
// webpack.client.config.js
output: {
publicPath: '/dist/'
}
异步组件处理:
// router.js
components: () => import('./Foo.vue').then(c => c.default || c)
以上实现方案可根据项目需求进行扩展,建议结合官方文档和实际场景调整配置参数。






