Parcel v2.14.0
Parcel v2.14.0 引入了 React Server Components 的测试版支持,可以集成到现有的客户端渲染应用中,在请求时在服务器端渲染,或在构建时静态渲染为 HTML。此外,它还添加了一流的 MDX 支持、用于搭建新 Parcel 应用的 CLI,以及新的 React 错误覆盖层。它还通过原生 HTML 导入映射优化了浏览器缓存。这是一个重大版本,让我们深入了解!
React Server Components
#Parcel v2.14.0 引入了 React Server Components 的测试版支持,这是一种可以提前渲染、在服务器端或构建时渲染的新型组件。服务器组件在一个统一的组件树中无缝集成客户端和服务器代码,通过预渲染非交互式组件帮助减少客户端捆绑包大小。
与其他 RSC 实现不同,Parcel 不是一个完整的框架。相反,它提供了从头开始构建自己的应用程序或框架所需的工具,工作量大大减少。这使您可以自由尝试新模式,或在不进行重大重写的情况下将服务器组件集成到现有应用中。
得益于其现有的多环境支持,Parcel 在一个统一的模块图中集成服务器和客户端代码,只需一个命令就能构建整个应用,并支持跨环境的代码拆分等功能。这包括支持 "use client" 和 "use server" 指令来声明环境边界,动态导入以根据数据按需加载组件等。
查看我们的 rsc-examples 仓库,了解使用 React Server Components 和 Parcel 构建的完整示例应用,并查看文档以深入了解。
集成到客户端渲染应用
#Parcel 使得在现有的客户端渲染 React 应用中逐步采用服务器组件成为可能。例如,对于新功能,您可以渲染服务器组件,而不是从 API 服务器返回 JSON。这可以通过仅发送渲染所需的组件来帮助减少客户端捆绑包大小,并完全从客户端捆绑包中省略重型非交互式组件(例如 Markdown 渲染器)。
import express from "express";
import { renderRSC } from "@parcel/rsc/node";
let app = express();
app.get("/comments", (req, res) => {
renderRSC(<Comments />).pipe(res);
});
async function Comments() {
// 从数据库加载数据...
let comments = await db.getComments();
// 渲染 Markdown 和交互式客户端组件
return comments.map((comment) => (
<article key={comment.id}>
<p>发布者:{comment.user}</p>
<Markdown content={comment.body} />
<LikeButton />
</article>
));
}
在客户端,服务器组件可以使用 React Suspense 加载。
import { fetchRSC } from "@parcel/rsc/client";
function App() {
return (
<Suspense fallback={<>加载评论中...</>}>
<Comments />
</Suspense>
);
}
let request;
function Comments() {
request ??= fetchRSC("http://localhost:3000/comments");
return request;
}
服务器组件可以集成到现有的客户端渲染 SPA 中,而无需重写整个应用。只需添加一个指向服务器代码的新目标,与现有的 SPA 并排。Parcel 将一起构建这两个目标,并在它们之间共享公共依赖项。查看文档以了解更多。
服务器渲染
#在客户端渲染的 React 应用中,Parcel 构建的入口点通常是一个 HTML 文件。构建的输出可能会上传到静态文件服务器或 CDN。在 HTML 和 JavaScript 加载后,您可能会从 API 服务器请求数据并使用客户端组件渲染。在渲染数据的过程中,您可能会动态加载其他组件或数据。这是一个称为 网络瀑布 的性能问题。
React 服务器组件可以通过在初始请求中渲染为 HTML 来优化网络瀑布。这避免了额外的 API 请求来加载数据,并允许渲染数据所需的组件并行加载,而不是串行加载。
使用服务器渲染时,Parcel 构建的入口点是服务器的源代码,而不是静态 HTML 文件。Parcel v2.14.0 包括对在开发模式下运行 Node 服务器的开箱即用支持。运行 parcel src/server.js
将构建您的服务器,并在您进行更改时使用内置的热重载,就像客户端代码一样。

查看文档以获取更多信息。
静态渲染
#Parcel 还支持在构建时将 React 服务器组件预渲染为完全静态的 HTML。例如,营销页面或博客文章通常是静态的,不包含针对用户个性化的动态数据。预渲染允许这些页面直接从 CDN 提供服务,而不需要服务器。
Parcel 现在包括一个开箱即用的静态站点生成器,由 React 服务器组件提供支持。入口组件在构建时渲染为静态 HTML,交互式客户端组件在浏览器中激活。Parcel 提供所有页面的列表以及当前页面的元数据,使每个入口组件能够渲染站点导航。使用 MDX,它还为每个页面生成目录,并提供静态导出作为元数据。请参见下文了解有关 MDX 的更多信息。
export default function Page({ pages, currentPage }) {
return (
<html>
<head>
<title>{currentPage.name}</title>
</head>
<body>
<nav>
{pages.map((page) => (
<a href={page.url}>{page.name}</a>
))}
</nav>
</body>
</html>
);
}
通过创建多个目标,您还可以在同一个应用中混合静态和动态页面。例如,营销页面可以静态渲染并部署到 CDN,而您的产品仪表板可以在服务器端渲染。
请参见文档以获取更多详细信息。
一流的 MDX 支持
#Parcel 现在开箱即用地包括一流的 MDX 支持。它使用 mdx-rs 以性能为目标用 Rust 编写,并深度集成到 Parcel 中。Markdown 和 JSX 语法中的依赖项(如图像和链接)由 Parcel 检测和处理,就像 HTML 一样。可以提供自定义代码块组件,轻松实现语法高亮和内联渲染示例,非常适合文档站点。MDX 还可以与 React 服务器组件一起使用,从静态导出中自动提取目录和元数据。
create-parcel CLI
#为了更快地设置新项目,Parcel 现在包括一个 create-parcel
CLI,可以从模板搭建项目。例如,要创建一个新的 React 服务器组件项目,请运行以下命令:
npm create parcel react-server my-rsc-app
这将创建一个新的 my-rsc-app
目录,初始化 Git 仓库,搭建样板文件,并安装依赖项。目前有 4 个模板:
vanilla
– 一个 Vanilla JS + HTML 应用react-client
– 一个 TypeScript + React 仅客户端应用。请参见 Parcel 的 React 文档。react-server
– 一个 TypeScript + React 服务器组件应用。请参见 Parcel 的 React 服务器组件文档。react-static
– 一个 TypeScript + React 静态站点生成器。请参见 Parcel 的 React 服务器组件文档。
我们将来会为其他框架和设置添加更多模板。
Create React App 迁移
#最近,React 团队弃用了 Create React App用于新应用。鼓励现有应用迁移到另一个框架或构建工具,如 Parcel。为了帮助协助这一过程,我们现在有官方的迁移文档,描述如何从 CRA 迁移到 Parcel。此外,这些步骤通过我们新的 cra-to-parcel 脚本实现了自动化。
npx cra-to-parcel
这将迁移您的依赖项、配置和源代码以使用 Parcel。如果在此过程中遇到任何问题,请在 Github 上提交问题。
新的 React 错误覆盖层
#在 React 应用中,Parcel 包括一个错误覆盖层,以漂亮的 UI 显示运行时错误,其中包含内联代码帧。我们之前使用 Create React App 的 react-error-overlay
包来实现这一点。如上所述,CRA 现已正式弃用,react-error-overlay
已有一段时间未维护。在此版本中,我们分叉并现代化了错误覆盖层,并将其更深入地集成到 Parcel 中。
以前,错误覆盖层使用源映射实现其内联代码帧。当发生错误时,它解析堆栈跟踪,在浏览器中加载相关的源映射,并将堆栈中的每一行映射到带有语法高亮的代码帧。在浏览器中实现这一点相当密集,通常需要多次网络往返和昂贵的源映射解析逻辑。
Parcel 开发服务器现在公开了一个内部端点来完成所有这些工作,而不是在浏览器中完成。这提高了性能,因为源映射逻辑可以在 Rust 中实现,并且没有网络往返。
此外,对于 React 服务器组件,服务器端代码中发生的错误也将出现在同一个错误覆盖层中,并且 React 水合错误将显示带颜色的差异。
原生 HTML 导入映射
#当您的浏览器目标支持时,Parcel 现在使用原生 HTML 导入映射来实现其捆绑清单。
Parcel 的捆绑清单有助于避免级联缓存失效。不是直接通过可能包含变化的内容哈希的 URL 引用动态加载的捆绑包(例如 import("./some-bundle.fh36va.js")
),而是使用稳定的捆绑包 ID(例如 import("af43fx")
)。此 ID 在运行时通过捆绑清单映射到 URL。这样,当引用的捆绑包的内容哈希发生变化时,它不会 级联 到引用它的所有捆绑包。
以前,Parcel 在 JavaScript 中实现了自定义的捆绑清单。这被放置在应用的每个入口 JavaScript 捆绑包中。因此,当动态加载的捆绑包发生变化时,只有该捆绑包和入口捆绑包会在浏览器缓存中失效。
现在,Parcel 在可能的情况下使用原生 HTML 导入映射来实现捆绑清单。Parcel 将包含此捆绑清单的 <script type="importmap">
注入 HTML 页面。这消除了 Parcel 的自定义运行时,并提高了缓存命中率。现在,不是在任何捆绑包发生变化时使所有入口 JavaScript 捆绑包失效,而是只使已更改的捆绑包失效。
感谢!
#感谢所有为此版本做出贡献的人!查看完整的更新日志以了解所有其他错误修复和改进。