- Published on
选用 Next.js 之前要注意什么?做了三个项目之后,谈谈我的想法
- Authors
- Name
- 阿森 Hansen
本篇文章包含以下内容:
- 对 Next.js 的特性,服务端渲染的介绍
- Next.js 的优点
- 使用 Next.js 需要注意的地方
语法和框架细节不是本文要讨论的主题,如有兴趣,请自行搜索 Next.js 的教程。例如官方的:Learn Next.js | Next.js by Vercel - The React Framework
Next.js 需要 React 基础,本文不另外讨论,如对 React 感兴趣,可前往:React Foundations | Next.js
有趣的 Next.js
最近好奇使用了一下 Next.js 做了几个小项目。用了一段时候发现这个框架极有意思。
当前的主流框架,一般都采用前后端分离的单页面应用模式(SPA)。浏览器就相当于一个应用程序,只不过这个应用程序由浏览器在访问网站时加载,而无须本地安装。
然而 Next.js 却创新地将现代前端开发技术和传统的服务器渲染技术(SSR)结合,做成了一个开箱即用的,既包含了前端功能,也有后端的“大而全”的框架。
服务端渲染(SSR)的背景
最早的 Web 应用就是服务端渲染。例如在我们大学里学的 JSP、ASP 等,网页的处理由服务器完成,然后发送给浏览器渲染。浏览器只是一个“显示器”,仅渲染网页。
而后,HTML + CSS + JS 技术栈成为主流,Node 兴起,程序员们发现 JS 有很强的处理能力,于是出现了前后端分离的架构:服务器仅发送数据,浏览器负责进一步加工、处理、渲染,最终展示给用户。
前后端分离,将网页模版的渲染过程放在了浏览器,简化了服务器的逻辑,也减轻了服务器的计算压力。
随着云计算和移动互联网的发展,开发方式出现回潮。云服务使得计算能力随处可得,5G 也让通信成本大幅降低。边缘计算、Serverless 甚至在部分平台可以免费使用。
如此背景下,服务端渲染重获生机,Next.js 和 Nuxt 这样的一体化框架开始出现。
我的感受:全而美
我把 Next.js 的优点总结为以下几点:
- 一体化和干净:Next.js 类似于 SpringBoot 这样的 Web 全家桶,它自带了一套服务器和模版渲染引擎。直接创建一个项目,TS/JS 就可以完成服务端操作和客户端页面渲染,项目既干净又美丽。无需学习其他语言,更不用在一个项目里混杂各种不同语言的语法。
- SEO:得益于服务端渲染,搜索引擎的爬虫无需执行页面上的脚本就能获得全部的页面信息。让网页可以被更好收录。
- 性能:得益于一体化,Next.js 在其内部对函数计算和缓存做了更多优化。而从懒加载,到数据缓存,都能很方便地处理。
- 部署:部署极为方便,直接
npm run build
就可以得到 Web 应用,开发调试也做了很多优化。如果利用 vercel 技术栈,那是更加方便了。
一些注意事项
对于开发者来说,这里有很关键的一点是你要注意的:
注意运行边界:一定要搞清楚你正在写的代码,到底运行在哪里。
这里有很多奥妙,而也是我认为 Next.js 最大的一个坑。这里的根源就是在于它会自动拆分代码,一部分运行在服务器,另一部分运行在客户端。
并且,在服务器端,还有两个环境,一个是 Node 环境,另一个是边缘环境(Edge Runtime),前者是服务器主要的运行环境,后者一般用来运行一些轻量级函数,例如中间件。边缘环境受限很多,只能做一些轻量级的操作。这让编程变得更复杂!
关于两个环境的说明,可移步:Rendering: Runtimes | Next.js
所以,在落笔代码之前,一定对项目有个大体的构架:哪些功能用 Server 组件,哪些用客户端渲染的 Client 组件,哪些地方用 ServerAction,哪些地方声明 API Routes。
否则,你的项目在运行时会遇到大量错误(例如服务使用的库无法在客户端执行),要重构才能解决。
对于这个问题,我有以下四点总结:
- 优先使用服务端渲染的 Server 组件(
'use server'
):这将最大化 Next.js 的优势,也可以获得更好的性能。一般来说,数据展示、单向的表单提交,发起 http 请求等功能都适合用服务端渲染。当然 Next.js 默认也是服务端渲染。 - 复杂交互使用客户端渲染的 Client 组件(
'use client'
):当服务端渲染无法胜任的时候,考虑客户端渲染。一般需要客户端处理的情况:复杂的表单交互,绘图,动画,复杂的响应。对于复杂的页面,做好 Server 和 Client 组件的相互嵌套,达到最好的懒加载效果。 - ServerAction (也是
'use server'
):绝大部分操作数据库都可以用 ServerAction 来处理,例如为 Server 或 Client 组件提供读写数据的能力。Next.js 会为你自动做好代码拆分,保证性能和安全性。 - API Routes:我个人认为,API Router 的存在是为了保证最大的兼容性,所以最好只有在外部系统要访问当前项目的时候,或者功能不适合用 ServerAction 时,再考虑利用 API Router。
你可以参考:
- 关于挑选客户端和服务端组件:Rendering: Composition Patterns | Next.js
- 关于 ServerAction:Data Fetching: Server Actions and Mutations | Next.js
- 关于 API Routes:Routing: Route Handlers | Next.js
- 关于挑选 ServerAction 还是 API Routes,这篇文章认为写数据用 ServerAction,读数据用 API:reactjs - Nextjs 14: Server actions vs Route handlers - Stack Overflow
关于编程框架的反思
越大而全的框架限制越多,学习、适应的成本也就越高,在方便使用的同时,若要定制就会限制更多,例如要更改一些预设好的功能,可能要 Hacking。
框架的定制,会有种“戴着镣铐跳舞”的感觉。
总之,计算机技术“没有银弹”。每个框架都有优缺点和适用范围,而我对此的建议是,什么场景下就用什么样的技术,别硬来,别纠结。
This work is licensed under Creative Commons Attribution-NonCommercial 4.0 International