###### 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/) ![](https://i.imgur.com/zk8o6d3.png) ## 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)