iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 28
1
Modern Web

從 0 開始建一個 Static Site Generator系列 第 28

Day 28: 介紹 Vue 的 Server Side Render

  • 分享至 

  • xImage
  •  

雖然一開始說 Vue 因為有 Single File Component ,所以要 Server Side Render 可能會碰到需要用 bundler 的情況,不過用 React 時,在最後碰到圖片時還是非要用 hook require 的方式來解決,實際上早點用 bundler 或許也不用做到這樣,回到正題,雖然我個人是 React 派的,但 Vue 在某些方面真的做的很好,這篇也會提到

Vue 做好了什麼

這邊提到的只是就這個系列而言,我沒有要來寫一篇 React 跟 Vue 的比較文 (雖然我寫過,但那是很久以前的事了)

在 Vuex 中分離 actionmutation

還記得我們把 Redux 的 actions 全部保存下來嗎?但實際上有些只是用來觸發 AJAX 之類的非同步的工作用的 action ,並不是真的要改變資料,而在 Vuex 中, actionmutation 有明確的工作分別, mutation 才能改變資料,如果用 Vuex 就只要保存 mutation 就夠了

非同步的 vue-router

或許知道這個東西的人可能比較少, vue-router 的 middleware 是非同步的,所以 vue-router 從網址改變,到實際跳轉網頁前還可以做一些事,也可以反悔,取消掉使用者的跳轉, react-router 則是要跳轉完才可以開始動作,不知道你有沒有想到這東西可以用在哪?可以用在抓資料上,只要在 middleware 中加入抓資料的程式碼,我們也不用自己先把資料抓完才開始 render 了,只要等到 vue-router 通知我們網址已經轉過去了 (正常情況下應該是沒有機會用到 router.onReady 這個 API 吧)

SFC

這個其實有好有壞,壞處之前講過了,因為一定要編譯,所以初期會多出 bundler 要設定,不過好處是除了現有的 html, scriptstyle ,它可以加入自訂的區塊,這個功能也很少用,不過你可以看看 Gridsome ,它就用這個功能來放 page query 跟 static query ,雖然 page query 沒有這個問題,但 static query 是要用 babel 從原始碼中抽出來的,它也是正常的程式碼的一部份,要從一份原始碼中將其區格出來也是一個麻煩,雖然差別我是沒有覺得到很大

Vue 的 SSR

Vue 基本的 SSR 該說是大同小異嗎?同樣的也是 renderToStringrenderToStream,不過不一樣的是,該說 Vue 的定位真不愧是框架, html 的 template 也可以由它產生, Vuex 的初始 state 也會幫你加入產生的 html 中 (前題是如果你有提供的話)

Vue 的元件其實有個 API 叫 serverPrefetch,它會在 Server 端被執行,讓你可以在 Server 端呼叫 Vuex 的 action ,從而把資料存進去:

<script>
import {mapActions} from 'vuex'
export default {
  serverPrefetch() {
    return this.fetchData()
  },

  methods: {
    ...mapActions(['fetchData']),
  },
}
</script>

這個 API Vue 也會自動的等待它完成,所以在 Vue 中,完全不用擔心之前碰到的什麼 render 過程是同步的問題,另外 Vue 的元件上還有個屬性:

<script>
export default {
  // created 跟 beforeCreate 才會在 server 端執行,但 beforeCreate 時 Vue 的 instance 又還沒建好
  created() {
    // 這個物件會跟 render 時傳入的一個物件是同一個,所以可以用這邊傳資料回去給 render 的程式
    this.$ssrContext.foo = 42
  }
}
</script>

在 render 時 Vue 要傳入一個 object :

import { createRenderer } from 'vue-server-renderer'

const renderer = createRenderer()

// 這就會是上面的 `$ssrContext`
const context = {}
// 這樣就能取得完整的 html
const html = await renderer.renderToString(app, context)

下一篇我們再來實際用一次 Vue 的 SSG


上一篇
Day 27: Incremental build
下一篇
Day 29: 實作 Vue 的 Server Side Render
系列文
從 0 開始建一個 Static Site Generator30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言