React SSG - 也寫個 Demo 吧

来源:https://www.cnblogs.com/zxbing0066/archive/2023/06/24/17501788.html
-Advertisement-
Play Games

上次寫了一個 `SSR` 的 `DEMO`,今天寫個小 `Demo` 來從頭實現一下 `react` 的 `SSG`,來理解下 `SSG` 是如何實現的。 ## 什麼是 SSG `SSG` 即 `Static Site Generation` 靜態站點生成,是指將在構建時就提前生成靜態 `HTML` ...


上次寫了一個 SSRDEMO,今天寫個小 Demo 來從頭實現一下 reactSSG,來理解下 SSG 是如何實現的。

什麼是 SSG

SSGStatic Site Generation 靜態站點生成,是指將在構建時就提前生成靜態 HTML 頁面,速度很快,一般用於以下場景:

  1. SEO (搜索引擎優化):由於部分搜索引擎對 CSR 內容支持不佳,所以 SSG 可以提升網站在搜索引擎結果中的排名。
  2. 靜態站點:比如博客、CMS 系統輸出站點等,由於內容以靜態內容居多,都可以使用 SSG

如何實現

簡單的 SSGSSR 實現原理差不多,只是時機不同: SSR 渲染 HTML 的過程在服務端,而 SSG 則在構建時。渲染同樣是通過在 Node 端導入要渲染的組件,然後調用 react-dom/server 包中提供的 renderToString 方法將該組件的渲染內容輸出為 HTML 保存。

系統設計

下麵使用 SSG 實現一個簡單的靜態博客系統:

  • 每篇博文都使用一個 JSON 文件來記錄其中的信息(為了簡化沒有使用 markdown,可以理解為 markdown 博文信息已提前轉換為 JSON 文件)
  • 構建時會將博文編譯為靜態 HTML 文件,並生成一個博文列表的 HTML 文件
  • 通過靜態文件伺服器啟動即可展示博文

組件設計

可以看出我們只需要兩個組件:

  • 一個 Post 組件,用於接收博文信息展示博文
  • 一個 List 組件,用於接受博文列表展示博文清單

簡單的實現一下:

import React from 'react';

export default ({
    data
}: {
    data: {
        title: string;
        content: { title: string; content: string }[];
    };
}) => {
    return (
        <div>
            <h1>{data.title}</h1>
            <div>
                {data.content.map(({ title, content }) => (
                    <article key={title}>
                        <h2>{title}</h2>
                        <p>{content}</p>
                    </article>
                ))}
            </div>
        </div>
    );
};
import React from 'react';

export default ({ list }: { list: { title: string; key: string }[] }) => {
    return (
        <div>
            <ul>
                {list.map(({ title, key }) => (
                    <li key={title}>
                        <a href={`/posts/${key}.html`}>{title}</a>
                    </li>
                ))}
            </ul>
        </div>
    );
};

構建腳本

然後再來實現下構建腳本,首先構建腳本一樣需要支持 JSX 的解析,然後構建腳本讀取博文數據文件夾下的所有文件,將其依次解析為靜態 HTML,並且再生成一份列表的 HTML

代碼也非常簡單:

import fs from 'fs';
import { renderToString } from 'react-dom/server';
import React from 'react';
import Post from './ui/Post';
import List from './ui/List';

// get all the files in posts
const posts = fs.readdirSync('posts');

// make sure the dir exists
if (!fs.existsSync('dist')) {
    fs.mkdirSync('dist');
}
if (!fs.existsSync('dist/posts')) {
    fs.mkdirSync('dist/posts');
}

posts.map(post => {
    const postInfo = require('./posts/' + post);
    const fileName = `dist/posts/${post.replace('.json', '.html')}`;
    // make sure file exists
    fs.writeFileSync(fileName, `<div id="root">${renderToString(<Post data={postInfo} />)}</div>`);
});

fs.writeFileSync(
    'dist/index.html',
    `<div id="root">${renderToString(
        <List list={posts.map(post => ({ ...require('./posts/' + post), key: post.replace('.json', '') }))} />
    )}</div>`
);

首先通過 readdirSync 讀取博文信息目錄,這裡只處理了單層,複雜點的需要遞歸處理下多層目錄結構。然後將每篇博文通過 renderToString 渲染為靜態 HTML 並寫入文件。最後再輸出列表對應的 HTML 文件即可。

通過該腳本可以通過以下的博文:

picture 1

生成以下 HTML

picture 2

靜態文件服務

HTML 生成後,只需要啟動靜態文件伺服器,將靜態 HTML 丟過去即可,可以使用 nginx 或者 serve 包。

picture 3

picture 4

更多細節

上面只是一個最簡單的例子,要實現一個完整的系統還需要考慮以下幾個方面:

  • 樣式支持 - 在渲染靜態文件時添加上 link 引入即可。
  • hydrate - 本文並沒有實現 hydrate,其實實現邏輯差不多,在靜態文件渲染時嵌入腳本,然後腳本在客戶端進行 hydrate,不過一般的 SSG 場景下動態的內容不多,所以如果沒有交互可以忽略。

總結

React 中的 SSG 本質也是通過 renderToString 來實現,但是時機與 SSR 不同,是在構建時進行。

最後

本文的 demo 代碼放置在 React SSG Demo 中,可自行取閱。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 經過前幾篇文章的講解,初步瞭解ASP.NET Core MVC項目創建,啟動運行,以及命名約定,創建控制器,視圖,模型,接收參數,傳遞數據ViewData,ViewBag,路由,頁面佈局,wwwroot和客戶端庫,Razor語法,EnityFrameworkCore與資料庫,HttpContext,... ...
  • # 記錄伺服器和docker時區修改 ## 前言 我的博客是部署在docker裡面的,然後我發現評論和留言的時間和北京時間是有差別的,相差8個小時,然後發現是因為容器中的時區設置與伺服器是不一致的,所以需要設置一下。 ## 更改liunx伺服器時區 1. 查看當前時區設置 使用`date`命令查看當 ...
  • 大家好,我是沙漠盡頭的狼。 Dotnet9網站回歸Blazor重構,訪問速度確實飛快,同時用上Blazor的交互能力,站長也同步添加了幾個線上工具,這篇文章分享下Blazor的重構過程,希望對大家網站開發時做技術選型有個參考。 ![](https://img1.dotnet9.com/2023/06 ...
  • 當我們輸入ls 再按下TAB時, 會自動列出當前路徑下所有的文件; 當我們輸入ls a 再按下TAB時, 會自動列出當前路徑下所有以a開頭的文件; 若只有一個以a開頭的文件, 將會自動補全; 這是怎麼做到的? 本文將帶你一探究竟 ...
  • 端午放假,本想註冊個美團眾包騎自行車送外賣體驗一下生活,奈何這幾天北京熱的要死,只能作罷,還是苟在屋裡空調續命吧。 無事乾的時候,想著給我花盆監控升個級,換個電容的土壤檢測(`之前的腐蝕了gg了`)但是電容的是3v的,esp8266只能檢測1v的,所以買了一個新的esp32-cam,正好帶個攝像頭,... ...
  • # MVCC機制遺留的問題 **為什麼在可重覆讀級別下,幻讀沒有產生?** 回想一下在事務隔離級別那篇文章中,可串列化是通過什麼保證的? 對操作的每一行記錄加讀鎖、寫鎖和範圍鎖;任何其他事務都必須等待持有鎖的事務釋放鎖之後才能進行操作; 而可重覆讀級別相比之下唯一少的就是範圍鎖,所以無論你是否瞭解過 ...
  • (一)好好的系統,為什麼要分庫分表? 咱們先介紹下在分庫分表架構實施過程中,會接觸到的一些通用概念,瞭解這些概念能夠幫助理解市面上其他的分庫分表工具,儘管它們的實現方法可能存在差異,但整體思路基本一致。因此,在開始實際操作之前,我們有必要先掌握這些通用概念,以便更好地理解和應用分庫分表技術。 我們結 ...
  • ### 背景 在項目中有集成低代碼平臺的想法,經過多方對比最後選擇了 amis,主要是需要通過 amis 進行頁面配置,導出 json 供移動端和 PC 端進行渲染,所以接下來講一下近兩周研究 amis 的新的以及一些簡單經驗,供大家參考. ### 什麼是 amis amis 是一個低代碼前端框架, ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...