Bun + React 实现服务器端渲染(SSR)
Bun 1.0 版本发布后,写了篇文章“Bun 为什么火了”,本篇将使用 Bun 和 React 来实现一个服务端渲染项目。
如果你对Bun 还不了解,可以简短做下说明:Bun 是一个一体化的 JavaScript 运行时和工具包,设计速度极快。它配备了Bundler、Test Runner、原生 TypeScript 和 JSX 支持,甚至还有一个兼容 Node.js 的包管理器。Bun 的核心是一个快速的 JavaScript 运行时,旨在取代 Node.js。它是用 Zig 语言编写的,并在底层由 JavaScriptCore 提供支持,大大减少了启动时间和内存使用。
通过本文,我将带你探索 Bun v1.0的诸多特性,内容将涵盖以下几个方面:
Bun 的安装 创建第一个 Bun 项目 创建第一个 Bun 服务器 使用 Bun 和 React 实现服务端渲染 预取数据并在服务端渲染
1.Bun 安装
可以通过以下脚本安装 Bun
# Install Bun
curl -fsSL https://bun.sh/install | bash
2.Bun 项目初始化
可以使用 bun init
命令来初始化项目,脚手架会创建一个 bun.lockb
的锁文件,它取代了 yarn
、npm
、pnpm
。同时创建了 入口文件 index.ts
和 Typescript 配置文件 tsconfig.json
,这也意味着 Typescript 已经被内置了,我们无需求额外去做设置。package.json
文件中的 "type": "module"
标识直接使用的是 ES6 模块化规范。
mkdir bun-react-proj && cd bun-react-proj && bun init
# progress
bun init helps you get started with a minimal project and tries to guess sensible defaults. Press ^C anytime to quit
package name (bun-react-proj):
entry point (index.ts):
Done! A package.json file was saved in the current directory.
+ index.ts
+ .gitignore
+ tsconfig.json (for editor auto-complete)
+ README.md
To get started, run:
bun run index.ts
生成的目录结构如下:
$ tree -L 1
.
├── README.md
├── bun.lockb
├── index.ts
├── node_modules
├── package.json
└── tsconfig.json
3.创建第一个 Bun 服务器
创建一个 Bun 服务器非常简单。只需几行代码就能启动并运行。
const server = Bun.serve({
port: 3000,
fetch(req) {
return new Response(`欢迎关注「FED 实验室」微信公众号!`);
},
});
console.log(`Listening on http://localhost:${server.port} ...`);
简单对上面代码做个解释,通过 Bun.serve()
创建了一个服务器,监听端口为 3000,fetch(req) {}
定义一个处理所有 HTTP 请求的函数。当收到请求时,它会返回一个新的 HTTP 响应,响应文本为 "欢迎关注「FED 实验室」微信公众号!"。
运行服务:
$ bun index.ts
Listening on http://localhost:3000 ...
从 bun index.ts
可以看到 Bun 的好处,我们不在需要 ts-node
、tsx
就可以直接运行 Typescript 文件。
4.使用 Bun 和 React 实现服务端渲染
要实现服务端渲染(SSR),我们需要安装 React 和 index.ts
重命名为 index.tsx
。
4.1.安装软件包
# 和 yarn 命令类似,我们使用 bun add 命令来添加软件包
bun add react react-dom
## install devDependences
bun add -d @types/react-dom
4.2.重命名文件
接下来,我们要将服务器入口文件 index.ts
转换为 index.tsx
,这样我们就可以直接返回 JSX 元素。
mv index.ts index.tsx
4.3.编写index.tsx
在这个文件中我们将使用 renderToReadableStream
来渲染 React 组件。同时,将该数据流封装到一个 Response 对象中,确保内容类型设置为 "text/html"。
import { renderToReadableStream } from "react-dom/server";
import User from "./components/User";
const server = Bun.serve({
port: 3000,
async fetch(request) {
const stream = await renderToReadableStream(<User />);
return new Response(stream, {
headers: {
"Content-Type": "text/html;charset=UTF-8"
},
});
},
});
console.log(`Listening on http://localhost:${server.port} ...`);
4.4.创建 React 组件
创建一个简单的 React 组件。该组件将在服务器端渲染(SSR),并直接流回客户端。
import React from "react";
type UserProps = {
name?: string;
};
function User() {
return <div>FED 实验室,前端开发实验室!</div>;
}
export default User;
效果如下:
4.5.增加服务端预取数据并渲染
通过 fetch 方法来预取数据,传递给 UserList
组件,并交由服务端执行渲染。
import { renderToReadableStream } from "react-dom/server";
import UserList from "./components/UserList";
const server = Bun.serve({
port: 3000,
async fetch(request) {
const url = new URL(request.url);
const pathname = url.pathname;
if(pathname === '/userlist') {
const response = await fetch("https://pokeapi.co/api/v2/pokemon");
const {results} = await response.json();
const stream = await renderToReadableStream(<UserList results={results} />);
return new Response(stream, {
headers: {
"Content-Type": "text/html;charset=UTF-8"
},
});
}
return new Response("Not Found", { status: 404 });
},
});
console.log(`Listening on http://localhost:${server.port} ...`);
UserList
组件开发:
import React from "react";
function UserList({results = []}) {
return <ul>
{
results.map(item => {
return <li><a href={item.url}>{item.name}</a></li>
})
}
</ul>
}
export default UserList;
效果如下:
5.总结
我们安装并初始化了一个 Bun 项目,创建了 Bun 服务器,利用服务端渲染技术对 React 组件进行了流式渲染处理。从整个开发体验上看 Bun 开发比 Node.js 开发要快速很多,对开发者很友好,很多套件可以直接使用,默认支持运行 .tsx
文件,真是太方便了✌🏻!!!。
如果您觉得这篇文章对有所帮助,欢迎关注我,您的支持是我持续分享和写作的动力。有问题欢迎留言讨论。