查看原文
其他

Bun + React 实现服务器端渲染(SSR)

FEDLAB FED实验室 2024-02-12

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的诸多特性,内容将涵盖以下几个方面:

  1. Bun 的安装
  2. 创建第一个 Bun 项目
  3. 创建第一个 Bun 服务器
  4. 使用 Bun 和 React 实现服务端渲染
  5. 预取数据并在服务端渲染

1.Bun 安装

可以通过以下脚本安装 Bun

# Install Bun
curl -fsSL https://bun.sh/install | bash

2.Bun 项目初始化

可以使用 bun init 命令来初始化项目,脚手架会创建一个 bun.lockb 的锁文件,它取代了 yarnnpmpnpm。同时创建了 入口文件 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-nodetsx 就可以直接运行 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 文件,真是太方便了✌🏻!!!

如果您觉得这篇文章对有所帮助,欢迎关注我,您的支持是我持续分享和写作的动力。有问题欢迎留言讨论。

下面是「FED 实验室」的微信公众号名片,欢迎关注:
继续滑动看下一个

Bun + React 实现服务器端渲染(SSR)

FEDLAB FED实验室
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存