# SSR vs Prerendering dochi?
### EK
---
## 名詞定義
### 渲染
* **SSR**(Server-Side Rendering)
* **CSR**(Client-Side Rendering)
* **Rehydration**
* 透過javascript在client端,產生像SSR產生HTML’s DOM tree和資料。
* **Prerendering**
* 在client跑應用前,捕獲所有的狀態產生出靜態HTML
----
### 效能
* **TTFB**(Time to First Byte)
* 造訪網站後,收到伺服器回應第一個位元組的時間。
* **FP**(First Paint)第一次渲染
* 白屏到有畫面。
* **FCP**(First Contentful Paint)首次內容繪製
* 表示瀏覽器抓取到內容顯示的時間 (article body, etc)。
* **TTI**(Time To Interactive)可互動時間
* 表示頁面能提供完整互動功能的時間。
---
## Server Rendering

----
* Client端 cpu使用較少。
* 更快的FP和FCP,以致可以達到快速的TTI。
* 產生頁面在主機端需要更長時間,換來更慢的TTFB。
---
## Static Rendering

----
* 更快的FP和FCP,以致可以達到快速的TTI。
* 他還改善了Server Rendering的TTFB
* 靜態渲染意味著每個URL對應單獨的HTML檔案,透過cdn做緩存可以達到最好的效果。
* 但如果每個URL的內容無法預測,或是有大量不同頁面,會影響其可行性。
---
## Server Rendering vs Prerendering
* Server Rendering 不是萬用解,他的動態特性可能會造成巨大的與算成本。
* Server Rendering不能提前工作,會造成TTFB的延遲。
* Server rendering 產生靜態HTML是依據URL,但一定比Static Rendering更慢。
* 如果同時使用 **server rendering** + **HTML caching**可以顯著的減少server render時間。
---

---
## SSR(伺服器渲染)
* 使用
* Laravel
* Vue
* [套件](https://github.com/spatie/laravel-server-side-rendering)
* 套件包沒有特別說明**vuex**, **vue-router**如何使用在套件的寫法中,可以參考[範例](https://github.com/spatie/laravel-server-side-rendering-examples)。
----
* 作法
* 透過php v8或是 node原生,在進後端route的時候在server side render,把整個完整的html return回去。
* 前端點選網址,則使用前端router做觸發。
----
* 優點
* 可以渲染即時的資料,解決SEO。
* 不會有進入時白頁問題,因為不需要在前端渲染。
* 缺點
* 在vue生命週期只有 **beforeCreate**和**created**會被調用到。
* server端沒有**window**、**document**,如果要算頁寬,高度等等都會GG,要做特別處理。
----
### [實例](http://ssr.dev.parenting.com.tw)
* 使用vue-router,在每一頁看原始碼都是一次SSR,可以看到Vue component產生的內容,會在網頁原始碼內。
---
## Prerender(預渲染)
* 使用
* Koa
* Vue
* 套件
* [prerender-spa-plugin](https://github.com/chrisvfritz/prerender-spa-plugin)
* 核心技術
* [puppeteer](https://github.com/GoogleChrome/puppeteer)
* [範例](https://github.com/chrisvfritz/prerender-spa-plugin/tree/master/examples/vue2-webpack-router)
* **P.S.** 範例沒有後端router,所以產生靜態後,重整網址後,未預渲染路徑會404,此處使用Node.js架設主機撰寫wildcard。
----
### 作法
#### 指定需要做預渲染的Url
**webpack.config.js**
```javascript=71
new PrerenderSPAPlugin({
staticDir: path.join(__dirname, 'dist'),
routes: [ '/', '/about', '/contact'],
```
----
#### 用node寫一個server(Koa為例)
安裝koa
```shell=
yarn add koa koa-router koa-views koa-static
```
----
撰寫koa
引用lib
**./server.js**
```javascript=
const Koa = require('koa');
const Router = require('koa-router');
const views = require('koa-views');
const serve = require('koa-static');
const app = new Koa();
```
----
指定view的路徑與副檔名
```javascript=7
app.use(views(__dirname + '/dist', {
extension: 'html'
}));
```
寫個router
```javascript=11
const router = Router();
// Router -> /
router.get('/(.*)', async(ctx) => {
await ctx.render('index')
});
```
----
指定static folder
```javascript=17
app.use(serve(__dirname + '/dist'));
```
最後註冊router和設定port
```javascript=19
app
.use(router.routes())
.use(router.allowedMethods());
app.listen(8001);
```
----
#### SEO META怎麼辦?
----
裝 [vue-meta-info](https://github.com/muwoo/vue-meta-info)
```shell=
yarn add vue-meta-info
```
----
以 about頁面為例
**src/components/About.vue**
```javascript=8
export default {
metaInfo: {
title: "About",
meta: [
{
name: "About",
content: "About Page"
}
],
link: [
{
rel: "asstes",
href: "https://assets-cdn.github.com/"
}
]
}
};
```
----
**index.html**
```htmlembedded=
<head>
<meta charset="utf-8">
<title>{{ title }}</title>
</head>
```
----
#### 使用webpack做SSR產生靜態頁面
```shell=
yarn build
```
會產生到 **./dist** 資料夾

----
#### 執行node
```shell=
yarn serve
```
此時已經將 yarn serve改寫成 node app.js
網址為 http://127.0.0.1:8001

----
#### 如果Contact Page為動態資料,不能要產生靜態頁面
----
修改
**webpack.config.js**
```javascript=71
new PrerenderSPAPlugin({
staticDir: path.join(__dirname, 'dist'),
routes: [ '/', '/about'],
```
重新產生靜態頁面
```shell=
yarn build
```
----
或是我們偷懶一點,直接把 **./dist/contact**砍掉就好
----
重新跑,點擊contact超連結,之後看原始碼

你會發現它讀取的是Vue進入的那一頁 **./dict/index.html**,表示這頁是CSR。
----
這兩種方法可不可以混在一塊寫..........
----

等你....
---
會後討論
{"metaMigratedAt":"2023-06-14T22:50:36.653Z","metaMigratedFrom":"Content","title":"SSR vs Prerendering dochi?","breaks":true,"contributors":"[{\"id\":\"8e42ec30-16dd-49e7-9493-42a2633bb31a\",\"add\":5935,\"del\":1437}]"}