本文转载自微信公众号「前端向后」,作者黯羽轻扬 。转载本文请联系前端向后公众号。
网站的建设成都创新互联专注网站定制,经验丰富,不做模板,主营网站定制开发.小程序定制开发,H5页面制作!给你焕然一新的设计体验!已为木托盘等企业提供专业服务。
一.Next.js 简介
The React Framework for Production
面向生产使用的 React 框架(废话)。提供了好些开箱即用的特性,支持静态渲染/服务端渲染混用、支持 TypeScript、支持打包优化、支持按路由预加载等等:
Next.js gives you the best developer experience with all the features you need for production: hybrid static & server rendering, TypeScript support, smart bundling, route pre-fetching, and more. No config needed.
其中,完善的静态渲染/服务端渲染支持让 Next.js 在 React 生态中独树一帜
二.核心特性
如果说 Next.js 只做了一件事,那就是预渲染(Pre-rendering):
By default, Next.js pre-renders every page. This means that Next.js generates HTML for each page in advance, instead of having it all done by client-side JavaScript.
具体的,预渲染分为两种方式:
与 SSR 相比,Next.js 更推崇的是 SSG,因为其性能优势更大(静态内容可托管至 CDN,性能提升立竿见影)。因此建议优先考虑 SSG,只在 SSG 无法满足的情况下(比如一些无法在编译时静态生成的个性化内容)才考虑 SSR、CSR
P.S.CSR、SSR 等更多渲染模式,见前端渲染模式的探索
围绕核心的预渲染功能,延伸出了一系列相关支持,如:
此外,还提供了一些通用场景支持:
三.路由支持
Next.js 提供了两种路由支持,静态路由与动态路由
静态路由
静态路由通过文件规范来约定,pages目录下的js文件都认为是路由(每个静态路由对应一个页面文件),例如:
- pages/index.js → /
- pages/blog/index.js → /blog
- pages/blog/first-post.js → /blog/first-post
- pages/dashboard/settings/username.js → /dashboard/settings/username
动态路由
类似的,动态路由也要在pages目录下创建文件,只是文件名有些不同寻常:
- pages/blog/[slug].js → /blog/:slug (/blog/hello-world)
- pages/[username]/settings.js → /:username/settings (/foo/settings)
- pages/post/[...all].js → /post/* (/post/2020/id/title)
路径中变化的参数通过getStaticPaths来填充:
- // pages/posts/[id].js
- export async function getStaticPaths() {
- return {
- // 必须叫paths,值必须是数组
- paths: [{
- // 每一项必须是这个形式
- params: {
- // 必须含有id
- id: 'ssg-SSR'
- }
- },{
- params: {
- id: 'pre-rendering'
- }
- }],
- fallback: false
- }
- }
进一步传递给getStaticProps按参数获取数据,并渲染页面:
- props: {
- postData
- }
- }
- }
- // 渲染页面
- export default function Post({ postData }) {
- return (
{postData.title} {postData.title}
- )
- }
可以理解为先创建一个工厂 page(例如pages/[路由参数1]/[路由参数2].js),接着getStaticPaths填充路由参数,getStaticProps({ params })根据参数请求不同数据,最后数据进入页面组件开始预渲染:
四.SSG 支持
最简单,同时性能也最优的预渲染方式就是静态生成(SSG),把组件渲染工作完全前移到编译时:
将生成的 HTML 静态资源托管到 Web 服务器或 CDN 即可,兼具 React 工程优势与 Web 极致性能
那么首先要解决如何获取数据的问题,Next.js 的做法是将页面依赖的数据集中管理起来:
- // pages/index.js
- export default function Home(props) { ... }
- // 获取静态数据
- export async function getStaticProps() {
- // Get external data from the file system, API, DB, etc.
- const data = ...
- // The value of the `props` key will be
- // passed to the `Home` component
- return {
- props: ...
- }
- }
其中,getStaticProps只在服务端执行(根本不会进入客户端 bundle),返回的静态数据会传递给页面组件(上例中的Home)。也就是说,要求通过getStaticProps提前备好页面所依赖的全部数据,数据 ready 之后组件才开始渲染,并生成 HTML
P.S.注意,只有页面能通过getStaticProps声明其数据依赖,普通组件不允许,所以要求将整页依赖的所有数据都组织到一处
至于渲染生成 HTML 的部分,借助React 提供的 SSR API即可完成
至此,只要是依赖数据有办法提前获取到的页面,理论上都可以编译生成静态 HTML,但 2 个问题也随之而来:
以电商页面为例,要把海量商品数据全都编译成静态页面,几乎是不可能的(或许要编译一个世纪那么长),即便都生成了,商品信息也会时不时地更新,静态页面需要重新生成:
If your app has a very large number of static pages that depend on data (think: a very large e-commerce site). You want to pre-render all product pages, but then your builds would take forever.
因此,增量静态再生成(Incremental Static Regeneration)应运而生
ISR 支持
对于编译时无法穷举的海量页面以及需要更新的场景,Next.js 允许运行时再生成(相当于运行时静态化):
Incremental Static Regeneration allows you to update existing pages by re-rendering them in the background as traffic comes in.
例如:
- export async function getStaticProps() {
- const res = await fetch('https://.../posts')
- const posts = await res.json()
- return {
- props: {
- posts,
- },
- // 设置有效期,开启ISR
- revalidate: 1, // In seconds
- }
- }
revalidate: 1表示运行时(用户请求打过来时)尝试重新生成静态 HTML,1秒最多重新生成一次
运行时静态生成需要一些时间(用户请求等着要 HTML),在此过程中有 3 种选择:
即结合路由(getStaticPaths)对尚未生成的页面进行降级,例如:
- // pages/index.js
- import { useRouter } from 'next/router'
- function Post({ post }) {
- const router = useRouter()
- // 渲染降级页面
- if (router.isFallback) {
- return
Loading...- }
- // Render post...
- }
- export async function getStaticPaths() {
- return {
- paths: [{ params: { id: '1' } }, { params: { id: '2' } }],
- // (页面级)降级策略,true表示遇到尚未生成的先给个降级页,生成完毕后客户端自动更新过来
- fallback: true,
- }
- }
P.S.具体见Incremental Static Regeneration、以及The fallback key
然而,并非所有场景都能愉快地在编译时静态生成。典型的,如果组件依赖的数据是动态的,显然无法在编译时预先取得数据,静态生成就无从谈起了
五.SSR 支持
对于编译时无法生成静态页面的场景,就不得不考虑 SSR 了:
区别于 SSG getStaticProps,Next.js 提供了 SSR 专用的getServerSideProps(context):
- // pages/index.js
- export async function getServerSideProps(context) {
- const res = await fetch(`https://...`)
- const data = await res.json()
- if (!data) {
- return {
- notFound: true,
- }
- }
- return {
- props: {}, // will be passed to the page component as props
- }
- }
同样用来获取数据,与getStaticProps最大的区别在于每个请求过来时都执行,所以能够拿到请求上下文参数(context)
六.总结
围绕预渲染如何获取数据的问题,Next.js 探索出了别致的路由支持和精巧的 SSG、SSR 支持。不仅如此,Next.js 还提供了鱼和熊掌可以兼得的混用支持,不同渲染模式结合起来到底有多厉害,且看下篇分解
参考资料
原文链接:https://mp.weixin.qq.com/s/bS9GHni4ecnz9UFi9RD24Q
分享文章:从Next.js看企业级框架的SSR支持
当前网址:http://www.shufengxianlan.com/qtweb/news18/243318.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联