React SSG - 也写个 Demo 吧

这篇具有很好参考价值的文章主要介绍了React SSG - 也写个 Demo 吧。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

上次写了一个 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 文件即可。

通过该脚本可以通过以下的博文:

生成以下 HTML

静态文件服务

HTML 生成后,只需要启动静态文件服务器,将静态 HTML 丢过去即可,可以使用 nginx 或者 serve 包。

更多细节

上面只是一个最简单的例子,要实现一个完整的系统还需要考虑以下几个方面:

  • 样式支持 - 在渲染静态文件时添加上 link 引入即可。
  • hydrate - 本文并没有实现 hydrate,其实实现逻辑差不多,在静态文件渲染时嵌入脚本,然后脚本在客户端进行 hydrate,不过一般的 SSG 场景下动态的内容不多,所以如果没有交互可以忽略。

总结

React 中的 SSG 本质也是通过 renderToString 来实现,但是时机与 SSR 不同,是在构建时进行。

最后

本文的 demo 代码放置在 React SSG Demo 中,可自行取阅。文章来源地址https://www.toymoban.com/news/detail-498580.html

到了这里,关于React SSG - 也写个 Demo 吧的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 实现一个 SEO 友好的响应式多语言官网 (Vite-SSG + Vuetify3) 我的踩坑之旅

    在 2023 年的年底,我终于有时间下定决心把我的 UtilMeta 项目官网 进行翻新,主要的原因是之前的官网是用 Vue2 实现的一个 SPA 应用,对搜索引擎 SEO 很不友好,这对于介绍项目的官网来说是一个硬伤 所以在调研一圈后,我准备用 Vite-SSG + Vue3 + Vuetify3 把官网重新来过,前后花

    2024年03月11日
    浏览(51)
  • 写了一个 SRE 调试工具,类似一个小木马

    远程操作机器有时会比较麻烦,我写了一个工具,主要功能:1.远程执行命令 2.上传下载文件。是一个 Web Server,通过 HTTP 请求来操作机器,类似一个小木马。当然,因为是一个 Web Server,所以也提供了打印 HTTP 请求的能力,方便调试 Webhook 场景。下面给大家演示一下。 工具代

    2024年04月22日
    浏览(57)
  • 我用爬虫写了一个小程序

    一天我在微信小程序上面发现有很多表情包或者壁纸一类的小程序,我就在想我可不可以做一个类似的小程序呢? 想法 最开始的时候想法比较简单,就是写一个接口然后上传表情包或者壁纸(到处是下载,哈哈哈)。 然后根据分类以及标题进行搜索已达到其效果;但是让我没

    2024年02月07日
    浏览(47)
  • vue+elementui写了一个图书管理系统

    用vue+elementui写了一个图书管理系统 转载自公号:java大师 目前是指一个纯前端的展示,后端还在开发中,前端接口是通过json-server模拟的 用到的技术栈 1、vue.js 2、elementui 3、json-server 4、axios 5、vue-router 动态路由 目录结构 1、components文件夹是封装的通用的Mytable和Myform及Nav等,

    2024年02月04日
    浏览(90)
  • 用JavaFX写了一个简易的管理系统

    自学一下Java FX ,用Java代码写一个简易的客户端。 本文项目是Maven项目,使用了Java17,以及mysql。 代码仓库:https://gitee.com/fengsoshuai/java-fx-management-system-demo/tree/dev-with-db/ 代码仓库(前后端分离版本) : https://gitee.com/fengsoshuai/javafx-management-front-back-demo 建议代码可以直接看前后

    2024年01月25日
    浏览(38)
  • 用Python写了一个「拥抱梅西」的小游戏

    大家好,欢迎来到 Crossin的编程教室 !  最近有个小伙儿因为在比赛中冲进场地拥抱梅西而出名了。  这种行为当然不可取,他也为此付出了代价。但要说我没有一丁点羡慕和佩服那是不可能的。 于是,我也尬蹭一下这个热点,用Python写了一个「拥抱梅西」的小游戏。 游戏

    2024年02月09日
    浏览(41)
  • 我写了一个用来刷题的微信小程序

    目录 土著刷题是一个什么工具? 为什么要做土著刷题这样一个产品? 当前版本的规划 版本效果 土著刷题微信小程序,一款免费的刷题小程序,提供多种刷题模式,可以分享题库给小伙伴一起刷,针对特定题库的用户群体。 对于为什么要开发这个刷题小程序,这可以说是一

    2024年02月10日
    浏览(52)
  • 手动自己写了一个波场(Tron)本地网页版钱包

    最近由于项目需要,需要给每个用户分配一个充币地址,考虑到钱包安全性和方便管理,于是自己动手写了一个本地网页版的钱包,附上源代码跟大家交流下。 Github 源码地址 钱包和项目是分离的,项目通过鉴权访问钱包的接口,主要实现了以下功能: 1、可以导入助记词、

    2023年04月15日
    浏览(53)
  • 用auto.js写了一个抖音点赞、关注的脚本

    最近一直在找工作,有天就遇到一个要求使用auto.js写一些自动化控件的公司(我严重怀疑它其实就想白嫖。。。),于是就有了这个小demo... 因为没用过抖音,也不懂auto.js,所以看了一些教学视频,所以写成这个样子了。。。(有点烂,就单纯记录一下自己的学习过程,au

    2024年02月13日
    浏览(47)
  • 最前端|注意看!我用代码写了一个会动的3D地球

    目录 一、文章背景 二、实现方式 (一)方案 (二)实现细则 三、总结 在我们负责的某个项目中有一个需求,其展馆的可视化大屏首屏需要 3D 地球作为载体,来展示各国贸易额的信息,因此催生了 3D 地球的需求。需求的侧重点更多在于美观,动态方面,对于数据展示层面

    2024年02月09日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包