前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >next.js 源码解析 - getServerSideProps 篇

next.js 源码解析 - getServerSideProps 篇

作者头像
嘿嘿不务正业
发布于 2023-05-09 03:30:55
发布于 2023-05-09 03:30:55
1.1K00
代码可运行
举报
文章被收录于专栏:嘿嘿的专栏嘿嘿的专栏
运行总次数:0
代码可运行

老规矩,昨天写了关于 getServerSideProps 的内容,今天趁热写一下 getServerSideProps 相应的源码,看看 next.js getServerSideProps 是怎么实现的,还有什么从文档无法知晓的细节。

SSR 处理

我们先从 SSR 时相关的 getServerSideProps 处理看起,源码排查步骤上一步已经有所介绍,本篇不再多说,在 SSR 时,next.js 会调用 doRender 来进行渲染,其中会再次调用 renderHTML,进过各种判断和调用最终会进入 packages/next/server/render.tsx 中的 renderToHTML 进行处理。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// const SERVER_PROPS_ID = "__N_SSP";
if (getServerSideProps) {
    props[SERVER_PROPS_ID] = true;
}

next.js 会先将 props 中的 SERVER_PROPS_ID 设置为 true,用做标识。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
try {
    data = await getServerSideProps({
        req: req as IncomingMessage & {
            cookies: NextApiRequestCookies;
        },
        res: resOrProxy,
        query,
        resolvedUrl: renderOpts.resolvedUrl as string,
        ...(pageIsDynamic ? { params: params as ParsedUrlQuery } : undefined),
        ...(previewData !== false ? { preview: true, previewData: previewData } : undefined),
        locales: renderOpts.locales,
        locale: renderOpts.locale,
        defaultLocale: renderOpts.defaultLocale
    });
    canAccessRes = false;
} catch (serverSidePropsError: any) {
    if (isError(serverSidePropsError) && serverSidePropsError.code === 'ENOENT') {
        delete serverSidePropsError.code;
    }
    throw serverSidePropsError;
}

if (data == null) {
    throw new Error(GSSP_NO_RETURNED_VALUE);
}

if ((data as any).props instanceof Promise) {
    deferredContent = true;
}

const invalidKeys = Object.keys(data).filter(key => key !== 'props' && key !== 'redirect' && key !== 'notFound');
if (invalidKeys.length) {
    throw new Error(invalidKeysMsg('getServerSideProps', invalidKeys));
}

注意这里的 getServerSideProps 是从外层传进来了,因为涉及的代码较多,就不贴了,主要是通过 packages/next/server/load-components 中的 loadComponents,将路由文件中的 getServerSideProps 通过从 require 后的页面中取出。不过挺好奇他在 node 端是怎么 require 页面代码而不报错的,毕竟页面代码中很可能会存在依赖浏览器环境的代码,估计是做了一些类似于 runtime shim 之类的操作?此处先挖个坑,以后有空研究下。突然想起页面都是 SSR 了,初始化代码肯定都做过处理了 😂。

上面的代码可以看出 SSR 的时候是直接调用 getServerSideProps 传入 context 内容,context 的内容也一目了然。然后 next.js 会校验返回值是否为空,或者是否包含非法参数等。

然后回去检查 notFoundredirect 参数,进行特殊处理。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if ('notFound' in data && data.notFound) {
    if (pathname === '/404') {
        throw new Error(`The /404 page can not return notFound in "getStaticProps", please remove it to continue!`);
    }

    (renderOpts as any).isNotFound = true;
    return null;
}

if ('redirect' in data && typeof data.redirect === 'object') {
    checkRedirectValues(data.redirect as Redirect, req, 'getServerSideProps');
    (data as any).props = {
        __N_REDIRECT: data.redirect.destination,
        __N_REDIRECT_STATUS: getRedirectStatus(data.redirect)
    };
    if (typeof data.redirect.basePath !== 'undefined') {
        (data as any).props.__N_REDIRECT_BASE_PATH = data.redirect.basePath;
    }
    (renderOpts as any).isRedirect = true;
}

此外从上面这段代码还发现一个有意思的就是 props 是可以为 Promise 的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if ((data as any).props instanceof Promise) {
    deferredContent = true;
}

返回 Promise 时,next.js 会在异常处理完毕后获取值:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if (deferredContent) {
    (data as any).props = await(data as any).props;
}

最后 next.js 会将获取到的 props 值放入到顶层的 props 中:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
props.pageProps = Object.assign({}, props.pageProps, (data as any).props);
(renderOpts as any).pageData = props;

SSR 时,我们在页面中看到的用于 hydrate__NEXT_DATA__ 中的 props 就是这个 props,可以再看一眼其中的数据:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<script id="__NEXT_DATA__" type="application/json">
    {
        "props": {
            "pageProps": {
                "feature": {
                    "name": "xxxx",
                    "desc": "xxxx",
                    "tags": ["xxx"],
                    "id": "account-manage"
                }
            },
            "__N_SSP": true
        },
        "page": "/feature/[fid]",
        "query": { "fid": "account-manage" },
        "buildId": "development",
        "isFallback": false,
        "gssp": true,
        "scriptLoader": []
    }
</script>

可以看到 pageProps__N_SSP 都是上面放进去的。

动态加载处理

看完了 SSR 场景下,next.js 如何处理 getServerSideProps,我们再看下页面为动态加载时的处理。

通过跳转时发起请求的调用栈,我们很轻松就能找到在页面为动态加载时,next.js 将会通过 packages/next/shared/lib/router.ts 中的 getRouteInfo 来获取要跳转的页面信息,然后会通过 routeInfo__N_SSP 判定是否要去获取数据:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const shouldFetchData = routeInfo.__N_SSG || routeInfo.__N_SSP;
if (shouldFetchData) {
    const { json, cacheKey: _cacheKey } = data?.json
        ? data
        : await fetchNextData({
              dataHref: this.pageLoader.getDataHref({
                  href: formatWithValidation({ pathname, query }),
                  asPath: resolvedAs,
                  locale
              }),
              isServerRender: this.isSsr,
              parseJSON: true,
              inflightCache: this.sdc,
              persistCache: !isPreview,
              isPrefetch: false,
              unstable_skipClientCache
          });

    return {
        cacheKey: _cacheKey,
        props: json || {}
    };
}

然后通过 fetchNextData 来获取数据,而我们上文提到的 _next/data/development/{url}.json?{query} 这段 URL 就是由 formatWithValidation 构建生成的。

而请求发送后服务端的处理就七绕八绕逻辑太深了,这里不一一列举代码,简单说下:next.js 会通过 /_next/data/ 匹配请求判断是否是数据请求,如果是数据请求将会一样执行 SSR代码,然后可以理解为走的就是上面 SSR 初始化时的那套逻辑,只是最后会按照数据请求标识,将 props 抽离出来,放到响应中中返回。

总结

getServerSideProps 相关的源码还是有点绕的,其中应该还少了一些其它场景的相关代码,不过只看主场景应该就是这些了。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-01-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 嘿前端 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
一起来学 next.js - getStaticProps、getStaticPaths 篇
之前讲过 next.js 中的 getServerSideProps,今天来讲一讲另一个很类似的 API:getStaticProps,以及和 getStaticProps 紧密相关的 getStaticPaths。
嘿嘿不务正业
2023/05/09
1.6K0
一起来学 next.js - getStaticProps、getStaticPaths 篇
一起来学 next.js - getServerSideProps 篇
getServerSideProps 是 next.js 中的一项特色功能,可以让我们在给页面设置一些初始的 props 参数。
嘿嘿不务正业
2023/05/09
1.8K0
一起来学 next.js - getServerSideProps 篇
Next.js 简明教程
最近用Next.js + Editor.js 撸了一个博客系统。开发起来甚是畅滑,如果你喜欢React,又有同构的需求,不妨由此文入手。
小刀c
2022/09/21
3.1K0
Next.js 简明教程
React 必学SSR框架——next.js
F首先我们就回顾一下,我们到底是怎么告别了使用 php/jsp 做服务器端渲染,进入前后端分离的客户端渲染时代,又为什么重新回到了服务端渲染。
狂奔滴小马
2021/11/15
8K0
React 必学SSR框架——next.js
Next.js + TypeScript 搭建一个简易的博客系统
来记录下学习(踩坑)的过程,这篇文章的代码都在https://github.com/Maricaya/nextjs-blog-1啦。
coder_koala
2020/09/17
4.1K0
React服务端渲染-next.js
前台渲染-SPA应用是一个主要阵营,如果说有什么缺点,那就是SEO不好。因为默认的HTML文档只包含一个根节点,实质内容由JS渲染。并且,首屏渲染时间受JS大小和网络延迟的影响较大,因此,某些强SEO的项目,或者首屏渲染要求较高的项目,会采用服务端渲染SSR。
娜姐
2020/09/22
4.1K0
React服务端渲染-next.js
Next.js静态页面渲染技术(静态生成和服务端渲染):BSR/SSR/SSG
next是一款用JS开发的全栈框架,它是基于express框架基础上开发而成,可以用react写客户端,node.js写服务端。一份代码可在前后端同时运行,这在next中称之为同构!
周陆军博客
2023/05/14
4K0
Next.js进阶:静态生成、服务器端渲染与SEO优化
Next.js在现代Web开发中处于重要地位,尤其是其对静态生成(Static Generation, SG)、服务器端渲染(Server-Side Rendering, SSR)以及搜索引擎优化(Search Engine Optimization, SEO)的强大支持。在本文中,我将深入探讨这些核心特性的工作原理、应用场景及最佳实践,并通过代码示例演示如何在实际项目中高效利用Next.js实现高性能、高SEO友好的应用。
Jimaks
2024/04/16
1.3K0
Next.js基础教程:入门与实战
Next.js是一个流行的React框架,用于构建服务器 - 渲染(SSR)和静态网站生成(SSG)的现代Web应用程序。它提供了一种简单而高效的方式来开发具有高性能和良好可扩展性的Web应用。其独特之处在于能够充分利用服务器端渲染的优势,提高首屏加载速度,改善搜索引擎优化(SEO),同时也方便与React的各种生态系统集成。
Front_Yue
2025/01/06
7390
Next.js基础教程:入门与实战
Next.js实现国际化方案完全指南
最近 Next-Admin 中后台管理系统已经支持国际化,接下来就和大家分享一下实现国际化的详细方案,方便大家轻松应用到自己的项目。
徐小夕
2024/04/14
1.4K0
Next.js实现国际化方案完全指南
Next.js + 云开发Webify 打造绝佳网站
之前使用 Next.js + strapi 做了一个简单博客站点也顺道写了一篇 Next.js 简明教程,之后 Next 本身一直在迅猛发展。利用代 js 能力来说做到了:
腾讯云开发TCB
2021/09/10
1.6K0
Next.js + 云开发Webify 打造绝佳网站
Next.js/Nuxt.js/Nest.js/Fastify
安利下:《next.js静态页面渲染技术(静态生成和服务端渲染):BSR/SSG/SSG》
周陆军博客
2023/05/14
3.4K0
改变渲染顺序实现按需加载,主要可以从以下几个方面入手:
当你访问http://localhost:3000/app/list/testpage时,Next.js 的处理顺序是:
用户1232103
2024/12/14
1410
从 Next.js 看企业级框架的 SSR 支持
面向生产使用的 React 框架(废话)。提供了好些开箱即用的特性,支持静态渲染/服务端渲染混用、支持 TypeScript、支持打包优化、支持按路由预加载等等:
ayqy贾杰
2020/12/14
4K0
从 Next.js 看企业级框架的 SSR 支持
Next.js 有哪些主要功能?
Next.js 是由 Vercel 开发的一款开源 React 框架,以其丰富的高级功能和对应用性能的优化备受开发者青睐。
前端小智@大迁世界
2025/02/06
3140
动手练一练,使用 React 和 Next.js 做一个简单的博客网站(下)
大家好,在《动手练一练,使用 React 和 Next.js 做一个简单的博客网站(上)》和 《动手练一练,使用 React 和 Next.js 做一个简单的博客网站(中)》这两篇文章里,我们一起完成了一个基于 MakeDown 文档为内容页源的博客网站,学习了动态路由(Dynamic Routes)、Static Generation 相关的知识及应用,本篇文章,我们将学习如何使用服务端渲染(Server-side Rendering)、客户端渲染(Client-side Rendering)的内容,最后再和大家聊聊如何编译项目、部署站点。
前端达人
2021/04/22
1.6K0
基于 Next.js 的 SSR/SSG 方案了解一下?
本文主要是讲讲如何使用 Next.js 框架实现服务端渲染,将有效提升网页的 SEO 和首屏渲染速度,说不定哪天就用上了,是吧!
小东同学
2022/07/29
5.8K0
基于 Next.js 的 SSR/SSG 方案了解一下?
一起来学 next.js - 关闭 SSR 方案及 hydration 错误的原因和解决方案
今天聊一聊上手 next.js 使用中常会出现的一类报错:hydration fail,估计大部分使用过 next.js 开发的同学对下面的报错信息一定都很熟悉:
嘿嘿不务正业
2023/05/09
4.7K0
一起来学 next.js - 关闭 SSR 方案及 hydration 错误的原因和解决方案
React 应用架构实战 0x3:构建和配置页面
这一节,将学习 Next.js 中的路由工作原理以及可以使用的渲染方法,以充分利用 Next.js 的特性。然后,我们将学习如何配置每个页面的布局,使应用程序看起来和感觉像一个单页应用程序。
Cellinlab
2023/05/17
8900
React 应用架构实战 0x3:构建和配置页面
Next.js - SSR / SSG / CSR / ISR / Dynamic Routing
Next.js 提供了多种网页渲染方式,这取决于你的服务应用的场景,包括服务端渲染、客户端渲染、静态生成、增量静态生成等。
轻量级云原生架构实验室
2022/12/01
1.3K0
相关推荐
一起来学 next.js - getStaticProps、getStaticPaths 篇
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验