###### tags: `Rendering Patterns`
# [Render] Static Rendering(SSG靜態渲染)
## introduction
- SSR
- 缺點:TTFB(Time to First Byte)需要較多時間
- CSR
- 缺點:因為JS bundle size較大,可能影響FCP(First Contentful Paint), LCP(Largest Contentful Paint) and TTI(Time to Interactive)
- SSG解決以上問題的方法
- server build time的時候預先產生html page, 達到當client-side發出請求可以快速拿到html頁面並互動,且可使client-side的JS bundle size縮小, 達到較快的 **FCP/TTI**
[SSG Video](https://www.patterns.dev/posts/static-rendering/)

## SSG - Basic Structure
- 顧名思義就是使用在靜態內容的頁面: 電子商務的‘About us'頁面, ‘Contact us'頁面, etc.而非 ’logged-in user‘客製化頁面
- 支援SSG的Frameworks有:Next.js, Gatsby, and VuePress
- 當後端sever build next.js時about頁面會先被render成HTML file(about.html), 當前端發出route “/about”請求時回傳給前端 [Next.js demo-SSG](https://codesandbox.io/s/ssg-fmkqyx)
## SSG with Data
### intro
- 不須先跟Database拿資料: 靜態頁面'About us' or 'Contact us', 不需要跟Database拿資料就可以直接轉成HTML
- 需要先跟Database拿資料: 個別化頁面'blog pages' or 'product pages', 在server build time時透過getStaticProps函式先跟Database拿資料完成(resolve)後,跟template merge 轉成 HTML
- HTML pages的數量取決於個人化頁面資料量
- 個別化頁面與其他頁面的相依性:'product pages'跟navigation頁面有相依性所以需要先跟Database要navigation頁面所需的資料像是分類和格式化資料render產品的分類列表 [Next.js Demo-n6wrkh](https://codesandbox.io/s/musing-spence-n6wrkh?file=/pages/index.js)
### Listing Page(列表頁面) - All Items
- 在**sever build time**時匯出page的同時也會匯出 **`getStaticProps()`** 函式
- `getStaticProps`是一個 **`async`** 函式, 利用這個函式跟外部Database獲取資料, 另一方面, 有`getStaticProps`函式 Next.js 就會知道要先跟外部要資料成功後, 再把資料塞進 **`props`** render html
- **`getStaticProps`** 只會在sever-side被執行, 不會在client-side被執行, 所以不會被打包傳進client-side的JS檔
- [Next.js Demo-98ze4k](https://codesandbox.io/s/amazing-torvalds-98ze4k?file=/pages/index.js)
### Individual Details Page(個別化詳細頁面) - Per Item
- 為列表頁面上列出的每個產品提供一個單獨的詳細頁面可使用**dynamic routes**, `getStaticPaths` 可以事先定義哪些單獨頁面需要產生 HTML 檔案
- 在sever build time時匯出共用 products/[id].js page的同時也會匯出 `getStaticPaths()` 函式
- `getStaticPaths`是一個 **`async`** 函式回傳值包含兩個 key,分別是 **paths** 與 **fallback**
- ==`getStaticPaths`把所有 dynamic routes 的 key 透過 paths 傳入 `getStaticProps`==
- ==`getStaticProps`透過 paths 取得 params 的參數來取得該頁面的資料內容==
- [Demo post page at localhost](https://github.com/vercel/next.js/tree/canary/examples/with-static-export)
## SSG - Key Considerations
正如討論的,SSG有好的performance(縮短TTFB)和SEO(回應給client-side已經build好的html),在評估 SSG 對特定應用的適用性時,需要考慮以下因素:
1. **A large number of HTML files**: 需要為用戶可能訪問的每個可能的路徑生成單獨的 HTML 文件,例如:build每篇post貼文儲存在sever端,編輯任意一個post就要重新rebuild一大包靜態資料夾,維護大量 HTML 文件可能具有挑戰性
2. **Hosting Dependency**
- 託管在平台: 用於存儲和提供 HTML 文件的託管平台效能要不錯,可使 SSG 站點超快並快速響應
- 託管在多個CDN: 如果把調整好的SSG網站託管在多個CDN上可以有最高的效能
4. **Dynamic Content**:
- 每次內容更改時,都需要build和re-deployed SSG 站點
- 如果網站在任何內容更改後尚未re-build+re-deployed,則顯示的內容可能是舊的
- 以上兩點使得 SSG 不適合高度動態的內容
## Reference
- [Next.js dynamic Routes](https://nextjs.org/docs/routing/dynamic-routes)
- [ref: Next.js getStaticProps](https://nextjs.org/docs/basic-features/data-fetching/get-static-props)
- [Next.js getStaticPaths](https://nextjs.org/docs/basic-features/data-fetching/get-static-paths)
- [Demo dynamic Routes](https://codesandbox.io/s/ecstatic-frog-6ecuck?file=/pages/index.js)
- [Vercel](https://vercel.com/blog/nextjs-server-side-rendering-vs-static-generation#individual-product-page-static-generation-with-data)