写点什么

我们如何使用 Next.js 将 React 加载时间缩短 70%

  • 2022-11-10
    北京
  • 本文字数:3319 字

    阅读完需:约 11 分钟

我们如何使用 Next.js 将 React 加载时间缩短 70%

Causal 是一个多维电子表格,能够处理从基本算术一直到 10 亿次计算的金融模型的一切。Causal 的前端是在 2019 年用 Create React App(CRA)构建的,它为我们提供了很好的服务——它只需要最小的初始设置,并允许快速迭代。随着我们的客户规模和复杂性的增加,性能变得越来越受到关注,我们达到了 CRA 设计支持的极限。最重要的是,CRA 本身并不支持跨多页应用程序的路由分割,所以我们的页面加载时间慢得令人沮丧。为了解决这些问题,我们改用 Next.js,将初始页面加载时间减少了 70%,并将开发者的体验提升到一个新的水平。


什么是 Next.js?


Next.js 是一个框架,带有构建工具和运行时库,用于创建丰富的 React 应用程序。它具有与 CRA 相同的功能,但也包括对 CRA 所缺少的关键功能的内置支持:页面路由、基于页面内容的智能预加载,以及混合静态和服务器端渲染。


从 CRA 迁移到 Next.js


在 2022 年中期,我们认为从 CRA 迁移到 Next.js 的好处是值得投入时间的。我们对于拥有内置的页面路由原语感到特别兴奋,这样我们就不必手动配置路由和 Webpack 构建。


路由


我们之前需要在 CRA 中使用 response-loadable 和 response-router + response-router-dom 来设置我们自己的组件,包括一个大型的 outes.tsx 文件,该文件显式地为应用程序中的每个页面设置了一个路由组件:


import Loadable from "react-loadable";import { Route, Switch } from "react-router-dom";
const EditorLoadable = Loadable({ loader: () => import(/* webpackChunkName: "routes-editor" */ "pages/editor"), loading: ChunkLoading,});
export function RouteSwitch() { return ( <Switch> <Route path={`/model/:id/edit`} render={() => <EditorLoadable />} /> </Switch> );}
复制代码


与 CRA 相比,Next.js 的优势之一是,Next.js 带有自己的集成链接和路由解决方案,即 next/router。Next.js 只需要在 pages/model/[:id]/edit.tsx 上放置一个带有默认导出的 React 组件的文件,就可以在这个路径上渲染一个页面,其中的 id 属性指示 URL 的 id。


此外,内置的 Next.js Webpack 配置会自动将页面分割成各自的包(bundle)。这意味着访问一个用于本地开发的页面只需要构建该页面所需的包内容。虽然 CRA 支持代码分割,但根据我们的经验,Next.js 配置对于本地重建来说是开箱即用的,速度快得多。


样式


Causal 代码库中的许多旧的 CSS 文件是在团队对 CSS 模块的最佳实践进行标准化之前编写的。其中一些文件使用了“不纯”的 CSS 选择器,这意味着它们可能会影响页面上其他地方的组件所呈现的元素。


例如,我们以前的 Button 组件无意中针对页面上的所有按钮:


// styles/button.scssbutton:disabled {  cursor: not-allowed;}
复制代码


// components/Button.tsximport "styles/button.scss";
export function Button(props) { return <button {...props} />; }
复制代码


我们尽可能地将全局 CSS 样式转换为 CSS 模块。这使得组件可以更明确地说明它们采用了哪些样式。


例如,我们在其 CSS 模块中将 Button 组件切换到一个有作用域的类名:


// components/Button/styles.module.scss.button:disabled {  cursor: not-allowed;}// components/Button/index.tsximport styles from "./styles.module.scss";
export function Button({ className, props }) { return <button className={cx(styles.button, className)} {...props} />; }
复制代码


注意:在最终切换到 Next.js 之前,切换到“纯” CSS 模块也大大改善了 CRA 应用的构建时间。许多 .scss 文件也一直在使用 @USE 和 @EXTEND SCSS 指令来使用其他共享的 .scss 文件来构建样式。这些指令导致共享文件被重新构建为包含它们的每个文件的一部分——导致一些较大文件的每个文件的构建时间都要花费数秒钟!


更多信息请参见 Next.js 关于纯模块的讨论答案。(https://github.com/vercel/next.js/discussions/16050#discussioncomment-49022)


部署


一旦我们让 Next.js 在本地工作,下一步就是要改变我们的部署策略。


在这里,CRA 和 Next.js 有根本的区别。CRA 的构建输出只是静态文件,所以提供它相对简单。Next.js 的构建输出确实包括一些静态文件,但它也可能包括运行一个单独服务器的代码。这个服务器负责提供重定向服务,在服务器端渲染动态页面,同时也提供静态页面。


在评估部署我们新的 Next.js 前端的选项时,我们确定了三种可能性:


  1. 不要对 Next.js 使用任何服务器端渲染,使用 next export 构建,并将输出与 CRA 的静态输出完全相同。

  2. 将整个前端托管在 Vercel 上,指向我们的后端(托管在 GCP 中)。

  3. 为 Next.js 服务器编写一个自定义的 Docker 镜像,并将其与我们的后端和其他服务一起托管在 GCP 中。


每种选项都各有利弊:


next export:


优点:要设置的工作量几乎为 0(与 CRA 输出相同)


缺点:不支持服务器端的渲染


托管 Vercel:


优点:只需最少的设置缺点:没有官方对 Yarn2 的支持


缺点:无法轻松连接到数据库以实现更快的服务器端渲染


自定义的 Docker 镜像:


优点:


  • 服务器端渲染的 D 日 ECT DB 连接的最大灵活性是可能的,由于 GCP 的上的托管,后端 API 调用将会非常快

  • 对所需 / 使用的资源进行最细粒度的控制


缺点:所需的最多设置:Vercel 提供了一些示例,但它们并不是开箱即用;Kubernetes 路由 / 网络、扩展等都需要自定义设置


考虑到我们希望获得最大的灵活性,我们选择了选项 3: 编写自定义 Docker 镜像。(不过,我们仍将部署在 Vercel——稍后将详细介绍!)我们在几个页面上进行了少量的服务器端渲染,我们发现到目前为止性能非常好,这在很大程度上归功于与其他服务通信所需的最小网络距离。


预览 App


尽管 Vercel 对于我们的生产部署来说并不可行(如上所述),但它对于其预览 App 仍然相当有用。虽然设置 Vercel 的构建过程需要一些变通方法(因为前面提到的缺乏 Yarn 2 的支持,以及构建我们前端使用的通用包),但好处是巨大的:现在推送到我们 GitHub 仓库的每一个提交都会作为一个预览 App 在 Vercel 上构建和部署,并指向我们的 staging 后端。


这使得前端修改的代码审查体验得到了数量级的改善。审查者只需点击他们正在审查的 PR 中的一个链接,就可以准确地预览该分支在生产中的样子,而不需要在本地拉出分支来进行测试。


虽然这一变化不需要 Next.js,但由于 Vercel 对其自身框架的原生支持,这也是轻而易举的。


结   果


切换到 Next.js 后,终端用户和开发人员的体验都得到了明显的改善。


Causal 模型通常是由几个人创建的,但也有几十个人查看;这些查看者看的是模型仪表板。而在没有对高级服务器端渲染做出任何努力的情况下(使用例如 getServerSideProps),这些仪表盘的加载时间减少了 32%(2.6 秒 → 1.5 秒)!


简单的页面有更显著的速度提升。例如,我们的主页(my.causal.app)的加载速度提高了 71%(1.7 秒 → 0.5 秒),除了从加载状态到载入状态的必要过渡,没有任何布局上的跳跃。


性能上的好处不仅仅是用户体验。Next.js 的开发体验明显比 CRA 快;开发人员从 30%(或更多!)更快的启动时间中受益,快速刷新体验是一种游戏规则的改变者,可以快速迭代小型 UI 调整。到目前为止,最大的改进来自拉取请求预览 App——这是对代码审查体验的重大改进。预览前端代码变化只需要几秒钟而不是几分钟,这使我们能够对较小的拉取请求进行更频繁的审查,也使我们的客户成功团队能够在开发过程的早期提供反馈。


下一步


看到 App 在 Next.js 上运行,我们感到非常兴奋。我们的页面加载速度明显更快,我们的本地构建只需几秒钟而不是几分钟就可以开始,我们需要维护的 Webpack 配置量是几十行而不是几百行。


我们计划很快实现更多的服务器端渲染,首先是嵌入式图表和表格,这些通常是由匿名访客查看的。我们希望看到这些用户的体验能因更快地加载时间而得到明显改善。


当然,现代 Web 应用的性能远不止首次加载时间那么简单。更重要的是用户互动的性能,这在 Causal 中特别难以优化,因为我们是一个渲染复杂网格、图表和表格的重数据应用。在未来的博客文章中,我们将分享更多关于如何解决这些性能问题的内容。


原文链接:


https://www.causal.app/blog/next-js


2022-11-10 19:136706

评论

发布
暂无评论
发现更多内容

选择住宅ip代理还是数据中心代理?

巨量HTTP

代理IP http代理

杭州悦数加入龙蜥社区,共同探索图数据库的未来

OpenAnolis小助手

数据库 开源 操作系统 龙蜥社区 杭州悦数

华为云,让AI算力入山河

脑极体

云计算

沉浸式体验与 AI 数智助理一起工作的一天

Kyligence

人工智能 数据分析

Golang微服务框架Kratos应用MQTT消息队列

golang mqtt Kratos #微服务

CIIS 2023丨聚焦文档图像处理前沿领域,合合信息AI助力图像处理与内容安全保障

合合技术团队

人工智能 文档 智能 多模态 大模型

下一个时代的船舵,李彦宏握住AI原生应用

脑极体

AI

IPA文件重签名教程:使用Ipa Guard进行签名和安装到设备的详细步骤

Linux 爱好者线下沙龙:LLUG 2023 深圳硬核来袭 | 第三站

OpenAnolis小助手

沙龙 龙蜥社区 开源操作系统 LLUG Linux中国

使用 Databend 加速 Hive 查询

Databend

华为“轻松打卡全世界”活动提供一站式出境服务,全球酒店预订85折起

最新动态

API网关是如何提升API接口安全管控能力的?

不思jo

安全 API

多模态 多引擎 超融合 新生态!2023亚信科技AntDB数据库8.0产品发布

亚信AntDB数据库

AntDB 国产数据库 AntDB数据库

[文本提取]基于Apache Tika的文本内容提取

alexgaoyh

Java nlp tika 文本提取 内容提取

狂热过后,RPA到底是什么?

金小K

RPA RPA评测 RPAxAI

C++输入流和输出流介绍

芯动大师

Golang微服务框架Kratos应用RabbitMQ消息队列

golang RabbitMQ Kratos #微服务

Golang微服务框架Kratos应用NATS消息队列

golang 消息队列 Kratos #微服务

如何出色的进行“自我介绍”?

王磊

Java java面试

"开源奥斯卡”认可!天谋科技 IoTDB 企业版荣获 OSCAR 开源尖峰案例开源技术创新(商业产品)奖

Apache IoTDB

演讲实录:DataFun 垂直开发者社区基于指标平台自主洞察北极星指标

Kyligence

数据分析 指标中台

【GO】LGTM_Grafana_gin_trace中间件(3)_代码实操

非晓为骁

golang Grafana Trace gin tempo

医疗虚拟仿真和虚拟现实有什么区别?哪个更好?

3DCAT实时渲染

虚拟现实 虚拟仿真 实时云渲染

《操作系统实战 45 讲》笔记5——接口与虚化

袁世超

操作系统 Cosmos LMOS

前后端分离的低代码快速开发框架

树上有只程序猿

前后端分离 低代码开发 JNPF

TiDB 7.1.0 LTS 特性解读丨关于资源管控 (Resource Control) 应该知道的 6 件事

PingCAP

数据库 TiDB

Golang微服务框架Kratos应用Pulsar消息队列

golang pulsar Kratos #微服务

Golang微服务框架Kratos应用NSQ消息队列

golang nsq Kratos #微服务

Golang微服务框架Kratos应用Kafka消息队列

golang kafka Kratos 消息列队 #微服务

Golang微服务框架Kratos应用RocketMQ消息队列

golang RocketMQ 消息队列 Kratos #微服务

我们如何使用 Next.js 将 React 加载时间缩短 70%_开源_Causal_InfoQ精选文章