詳解React?ISR如何實現(xiàn)Demo
什么是 ISR
之前寫了兩個 demo
講解了如何實現(xiàn) SSR
和 SSG
,今天再寫個 demo
說在 ISR
如何實現(xiàn)。
ISR
即 Incremental Static Regeneration
增量靜態(tài)再生,是指在 SSG
的前提下,可以在收到請求時判定頁面是否需要刷新,如果需要則重新構(gòu)建該頁面,這樣既擁有了靜態(tài)頁面的優(yōu)勢又可以避免頁面長時間未更新導(dǎo)致信息過時。且由于在頁面維度驗證,所以每次可以只構(gòu)建特定的頁面。
ISR
一般適用于符合 SSG
場景,但是卻對頁面的時限性有一定要求時。
如何實現(xiàn)
簡單的 ISR
實現(xiàn)也很簡單,只需要在收到頁面請求時按照更新策略判斷是否需要需要重新生成頁面,如果需要觸發(fā)頁面的構(gòu)建更新。需要注意一般情況下生成頁面不會影響頁面的響應(yīng),而是后臺去做構(gòu)建。
現(xiàn)在就基于之前寫的 SSG demo
,做一下改造讓其支持 ISR
。
修改構(gòu)建腳本
由于 ISR
構(gòu)建會同時在構(gòu)建腳本和服務(wù)器中觸發(fā),所以需要對之前的代碼做一些小小的改動。
首先抽離出一個通用的構(gòu)建函數(shù)(由于服務(wù)器會使用到盡量避免同步代碼):
import fs from 'fs/promises'; import { renderToString } from 'react-dom/server'; import React from 'react'; import Post from './ui/Post'; import List from './ui/List'; async function build(type: 'list'): Promise<void>; async function build(type: 'post', name: string): Promise<void>; async function build(type: 'list' | 'post', name?: string) { if (type === 'list') { const posts = await fs.readdir('posts'); await fs.writeFile( 'dist/index.html', `<div id="root">${renderToString( <List list={posts.map(post => { delete require.cache['posts/' + post]; return { ...require('./posts/' + post), key: post.replace('.json', '') }; })} /> )}</div>` ); } else { delete require.cache['posts/' + name]; const postInfo = require('./posts/' + name); const fileName = `dist/posts/${name}.html`; await fs.writeFile(fileName, `<div id="root">${renderToString(<Post data={postInfo} />)}</div>`); } } export default build;
這樣就可以通過 build
函數(shù)來構(gòu)建指定的 post
或者 list
頁面。
然后再將原先的構(gòu)建腳本做一下簡單的修改:
import fs from 'fs'; import build from './build-util'; // make sure the dir exists if (!fs.existsSync('dist')) { fs.mkdirSync('dist'); } if (!fs.existsSync('dist/posts')) { fs.mkdirSync('dist/posts'); } // get all the files in posts const posts = fs.readdirSync('posts'); (async () => { for await (const post of posts) { await build('post', post.replace('.json', '')); } await build('list'); })();
服務(wù)器
由于 ISR
需要在請求時做是否構(gòu)建的判定,所以原先的靜態(tài)服務(wù)器方案無法繼續(xù)使用,我們換成 express
來實現(xiàn):
import express from 'express'; import path from 'path'; import fs from 'fs'; import build from '../build-util'; const app = express(); const expiresTime = 1000 * 60 * 10; app.use(function (req, res, next) { setTimeout(() => { const filename = req.path.indexOf('.html') >= 0 ? req.path : req.path + 'index.html'; // get the file's create timestamps fs.stat(path.join('./dist', filename), function (err, stats) { if (err) { console.error(err); return; } if (Date.now() - +stats.mtime > expiresTime) { console.log(filename, 'files expired, rebuilding...'); if (filename === '/index.html') { build('list'); } else { build('post', path.basename(filename).replace('.html', '')); } } }); }); next(); }); app.use(express.static('dist')); app.listen(4000, () => { console.log('Listening on port 4000'); });
我們增加一個 express
的中間件,讓其來判定文件是否過期,這里以十分鐘為例,實際場景可按需定義過期判定。這里過期后就會調(diào)用 build
文件來重新構(gòu)建該文件。要注意此處先返回再構(gòu)建,所以用戶不會等待構(gòu)建,并且此次訪問依舊是舊的內(nèi)容,構(gòu)建完成后訪問的才是新的內(nèi)容。
更多細(xì)節(jié)
- 注意給構(gòu)建任務(wù)加鎖,避免一個頁面過期后多個請求同時觸發(fā)多個同樣的構(gòu)建任務(wù)
- 給構(gòu)建任務(wù)加隊列,避免請求過多時同時出現(xiàn)過多的后臺構(gòu)建任務(wù)導(dǎo)致服務(wù)器資源問題
- 可以為每個文件制定特定的過期判定條件,比如
post
源文件的修改時間等等
總結(jié)
ISR
對比 SSG
可以有效的控制頁面的時效性,但也要付出額外的代價:
- 需要額外的開發(fā)成本
- 需要額外的服務(wù)器資源投入
- 無法使用一般的靜態(tài)文件服務(wù)器
沒有最佳,只有最適合,所以實際場景下還是按需選用。
本文的 demo
代碼放置在 React ISR Demo 中,可自行取閱。
以上就是詳解React ISR如何實現(xiàn) Demo的詳細(xì)內(nèi)容,更多關(guān)于React ISR實現(xiàn)的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
React Native模塊之Permissions權(quán)限申請的實例相機(jī)
這篇文章主要介紹了React Native模塊之Permissions權(quán)限申請的實例相機(jī)的相關(guān)資料,希望通過本文能幫助到大家,需要的朋友可以參考下2017-09-09React使用有限狀態(tài)機(jī)的實現(xiàn)示例
本文主要介紹了React使用有限狀態(tài)機(jī)的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05React Native使用fetch實現(xiàn)圖片上傳的示例代碼
本篇文章主要介紹了React Native使用fetch實現(xiàn)圖片上傳的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-03-03高性能React開發(fā)React Server Components詳解
ReactServerComponents通過服務(wù)器端渲染、自動代碼分割等技術(shù),實現(xiàn)了高性能的React開發(fā),它解決了客戶端數(shù)據(jù)請求鏈?zhǔn)窖舆t、敏感數(shù)據(jù)暴露風(fēng)險等問題,提供了更好的用戶體驗和安全性,本文介紹高性能React開發(fā)React Server Components詳解,感興趣的朋友一起看看吧2025-03-03React?UI組件庫之快速實現(xiàn)antd的按需引入和自定義主題
react入門學(xué)習(xí)告一段路,下面這篇文章主要給大家介紹了關(guān)于React?UI組件庫之快速實現(xiàn)antd的按需引入和自定義主題的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-07-07使用react-router4.0實現(xiàn)重定向和404功能的方法
本篇文章主要介紹了使用react-router4.0實現(xiàn)重定向和404功能的方法,具有一定的參考價值,有興趣的可以了解一下2017-08-08next-redux-wrapper使用細(xì)節(jié)及源碼分析
這篇文章主要為大家介紹了next-redux-wrapper使用細(xì)節(jié)及源碼分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02