React SSG实现Demo详解
什么是 SSG
上次写了一个 SSR 的 DEMO,今天写个小 Demo 来从头实现一下 react 的 SSG,来理解下 SSG 是如何实现的。
SSG 即 Static Site Generation 静态站点生成,是指将在构建时就提前生成静态 HTML 页面,速度很快,一般用于以下场景:
SEO(搜索引擎优化):由于部分搜索引擎对CSR内容支持不佳,所以SSG可以提升网站在搜索引擎结果中的排名。- 静态站点:比如博客、
CMS系统输出站点等,由于内容以静态内容居多,都可以使用SSG。
如何实现
简单的 SSG 和 SSR 实现原理差不多,只是时机不同: 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 中,可自行取阅。
以上就是React SSG实现Demo详解的详细内容,更多关于React SSG实现的资料请关注脚本之家其它相关文章!
相关文章
React Hook useState useEffect componentD
这篇文章主要介绍了React Hook useState useEffect componentDidMount componentDidUpdate componentWillUnmount问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教2024-03-03


最新评论