【AICon】硅谷视野+中国实践,汇聚全球顶尖技术的 AI 科技盛会 >>> 了解详情
写点什么

我们如何使用 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:135914

评论

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

什么是plist

雪奈椰子

ios 开发 IPA上传

WeOpsV3.16持续拓展云平台能力,监管华为ManageOne云平台

嘉为蓝鲸

运维 weops

开心档之C++ 多线程

雪奈椰子

集简云已支持GPT-4 API接口,将最新AI模型接入到您的业务流程中

集简云开放平台

人工智能 ChatGPT

业务导向且支持开发过程的测试

测吧(北京)科技有限公司

测试

达观助手智能写作,让写作更快更好更有趣!

NLP资深玩家

REST API 安全基础知识:保护你的应用程序和用户数据

Apifox

API 企业安全 REST API 安全认证 API 安全

Nautilus Chain 上首个 DEX PoseiSwap 通证经济学模型解析

威廉META

OctConv:八度卷积复现

华为云开发者联盟

人工智能 华为云 卷积 华为云开发者联盟 企业号 4 月 PK 榜

华为云EI:引领企业智能化转型,助力全球行业创新

爱尚科技

解锁企业数据管理的利器——DataOps

数造万象

plist 文件是什么

雪奈椰子

ios 开发 IPA上传

“云智一体”进化史

百度开发者中心

人工智能 云智一体 文心一言

报名开启!成都首个ChatGPT和大模型专题研讨会,期待您的参与!

NLP资深玩家

百度智能云助力达拉特旗入选“数字城市创新成果与实践案例”

百度开发者中心

人工智能 智慧城市 云智一体

嘉为蓝鲸携手腾讯云亮相石油石化峰会!

嘉为蓝鲸

能源 嘉为蓝鲸 研运一体化

华为云FusionInsight引领现代数据平台革新:助力企业数字化转型与增值

科技怪授

Wallys/The IPQ9554+qcn6274 support the new WiFi 7 standard

Cindy-wallys

ipq9554 qcn6274

基于低代码开发平台打造新时代OA系统

力软低代码开发平台

REST 与 SOAP 之间的差异

Apifox

Rest 协议 soap REST API SOAP Webservice

如何使用 Postman 发送 JSON 数据

Liam

json Postman 接口测试 API API 调试

The era of Wallys/wifi7 has arrived-ipq9574+qcn9274.

Cindy-wallys

qcn9274 ipq9574

C++ 循环

雪奈椰子

开心档

深度学习:理解卷积神经网络(CNN)的原理和应用

兴科Sinco

人工智能 神经网络 深度学习 自然语言 图象识别

如何打开 plist 文件

ios 开发 IPA上传

中台的下一站:行业数字化操作系统

创智荟

中台 操作系统 数字化

C++ 修饰符类型

雪奈椰子

iOS上架 IPA上传

一文吃透低代码平台源代码交付的重要性

这我可不懂

软件开发 低代码 JNPF

Dapr和Rainbond集成,实现云原生BaaS和模块化微服务开发

北京好雨科技有限公司

云原生 #Kubernetes# Baas rainbond 企业号 4 月 PK 榜

持续集成的前提条件

测吧(北京)科技有限公司

测试

北京 Meetup 邀你来|云上 StarRocks 极速湖仓

StarRocks

数据库 活动 OLAP 大数据分析 StarRocks

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