成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

從 Next.js 看企業級框架的 SSR 支持

開發 架構
面向生產使用的 React 框架(廢話)。提供了好些開箱即用的特性,支持靜態渲染/服務端渲染混用、支持 TypeScript、支持打包優化、支持按路由預加載等等。

[[355666]]

本文轉載自微信公眾號「前端向后」,作者黯羽輕揚  。轉載本文請聯系前端向后公眾號。 

 一.Next.js 簡介

The React Framework for Production

面向生產使用的 React 框架(廢話)。提供了好些開箱即用的特性,支持靜態渲染/服務端渲染混用、支持 TypeScript、支持打包優化、支持按路由預加載等等:

Next.js gives you the best developer experience with all the features you need for production: hybrid static & server rendering, TypeScript support, smart bundling, route pre-fetching, and more. No config needed.

其中,完善的靜態渲染/服務端渲染支持讓 Next.js 在 React 生態中獨樹一幟

二.核心特性

如果說 Next.js 只做了一件事,那就是預渲染(Pre-rendering):

By default, Next.js pre-renders every page. This means that Next.js generates HTML for each page in advance, instead of having it all done by client-side JavaScript.

具體的,預渲染分為兩種方式:

  • SSG(Static Site Generation):也叫 Static Generation,在編譯時生成靜態 HTML
  • SSR(Server-Side Rendering):也叫 Server Rendering,用戶請求到來時動態生成 HTML

與 SSR 相比,Next.js 更推崇的是 SSG,因為其性能優勢更大(靜態內容可托管至 CDN,性能提升立竿見影)。因此建議優先考慮 SSG,只在 SSG 無法滿足的情況下(比如一些無法在編譯時靜態生成的個性化內容)才考慮 SSR、CSR

P.S.CSR、SSR 等更多渲染模式,見前端渲染模式的探索

圍繞核心的預渲染功能,延伸出了一系列相關支持,如:

  • 路由(文件規范、API):多頁面的基礎
  • 頁面級預渲染、代碼拆分:順理成章
  • 增量靜態生成:針對大量頁面的編譯時預渲染(即靜態生成)策略
  • 按路由預加載:錦上添花
  • 國際化(結合路由):錦上添花
  • 集成 Serverless 函數:錦上添花
  • 自動 polyfill、自定義head標簽:友情贈送

此外,還提供了一些通用場景支持:

  • 開箱即用(0 配置)
  • TypeScript
  • CSS module、Sass
  • Fast Refresh(可靠的 Hot Reload 支持)
  • 用戶真實數據收集分析(頁面加載性能、體驗評分等)
  • 帶默認優化的Image組件

三.路由支持

Next.js 提供了兩種路由支持,靜態路由與動態路由

靜態路由

靜態路由通過文件規范來約定,pages目錄下的js文件都認為是路由(每個靜態路由對應一個頁面文件),例如:

  1. pages/index.js → / 
  2. pages/blog/index.js → /blog 
  3. pages/blog/first-post.js → /blog/first-post 
  4. pages/dashboard/settings/username.js → /dashboard/settings/username 

動態路由

類似的,動態路由也要在pages目錄下創建文件,只是文件名有些不同尋常:

  1. pages/blog/[slug].js → /blog/:slug (/blog/hello-world) 
  2. pages/[username]/settings.js → /:username/settings (/foo/settings) 
  3. pages/post/[...all].js → /post/* (/post/2020/id/title) 

路徑中變化的參數通過getStaticPaths來填充:

  1. // pages/posts/[id].js 
  2. export async function getStaticPaths() { 
  3.   return { 
  4.     // 必須叫paths,值必須是數組 
  5.     paths: [{ 
  6.       // 每一項必須是這個形式 
  7.       params: { 
  8.         // 必須含有id 
  9.         id: 'ssg-SSR' 
  10.       } 
  11.     },{ 
  12.       params: { 
  13.         id: 'pre-rendering' 
  14.       } 
  15.     }], 
  16.     fallback: false 
  17.   } 

進一步傳遞給getStaticProps按參數獲取數據,并渲染頁面:

  1.  props: { 
  2.       postData 
  3.     } 
  4.   } 
  5.  
  6. // 渲染頁面 
  7. export default function Post({ postData }) { 
  8.   return ( 
  9.     <Layout> 
  10.       <Head> 
  11.         <title>{postData.title}</title> 
  12.       </Head> 
  13.       <article> 
  14.         <h1 className={utilStyles.headingXl}>{postData.title}</h1> 
  15.         <div className={utilStyles.lightText}> 
  16.           <Date dateString={postData.date} /> 
  17.         </div> 
  18.         <div dangerouslySetInnerHTML={{ __html: postData.contentHtml }} /> 
  19.       </article> 
  20.     </Layout> 
  21.   ) 

可以理解為先創建一個工廠 page(例如pages/[路由參數1]/[路由參數2].js),接著getStaticPaths填充路由參數,getStaticProps({ params })根據參數請求不同數據,最后數據進入頁面組件開始預渲染:

四.SSG 支持

最簡單,同時性能也最優的預渲染方式就是靜態生成(SSG),把組件渲染工作完全前移到編譯時:

  1. (編譯時)獲取數據
  2. (編譯時)渲染組件,生成 HTML

將生成的 HTML 靜態資源托管到 Web 服務器或 CDN 即可,兼具 React 工程優勢與 Web 極致性能

那么首先要解決如何獲取數據的問題,Next.js 的做法是將頁面依賴的數據集中管理起來:

  1. // pages/index.js 
  2. export default function Home(props) { ... } 
  3.  
  4. // 獲取靜態數據 
  5. export async function getStaticProps() { 
  6.   // Get external data from the file system, API, DB, etc. 
  7.   const data = ... 
  8.  
  9.   // The value of the `props` key will be 
  10.   //  passed to the `Home` component 
  11.   return { 
  12.     props: ... 
  13.   } 

其中,getStaticProps只在服務端執行(根本不會進入客戶端 bundle),返回的靜態數據會傳遞給頁面組件(上例中的Home)。也就是說,要求通過getStaticProps提前備好頁面所依賴的全部數據,數據 ready 之后組件才開始渲染,并生成 HTML

P.S.注意,只有頁面能通過getStaticProps聲明其數據依賴,普通組件不允許,所以要求將整頁依賴的所有數據都組織到一處

至于渲染生成 HTML 的部分,借助React 提供的 SSR API即可完成

至此,只要是依賴數據有辦法提前獲取到的頁面,理論上都可以編譯生成靜態 HTML,但 2 個問題也隨之而來:

  • 數據可能會發生變化,已經生成的靜態頁面需要更新
  • 數據量可能會多到“永遠”編譯不完

以電商頁面為例,要把海量商品數據全都編譯成靜態頁面,幾乎是不可能的(或許要編譯一個世紀那么長),即便都生成了,商品信息也會時不時地更新,靜態頁面需要重新生成:

If your app has a very large number of static pages that depend on data (think: a very large e-commerce site). You want to pre-render all product pages, but then your builds would take forever.

因此,增量靜態再生成(Incremental Static Regeneration)應運而生

ISR 支持

對于編譯時無法窮舉的海量頁面以及需要更新的場景,Next.js 允許運行時再生成(相當于運行時靜態化):

Incremental Static Regeneration allows you to update existing pages by re-rendering them in the background as traffic comes in.

例如:

  1. export async function getStaticProps() { 
  2.   const res = await fetch('https://.../posts'
  3.   const posts = await res.json() 
  4.  
  5.   return { 
  6.     props: { 
  7.       posts, 
  8.     }, 
  9.     // 設置有效期,開啟ISR 
  10.     revalidate: 1, // In seconds 
  11.   } 

revalidate: 1表示運行時(用戶請求打過來時)嘗試重新生成靜態 HTML,1秒最多重新生成一次

運行時靜態生成需要一些時間(用戶請求等著要 HTML),在此過程中有 3 種選擇:

  • fallback: false:不降級,命中尚未生成靜態頁面的路由直接 404
  • fallback: true:降級,命中尚未生成靜態頁面的路由先返回降級頁面(此時props為空,一般顯示個 loading),靜態生成 HTML 的同時會生成一份 JSON 供降級頁面 CSR 使用,完成之后瀏覽器拿到數據(在客戶端填上props),渲染出完整頁面
  • fallback: 'blocking':不降級,并且要求用戶請求一直等到新頁面靜態生成結束(實際上就是 SSR,渲染過程是阻塞的,只是完成之后會保留結果 HTML)

即結合路由(getStaticPaths)對尚未生成的頁面進行降級,例如:

  1. // pages/index.js 
  2. import { useRouter } from 'next/router' 
  3.  
  4. function Post({ post }) { 
  5.   const router = useRouter() 
  6.  
  7.   // 渲染降級頁面 
  8.   if (router.isFallback) { 
  9.     return <div>Loading...</div> 
  10.   } 
  11.  
  12.   // Render post... 
  13.  
  14. export async function getStaticPaths() { 
  15.   return { 
  16.     paths: [{ params: { id: '1' } }, { params: { id: '2' } }], 
  17.     // (頁面級)降級策略,true表示遇到尚未生成的先給個降級頁,生成完畢后客戶端自動更新過來 
  18.     fallback: true
  19.   } 

P.S.具體見Incremental Static Regeneration、以及The fallback key

然而,并非所有場景都能愉快地在編譯時靜態生成。典型的,如果組件依賴的數據是動態的,顯然無法在編譯時預先取得數據,靜態生成就無從談起了

五.SSR 支持

對于編譯時無法生成靜態頁面的場景,就不得不考慮 SSR 了:

區別于 SSG getStaticProps,Next.js 提供了 SSR 專用的getServerSideProps(context):

  1. // pages/index.js 
  2. export async function getServerSideProps(context) { 
  3.   const res = await fetch(`https://...`) 
  4.   const data = await res.json() 
  5.  
  6.   if (!data) { 
  7.     return { 
  8.       notFound: true
  9.     } 
  10.   } 
  11.  
  12.   return { 
  13.     props: {}, // will be passed to the page component as props 
  14.   } 

同樣用來獲取數據,與getStaticProps最大的區別在于每個請求過來時都執行,所以能夠拿到請求上下文參數(context)

六.總結

圍繞預渲染如何獲取數據的問題,Next.js 探索出了別致的路由支持和精巧的 SSG、SSR 支持。不僅如此,Next.js 還提供了魚和熊掌可以兼得的混用支持,不同渲染模式結合起來到底有多厲害,且看下篇分解

參考資料

  • Pages
  • Data Fetching
  • Create a Next.js App:教程有點意思
  • vercel/next-learn-starter:示例 Demo

原文鏈接:https://mp.weixin.qq.com/s/bS9GHni4ecnz9UFi9RD24Q

 

責任編輯:武曉燕 來源: 前端向后
相關推薦

2021-12-27 08:31:42

Next.js SSRSSG

2025-03-31 00:00:02

Next.jsReact漏洞

2024-03-04 07:33:39

RemixReact框架

2023-01-03 08:00:00

2025-02-03 00:00:35

2009-10-20 09:25:17

Java EE 6最終

2024-11-25 07:39:48

2024-09-20 15:37:02

2024-05-09 09:01:03

2025-01-17 09:29:42

2024-01-25 09:04:25

2009-03-02 09:22:39

OSGiJ2EEEclipse

2024-12-13 08:37:32

2024-04-28 10:56:34

Next.jsWeb應用搜索引擎優化

2024-09-04 10:27:53

2023-11-02 08:01:06

Next.jsReactWeb

2024-02-05 11:55:41

Next.js開發URL

2024-03-05 19:17:37

2009-12-10 17:27:17

企業級路由器

2012-09-17 09:50:24

桌面虛擬化
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产欧美一区二区三区在线看蜜臀 | 欧美亚洲在线视频 | 在线一区二区三区 | 久久久www成人免费精品张筱雨 | 免费国产网站 | 久久三区 | 欧洲亚洲精品久久久久 | 国产福利视频网站 | 精品国产乱码久久久久久丨区2区 | 亚洲一区在线日韩在线深爱 | 国产成人精品网站 | 国产精品美女久久久 | 久久久123| 91国内外精品自在线播放 | 免费一区在线观看 | 欧美操操操 | 亚洲国产一区二区在线 | 精品福利在线视频 | 欧美中文字幕一区二区三区亚洲 | 99久久日韩精品免费热麻豆美女 | 黄色片在线 | 免费在线观看成人 | 九九亚洲| 91久久精品一区二区二区 | 欧美成人精品一区二区男人看 | 午夜影院在线观看视频 | 久久久爽爽爽美女图片 | 亚洲第一福利网 | 国产一区不卡 | 北条麻妃99精品青青久久主播 | 欧美中国少妇xxx性高请视频 | 亚洲人人| 黄色免费观看网站 | 男人天堂网址 | 国产精品一区二区三区在线播放 | 999久久久 | 国产高清在线观看 | 久草精品视频 | 在线视频一区二区三区 | 国产成人综合网 | 久久久久黑人 |