1.最近学习vue 初探一下vue ssr 写个小demo
1.服务端渲染的优势缺点
1)、SSR渲染的优势:
(1)更利于SEO;
(2)更利于首屏渲染(特别是对于缓慢的网络情况或运行缓慢的设备,内容更快到达)
2)、SSR渲染的缺点:
(1)服务器压力大,考虑服务器端负载。
(2)开发条件受限,只会执行到ComponentMount之前的生命周期钩子,引用第三方库不可用其他生命周期钩子,引用库选择产生很大的限制。
(3)学习成本增大,需要学习构建设置和部署的更多要求。
2.直接上代码 参考 https://ssr.vuejs.org/zh/guide/
1)npm init
2)添加vue 各种依赖
3)创建app.js 与router.js文件 以及组件(不做详细介绍)
要做服务端渲染,每次用户访问,都必须重新创建vue,与router实例,采用工厂模式 ,router模式必须用history
import Vue from 'vue'
import VueRouter from 'vue-router'
import page1 from '../page/page1.vue';
import page2 from '../page/page2.vue';
import page3 from '../page/page3.vue';
Vue.use(VueRouter)
export function createRouter() {
return new VueRouter({
mode: 'history',
routes: [{
path: '/',
component: page1
},
{
path: '/page2',
component: page2
},
{
path: '/page3',
component: page3
}
]
})
}
import Vue from 'vue'
import App from './app.vue';
import { createRouter } from './router/router'
export function createApp() {
const router = createRouter()
const app = new Vue({
router,
render: (h) => h(App)
})
return { app, router }
}
4)分别创建entry-client.js entry-server.js 作为服务端与客户端的入口
entry-client.js
import { createApp } from './app'
const { app, router } = createApp()
router.onReady(() => {
app.$mount('#app')
})
entry-server.js
import { createApp } from './app'
export default context => {
return new Promise((reslove, reject) => {
const { app, router } = createApp()
router.push(context.url)
/* console.log(router); */
router.onReady(() => {
let matchs = router.getMatchedComponents()
if (!matchs.length) {
return reject({ code: 404 })
}
console.log(123456);
reslove(app)
}, reject)
})
}
5)webpack.config.client.js 与webpack.config.server.js 这里的配置比较简单 分别把entry-client.js entry-server.js作为入口文件打包 server的 比较中用的设置 devtool: 'source-map' libraryTarget: 'commonjs2', target: 'node',还有就是最重要的插件 new VueSSRServerPlugin() 客户端 new VueSSRClientPlugin(),
6) server.js 采用express 作为后台
const path = require('path')
const { createBundleRenderer } = require('vue-server-renderer')
const fs = require('fs')
const express = require('express')
const app = express()
const serverbundle = require(path.resolve(__dirname, './dist/server/vue-ssr-server-bundle.json'))
const clientbundle = require(path.resolve(__dirname, './dist/client/vue-ssr-client-manifest.json'))
const template = fs.readFileSync(path.resolve(__dirname, './static/tepelate.ssr.html'), 'utf-8')
const render = createBundleRenderer(serverbundle, {
runInNewContext: false,
clientManifest: clientbundle,
template: template
})
app.use(express.static(path.resolve(__dirname, './dist/client'), { index: false }))
app.get('*', (req, res) => {
const context = {
url: req.url
}
let stream = render.renderToStream(context)
let html = '';
stream.on('data', data => {
html += data.toString()
})
stream.on('end', () => {
// console.log(html) // 渲染完成
res.end(html)
})
stream.on('error', err => {
console.log(err)
})
})
app.listen(9301, () => {
console.log('服务器已启动!')
})