首页 / 文章

加快 Next.js 开发构建与生产打包速度的九种方法

更快的 Next.js:使用 Turbopack,跳过 barrel 文件,分离类型检查,保持客户端组件体积小巧,延迟加载大型库,并压缩生产环境下的代码包。

发布者:REACTAPP.TOP阅读约 4 分钟991 词

来源: Speeding Up Your Next.js web app: Best Practices

Next.js 在 React 的基础上几乎无需额外配置即可提供路由功能、服务器端渲染、API 路由以及图像优化,正因如此它成为包括 AI 生成项目在内的众多项目的常用选择。然而随着项目规模扩大,同样的问题也会出现:构建速度变慢、热模块替换效率低下,甚至对 UI 进行简单调整都会显得十分迟缓。原本只需一秒的编译现在需要十秒,每月累计下来就是数小时的时间损失;更令人烦恼的是,在页面重新编译期间还得等待 AI 助手应用更改。

让 AI 助手对项目进行审计

使用人工智能代码编辑器时,无需手动应用每一条建议。可以让助手将代码库与以下最佳实践进行对比。一个有效的请求应要求其检查每项最佳实践,解释其重要性,评估对开发速度、构建时间或运行时的影响,展示具体的代码改动,并确认所有内容是否符合当前官方的 Next.js 和 React 文档。它还应标出已过时或被弃用的建议,同时提供更新的方法,且不应进行文档未支持或不符合项目需求的推测性优化。

在合并代码之前,务必先审查它生成的成果。框架发展迅速,一年前有效的做法如今可能已不再适用。应将助手视为经验丰富的审查者,而非绝对权威。最终决策应以官方文档和具体应用的需求为准。

九个值得养成的习惯

1. 在 Turbopack 上进行开发

在最新的 Next.js 版本中,Turbopack 已经能够稳定地用于本地开发。启用它需要通过一个标志来实现:

next dev --turbopack

传统的基于 webpack 的开发服务器会处理项目中的大部分内容,而 Turbopack 只重新构建那些发生变更的模块。在中型和大型项目中,启动速度及热更新性能能立即得到提升。由于生产环境构建仍采用标准流程,因此在开发阶段使用 Turbopack 基本没有风险。

2. 预编译大型依赖项

每次启动时都重新处理那些几乎不会变化的第三方包是导致启动缓慢的主要原因。Material UI、Monaco Editor、Three.js、Chart.js 以及大型图标集在每次开发服务器启动时都需要耗费大量资源。Next.js 可以针对带名称的包优化导入过程:

experimental: {
    optimizePackageImports: [
        "@mui/material",
        "@mui/icons-material",
        "lodash"
    ]
}

当一个工具就能完成工作时,也避免引入整个包。更小的依赖关系图能更快编译。

3. 跳过桶文件

一个重新导出所有组件的 index.ts 文件虽然能让导入结构看起来更整洁,但却迫使编译器遍历比实际需要更多的文件。这样的导入会经过桶文件处理:

import { Button } from "@/components";

从组件自身的路径导入更为合适:

import Button from "@/components/Button";

这只是对模块解析功能进行的微小调整,尤其适用于大型应用。

4. 避免在开发服务器中执行类型检查

许多开发者会阻止开发服务器进行编辑器已自动完成的 TypeScript 检查。应将服务器与 TypeScript 监视工具作为两个独立的进程来运行:

next dev --turbopack
tsc --watch

页面会立即刷新,输入错误也会实时显示出来。

5. 保持客户端组件的体积小巧

在 App Router 中,任何标有 "use client" 的文件都会被纳入浏览器打包包中。需仔细考虑某个组件是否真的需要客户端渲染。静态布局、导航、内容页面以及数据获取功能通常可以作为服务器端组件处理,而仅将那些真正需要交互性的部分设为客户端组件。这样既能减少发送到浏览器的 JavaScript 代码量,也能在开发过程中降低需要重新构建的客户端模块数量。

6. 按需加载大型库

那些在首次渲染时并不需要的依赖可以稍后加载。编辑器、PDF 查看器、地图、图表及可视化相关库都是适合延迟加载的候选对象,只有在用户需要使用时才进行加载:

const Editor = dynamic(() => import("./Editor"), {
    ssr: false
});

初始打包文件以及开发环境下的重新构建后的文件大小依然明显更小。

7. 拆分大型组件

庞大的页面组件会拖慢整体性能。包含数百行JSX的页面最好拆分成更小的、可重复使用的部分,这样编译器能更容易缓存这些部分,测试也更为简单,且当有变动时重新构建的速度也会更快。如果某个文件变得难以管理,通常就说明该将其拆分了。

8. 在开发环境中关闭不必要的服务

分析工具、日志平台、会话回放功能、监控SDK以及营销脚本在正式环境中很重要,但在开发功能时几乎没什么用处。只有在正式环境运行时才启用它们:

if (process.env.NODE_ENV === "production") {
    initializeAnalytics();
    initializePWA();
}

更少的初始化意味着更简洁的本地启动过程,且在开发期间无需进行外部网络调用。

9. 同样要优化生产环境构建

开发速度只是其中一部分。应使用 Next.js 的 Image 组件而非原始图片标签,尽可能进行缓存,压缩资源,并借助服务器端组件来减少最终打包的 JavaScript 代码量。定期使用包分析工具检查打包结果,以便尽早发现异常庞大的依赖项。通常,多次小的改进比最后进行一次大规模优化效果更好。

从何处开始

关键是要弄清楚时间究竟花在了哪里,是在开发阶段、构建过程中还是运行时。首先从基础做起:保持依赖关系图整洁,合理进行代码拆分,尽量减少客户端 JavaScript 代码量,并充分利用 Next.js 已提供的工具。记录各项变化,不断迭代,随着应用的发展再重新审视架构设计。

Next.js 不断发展,每次版本更新都会带来新的建议。无论这些建议来自你自己还是 AI 助手,都应先对照最新的官方 Next.js 和 React 文档进行核实。最佳的优化方案应是适用于你当前所使用版本的,而非去年流行的那种。