与传统的spa渲染,服务器端渲染可以有更好的seo,更快的内容到达时间(time to content)。但是服务器端渲染并不是必须的,是否使用,需要细细斟酌。本文是一个完整的服务器渲染的实现,结合一个例子实现。同时假如是仅仅几个静态页面,完全可以使用预渲染实现,没必要完全使用服务器实时动态编译html。
在学习以下内容时请先观看下官方的文档
基本用法:(vue-server-renderer)注意一下几点
1、推荐使用 Node.js 版本 6+。
2、vue-server-renderer 和 vue 必须匹配版本。
3、vue-server-renderer 依赖一些 Node.js 原生模块,因此只能在 Node.js 中使用。我们可能会提供一个更简单的构建,可以在将来在其他「JavaScript 运行时(runtime)」运行
基本环境为 vue2.X+koa2,vue2.X和koa2的环境请自行搭建
npm install vue-server-render --save
const Koa = require('koa');
const Vue = require('vue');
const renderer= require('vue-server-renderer').createRenderer({
template: require('fs').readFileSync('./temp.html', 'utf-8')
});
const server= new Koa();
server.use(async ctx=>{
const app = new Vue({
data:{
msg:'hello vue+node ssr'
},
template:'<h4>{{msg}}</h4>'
});
renderer.renderToString(app, (err, html)=>{
if(err){
ctx.status = 500;
}
ctx.body = html;
})
});
server.listen(5000, ()=>{
console.log('server is start.........');
})
渲染模板(temp.html)
<!DOCTYPE html>
<html lang="en">
<head>
<title>title</title>
</head>
<body>
<!--vue-ssr-outlet-->
</body>
</html>
以上我们就实现了一个简单的ssr渲染。但是以上内容还不能应用于生产环境,我们以下进一步深入。
避免状态单列:我们为用户每次请求创建vue实例,如果我们在多个请求之间使用一个共享的实例,很容易导致交叉请求状态污染(cross-request state pollution)。
因此,我们不应该直接创建一个应用程序实例,而是应该暴露一个可以重复执行的工厂函数,为每个请求创建新的应用程序实例:
//app.js
import Vue from 'vue';
import App from './app.vue';
export function createApp(){
const app = new Vue({
render:h=>h(App)
});
return app;
}
//app.vue
<template>
<div>
<div class="demo">
<h1>Simple-webpack demo</h1>
<p>这是一个简单的 Vue demo</p>
</div>
</div>
</template>
创建client入口文件和server入口文件,并创建对应的webpack文件
//entry-client.js
import { createApp } from './app.js';
const app = createApp();
app.$mount("#app");
//entry-server.js
import { createApp } from './app.js';
const app = createApp();
return app;
webpack配置:
//webpack.client.js
............
const VueSSRClientPluguin = require('vue-server-renderer/client-plugin');
..............
plugins:[
new VueSSRClientPluguin()
]
//webpack.server.js
const VueSSRServerPlugin = require('vue-server-renderer/server-plugin');
...............
entry:{
main:'./entry-server.js'
},
output:{
filename:'server-bundle.js',
libraryTarget:'commonjs2'
},
............
plugins:[
new VueSSRServerPlugin ()
]
执行 webpack.client.js 和 webpack.server.js 文件,会生成 vue-ssr-server-bundle.json 和 vue-ssr-client-manifest.json 两个文件。服务端使用这两个文件解析文件。
const Koa = require('koa');
const Server = new Koa();
const { createBundleRenderer } = require('vue-server-renderer');
const path = require('path');
const fs = require('fs');
const template = fs.readFileSync(path.resolve(__dirname, '/temp.html'), 'UTF-8');
const serverBundle = require('./dist/vue-ssr-server-bundle.json');
const clientMainfest = require('./dist/vue-ssr-client-manifest.json');
const renderer = createBundleRenderer(serverBundle,{
basedir: path.resolve(__dirname, './dist'),
runInNewContext: false,
template,
clientMainfest
});
const renderToString = function(context){
return new Promise((resolve, reject) => {
renderer.renderToString(context, (err, html)=>{
if(err){
reject(err);
}
resolve(html);
});
});
}
Server.use(async ctx =>{
let html = '';
try{
html = await renderToString({});
}catch(err){
ctx.throw(500, err)
}
ctx.body = html;
});
Server.listen(5000, ()=>{
console.log('server is start.........');
});
这样就完成了vue+node的ssr渲染。
附上demo的git地址:https://github.com/yspwf/ssr-vue-node-
网友评论