「译」getInitialProps vs getServerSideProps in Next.js

Next.js v9.3版本引入了getServerSideProps,在定义服务端渲染这边页面上的props,getServerSideProps基本上取代了getInitialProps.
如今,仍然有些开发者对于使用哪个方法还是比较困惑,在这篇文章会通过各自举例来解释 getServerSidePropsgetInitialProps工作原理,让我们开始吧!

getServerSidePropsgetInitialProps内部工作原理

基本上来说,如果你要在编译阶段发出任何请求之前渲染页面,你应该使用getStaticProps,该方法会使页面静态化进行渲染,也意味着后续不会被重复渲染直到下一次的编译。虽然该方法对于渲染速度及SEO有显著的提高,但它不适合经常改变的动态数据渲染方式。

如果你希望在请求时渲染页面,你可以使用getServerSideProps方法,在客户端得到请求响应时渲染页面。该方法会对每个请求都是做页面渲染,虽然该方法使得服务端会对每个请求重新构建页面,从而降低整体的访问速度,然而该方法相比React在客户端渲染的普通方式有着较大的SEO优势。

next-getserversideprops-getstaticprops-diagram.png

关于语言和框架的升级,向后兼容性很重要,尽管老的模式或方法在后续的工程里不再使用,它们仍然被维护,以此保证不破坏遗留代码及边界情况。这就是getInitialProps的情况,它几乎和getServerSideProps有着一样的用法行为。

getServerSidePropsgetInitialProps那两者有什么不同点吗?
老的getInitialProps方法和新的getServerSideProps方法最大的区别点在于当用户点击链接访问不同区域时,如何在转换过程中使用该功能。
getInitialProps这边转换在服务端初始化页发生,在客户端会再次执行,然而如果有涉及到数据库之类的逻辑,在客户端这边是不能直接访问的,这将会是发生问题。
【个人补充:这块就是确保同构的一致性,因为服务端没有DOM,所以不能处理事件等DOM相关行为,只能输出HTML String。因此相同的代码客户端需要再跑一次,把DOM的行为再加上,这样才能输出一张功能完整的页面供用户使用,这也是同构渲染的意义所在】
举个例子:

// Import a User model
import User from "../models/User"
function Page({ User }) {
    return <div>Username: {User.username}</div>
  }

  Page.getInitialProps = async (ctx) => {
    // Get user id
    const User = await User.findOne(ctx.query.id)
    // return props
    return {
        User
    }
  }

  export default Page

在这个代码片段中,页面初始化可以通过User数据模型获取用户信息,然而在客户端当User数据模型不可使用的时候会操作失败。
作为其中一个解决方案,可以使用Next.js 自带的API服务进行端点接口提供,但这样比在服务端这边User数据模型直接访问数据库效率要低很多。
另外一个解决方案,可以使用getServerSideProps方法,该方法会在服务端初始化页面执行,在客户端页面转换阶段,getServerSideProps会在服务端生成一个API 调用接口,会再次运行处理逻辑并返回JSON格式作为结果。
通过做此更改,我们修复了getInitialProps在切换时产生的问题。下面这个例子,可以访问数据库的同时,在初始页面的时候也不会报错

// Import a User model
import User from "../models/User"
function Page({ User }) {
    return <div>Username: {User.username}</div>
  }
  export async function getServerSideProps(context) {
    // Get user id
    const User = await User.findOne(ctx.query.id)
    return {
      props: {User}, // will be passed to the page component as props
    }
  } 

  export default Page

那么什么情况下用哪个合适呢?
如果你通过Next.js创建了一个新的应用,那么你没有理由要使用遗留方法getServerSideProps,因为getServerSidePropsgetStaticProps方法会更加实用,语义更加明确。
在这篇文章,我们将阐明getServerSidePropsgetInitialProps的区别,通过看一个例子来看看我们是如何解决getServerSideProps解决getInitialProps中的切换问题。
我希望你喜欢这篇文章,如果你有任何问题,请留言。要了解更多关于Next.js和其他元框架的信息,请务必查看这篇比较Next.js和Remix的文章。
LogRocket是一个使得Next.js应用完全可视化的工具。
调试Next应用程序可能很困难,特别是当用户遇到难以再现的问题时。如果您对监视和跟踪状态、自动显示JavaScript错误、跟踪缓慢的网络请求和组件加载时间感兴趣。
LogRocket就像一个网页和app的DVR录制机,录制Next.js应用程序上发生的一切,您不必猜测问题发生的原因,而是可以聚合和报告问题发生时应用程序的状态,LogRocket还监视应用程序的性能,报告客户端CPU负载、客户端内存使用情况等指标。
LogRocket Redux中间件包在用户会话中增加了一个额外的可见层。LogRocket记录Redux存储中的所有操作和状态。

原文:https://blog.logrocket.com/getinitialprops-vs-getserversideprops-nextjs/

补充总结:

在 Next.js 中,getInitialPropsgetServerSideProps 是两个用于获取服务器端数据和传递给页面的 Prop(属性)的函数。它们之间有一些关键区别:

1. getInitialProps

getInitialProps 是一个较早的 Next.js 版本中引入的功能。它是一个异步函数,可以从服务器端和客户端请求数据。它适用于页面级别的组件,即 pages 目录中的文件。它的签名如下:

static async getInitialProps(ctx) {
  // Fetch data
}

特点:

  • 它在服务器端和客户端上都会执行
  • 不能在非页面组件中使用
  • 仅在初始化页面加载时运行,不在客户端的路由切换时运行
  • 与 _app.js、_document.js 和 _error.js 中的 getInitialProps 结合使用时,需注意它们之间的关系和执行顺序

注意: 从 Next.js 9.3 版本开始,推荐使用 getStaticPropsgetServerSideProps 替代 getInitialProps

2. getServerSideProps

getServerSideProps 是在 Next.js 9.3 及更高的版本中引入的新功能,用于服务器端的数据请求。与 getInitialProps 不同,getServerSideProps 只在服务器端运行。它的签名如下:

export async function getServerSideProps(ctx) {
  // Fetch data
}

特点:

  • 仅在服务器端执行,不在客户端执行
  • 适用于需要每次展示最新数据的页面
  • 在初始化页面加载时运行,并在客户端的路由切换时重新运行
  • 不能在非页面组件中使用

总结:

  • 当只在服务器端获取数据,且每次请求都需要获取新数据时,使用 getServerSideProps
  • 当数据在服务器端和客户端都需要获取时,可以继续使用 getInitialProps,但要注意 Next.js 推荐使用 getStaticPropsgetServerSideProps

推荐使用 Next.js 的新功能 getStaticPropsgetServerSideProps,因为它们提供了更明确的服务器端数据请求方式,且可以更好地配合新的增量静态生成(ISR)功能。如果可以,尽量避免继续使用 getInitialProps

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容