作为前端开发者 3 年了,第一次认真学习 SSR。
SSR 本质上是渲染应用程序的“快照”
因为,第一次做 C 端产品。日本最大红酒电商系统,对页面初始化要求特别高。
SPA,浏览器需要请求 JS,解析 JS,并渲染页面,再执行 JS 请求数据。
SSR,浏览器请求页面,服务器请求数据(Data),然后将 Data 和 JS 直接组合到 HTML,一次性返回给浏览器。浏览器接到页面可以直接渲染最终结果。
如果是 server 也是 JS 技术栈,还有一个优势就是代码共享。
Vue SSR 劣势(Virtual-DOM JS framework),因为每个请求都是一个独立的实例,大量占用 CPU 资源。
只是用来改善少数营销页面(例如 /, /about, /contact 等)的 SEO,那么你可能需要预渲染。 在构建时 (build time) 简单地生成针对特定路由的静态 HTML 文件。
data() {}
中设置初始值是多余的。SSR 本质上是渲染应用程序的“快照”
所以如果应用程序依赖异步数据,在开始渲染之前,需要先预期并解析好这些数据。
// store/modules/foo.js
export default {
namespaced: true,
// 重要信息:state 必须是一个函数,
// 因此可以创建多个实例化该模块
state: () => ({
items: {}
}),
actions: {
fetchItem ({ commit }, id) {
// `store.dispatch()` 会返回 Promise,
// 以便我们能够知道数据在何时更新
return fetchItem(id).then(item => {
commit('setItem', { id, item })
})
}
},
mutations: {
setItem (state, { id, item }) {
Vue.set(state.items, id, item)
}
}
}
何时,何地执行 dispatch action
?
合理的做法是在路由组件上放置数据。
Nuxt 有 asyncData
或 fetch
函数。
<!-- Item.vue -->
<template>
<div>{{ item.title }}</div>
</template>
<script>
export default {
asyncData ({ store, route }) {
// 触发 action 后,会返回 Promise
return store.dispatch('fetchItem', route.params.id)
},
computed: {
// 从 store 的 state 对象中的获取 item。
item () {
return this.$store.state.items[this.$route.params.id]
}
}
}
</script>
vue 通过 data-server-rendered
属性识别哪些 HTML 是服务器渲染的。
<div id="app" data-server-rendered="true">
因为每个请求都需要一个全新的 Vue 实例,Code Splitting 还是不能少
const Foo = () => import('./Foo.vue')
refs: