服务端渲染(SSR)是将同一个组件渲染为服务器端的 HTML 字符串,将它们直接发送到浏览器,最后将这些静态标记"激活"为客户端上完全可交互的应用程序。
和纯客户端的单页面应用不同(SPA),服务端渲染可以解决 首屏渲染慢,SEO搜索的问题。
Vue的SSR可以用Nuxt.js实现,以及使用Vue-SSR实现。
Vue-SSR实现原理
实现原理:Source部分就是我们所编写的源代码,所有代码有一个公共入口,就是app.js,紧接着就是服务端的入口
(entry-server.js)和客户端的入口(entry-client.js)。当完成所有源代码的编写之后,我们通过webpack的构建,打包出两个bundle,分别是server bundle和client bundle;当用户进行页面访问的时候,先是经过服务端的入口,将vue组建组装为html字符串,并混入客户端所访问的html模板中,最终就完成了整个ssr渲染的过程。
简单实现
安装
npm install vue vue-server-renderer --save
目录结构
src
├── components
│ ├── Foo.vue
│ ├── Bar.vue
│ └── Baz.vue
├── App.vue
├── app.js # 通用 entry(universal entry)
├── entry-client.js # 仅运行于浏览器
└── entry-server.js # 仅运行于服务器
app.js
是应用程序的通用入口,入口应该为每个请求创建一个新的跟Vue实例。因为Node.js是长期运行的进程,如果我们在多个请求之间使用一个共享的实例,很容易导致交叉请求状态污染 (cross-request state pollution)。
因此,我们不应该直接创建一个应用程序实例,而是应该暴露一个可以重复执行的工厂函数,为每个请求创建新的应用程序实例,这与每个用户在自己的浏览器中使用新应用程序的实例类似。
// 导出一个工厂函数,用于创建新的
// 应用程序、router 和 store 实例
export function createApp () {
const app = new Vue({
// 根实例简单的渲染应用程序组件。
render: h => h(App)
})
return { app }
}
entry-client.js
客户端 entry 只需创建应用程序,并且将其挂载到 DOM 中
import { createApp } from './app'
const { app } = createApp()
// 这里假定 App.vue 模板中根元素具有 `id="app"`
app.$mount('#app')
entry-server.js
服务器 entry 使用 default export 导出函数,并在每次渲染中重复调用此函数
import { createApp } from './app'
export default context => {
const { app } = createApp()
return app
}
用Vue-Router实现路由
和创建Vue实例相似,返回一个函数
// router.js
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
export function createRouter () {
return new Router({
mode: 'history', // 兼容服务器端
routes: [
// ...
]
})
}
在app.js中加入Vue-Router
export function createApp () {
// 创建 router 实例
const router = createRouter()
const app = new Vue({
// 注入 router 到根 Vue 实例
router,
render: h => h(App)
})
// 返回 app 和 router
return { app, router }
}
在entry-server.js中实现服务端路由逻辑
export default async context => {
// 因为有可能会是异步路由钩子函数或组件,所以我们将返回一个 Promise,
// 以便服务器能够等待所有的内容在渲染前,
// 就已经准备就绪。
const { app, router } = createApp()
// 设置服务器端 router 的位置
router.push(context.url)
// 等到 router 将可能的异步组件和钩子函数解析完
await new Promise(router.onReady.bind(router))
return app
}
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!