JackyLove 的技术人生

人生艰难,唯有一技傍身才能慢慢走向通途。个人博客,记录生活,分享技术,记录成长。专注全栈技术,next技术。

第78章—面试篇-常见面试题及解析(1)

首次发表于 2024-07-29, 更新于 2024-07-29

1. Next.js 与 React

1.1. 常见问题

Next.js 与 React 技术选型的区别在哪里?使用 Next.js 比使用 React 有什么优势?

1.2. 解题思路

考察对 Next.js 和 React 的基本理解,其实 React 和 Next.js 的差别说“多”你可以列很多点,说“少”一句话也可以概括。所以重点不在于一条条列出不同点,表明你对两个框架的极致理解。

只需要大致说出最核心的区别,然后引申到比如“如何进行技术选型的选择?”或者自己的实际使用经历即可,最好在使用经历中埋下一些引导词,吸引面试官继续提问。

1.3. 八股答案

React 是一个用于构建用户界面的 JavaScript 库,它提供了 JSX 语法用于快速创建可复用的组件,并基于数据驱动的理念,建立单向数据流,简化了调试流程。底层则使用虚拟 DOM 和 Fiber 优化渲染性能。

Next.js 是一个基于 React 的用于构建全栈 Web 应用程序的生产框架。不仅可以使用 React 构建用户界面,还可以使用 Next.js 的各种功能和优化,使用户可以专注于构建应用程序,而不是花时间进行配置。

从使用的角度来看,React 关心的是状态管理和渲染,所以 React 的定位是一个库,通常还要搭配其他库一起使用。而 Next.js 则是一个大而全的框架,提供了开箱即用的脚手架,内置了各种优化组件和 API,Next.js v12 前实现了 SSR、SSG、ISR,而 Next.js v13 则基于 React Server Components 进行了重构,实现了 App Router、服务端组件和客户端组件、Server Actions、路由处理程序、中间件、内置各种 CSS 支持等功能。

使用 Next.js 的优势:

  1. 开箱即用的脚手架,零配置,支持 TypeScipt、ESLint、Tailwind.css 等常用技术选型,快速上手使用
  2. 内置各种优化组件,如图片、字体、脚本、链接等
  3. SEO 友好,基于服务端组件和客户端组件进行客户端渲染和服务端渲染,自动进行静态、动态路由优化,支持流式传输
  4. 基于文件的路由系统,支持布局、嵌套路由、加载状态、错误处理等以及各种高级路由功能,解决了复杂场景下的路由实现
  5. 内置多种 CSS 支持,如 CSS Modules、Tailwind CSS 和 CSS-in-JS

1.4. 回答参考

React 是一个纯前端库,而 Next.js 是基于 React 的全栈框架。

传统的前后端分离架构,虽然带来了“前端”的繁荣,但也带来了诸如 SEO 优化、首屏加载时间过长等问题,由此诞生了 Next.js,主要解决了服务端渲染以及内置了各种全栈开发会用到的组件、工具、API 等,提高了开发效率。(简明扼要的说明区别就好)

我大概是 2020 年接触的 Next.js,这几年也用 Next.js 做过一些项目,我对 Next.js 的理解就是大而全的全栈框架,既可以写页面,又可以写接口,一把梭全部搞定。(假装自己这几年持续有关注,一直在学习实践)

我认为 Next.js 作为一个生产框架,追求的就是一个字——“快”。(说出自己的真实感受,有自己的理解,而不是直接背答案,吸引面试官)

当然这个“快”有两方面的解释,一个是应用程序本身性能上的快,比如它从 SSR 到 SSG 到 ISR 以及 v13 基于 RSC 进行重构,推出了 App Router,我理解都是为了进一步提升应用程序的性能。(抛出技术名词,吸引面试官提问如 SSR 原理、App Router、RSC 方向)

第二个“快”是开发效率上的快,比如它提供开箱即用的脚手架,内置各种优化后的组件比如图片、字体等,像图片组件我也可以自己写,自己实现懒加载,但是 Next.js 直接内置了,这就便捷了很多。此外 Next.js 还内置了各种 CSS 支持,比如 CSS Module,Tailwind CSS,当然我个人只用 Tailwind CSS。

还有 App Router,除了简化常见的加载状态、错误状态处理等,还提供了拦截路由、平行路由等高级路由功能,解决了特定场景下的路由问题。加上 Next.js 背靠 Vercel,部署也很方便,我基本做全栈的个人项目都是用 Next.js。(抛出一堆技术名词,继续吸引面试官提问,尽可能让面试官在自己熟悉的技术领域提问,而不要回到他擅长但你不一定擅长的技术领域)

2. 服务端渲染

2.1. 常见问题

什么是服务器端渲染(SSR)?SSR 的原理是什么?了解渐进式渲染和流式渲染嘛?

2.2. 解题思路

考察对 SSR 实现原理的理解,这种对原理的考察都是为了了解面试者的学习深度,是否在实现应用之外,有对实现原理有所了解。为了表达出自己真实研究过,可以引申到自己的实际研究经历。

2.3. 八股答案

服务器端渲染 (SSR) 是一种网页渲染技术,它在服务器端生成完整的 HTML 页面,然后将页面发送给浏览器。与客户端渲染 (CSR) 不同,SSR 在服务器端完成页面渲染,浏览器只需解析和显示 HTML 页面即可。

SSR 的工作原理:当用户请求一个页面时,服务器会执行以下步骤:

  1. 获取页面数据和模板。
  2. 使用数据和模板生成完整的 HTML 页面。
  3. 将 HTML 页面发送给浏览器。
  4. 浏览器解析和显示 HTML 页面。

SSR 的优势:

  1. 更快的首屏加载速度: 由于浏览器无需等待 JavaScript 下载和执行,SSR 可以提供更快的首屏加载速度。
  2. 更好的 SEO: 搜索引擎可以更容易抓取和索引 SSR 生成的页面,从而提高网站的 SEO 排名。
  3. 更易于访问: SSR 生成的页面无需 JavaScript 即可访问,这对于禁用 JavaScript 的用户或低带宽连接的用户来说非常有用。

流式渲染是指将 HTML 文档分块传输给客户端,客户端收到每一段内容时进行分批渲染。与一次性发送整个 HTML 文档相比,流式渲染可以更早地向用户展示内容,提升页面加载速度和用户体验。

流式渲染适用于各种需要快速展示内容的场景,例如:

  1. 大型电商网站的商品列表页面
  2. 社交媒体的动态消息流
  3. 实时数据更新的仪表盘

流式渲染可以通过多种技术实现,例如:

  1. HTTP/1.1 的分块传输编码
  2. WebSockets

2.4. 回答参考

所谓服务端渲染就是……在服务端进行渲染……

这样说好像有点草率……不过服务端渲染不就是这个意思吗……(这看似草率的回答说明我可没有背八股……)

其实我以前用 Webpack 和 React 实现过 React SSR (参考《源码篇 | 手写 React SSR》,至于你是否真的实现过,你讲得清原理就可以说成自己真的实现过)。

其实 React 的 react-dom/server 提供了服务端渲染的 API,像 renderToString,当然也有用于流式渲染的 renderToPipeableStream 等 API,服务端渲染成具体的 HTML 后传给客户端,同时 React 提供了用于客户端的 hyrateRoot API 进行水合,实现客户端事件的绑定,就这样完成了一个基本的 SSR。

当然这是最早期的 SSR 实现,虽然解决了 SEO 等问题,但还有很多问题。(SSR 没有什了不起的,且听我和你逼逼)

首先,SSR 需要在服务端完全渲染完毕后才能传给客户端。其次,为了保持服务端组件树和客户端组件树一致,所有的组件代码都要打包到客户端 bundle 中。最后,一旦开始水合,整个过程是阻塞的,必须全部完成水合后,用户才能开始操作。

为了缓解这个问题,就出现了 Streaming SSR,也就是您问的流式渲染。React 用的是 Suspense 组件来实现的,Suspense 的巧妙之处就在于它在渲染的时候先用一个占位符替代,等数据获取完毕的时候,在流式传输给 HTML,用脚本替换之前的占位符,从而实现渐进式渲染内容。

这个实现很好,在我看来,解决了 2 个问题:

一个是组件并不一定非要在服务端渲染完毕再传输给客户端组件,可以边渲染边传输,体验更好。第二个是选择性水合,页面分多个部分进行水合,甚至可以根据用户操作提高水合的优先级。

但问题并没有完全解决,客户端该下载的代码并没有少,所有的组件都需要水合,哪怕它只是需要静态渲染并不涉及客户端操作,也要水合一遍,这就浪费了性能。目前的终极解决方案就是 RSC。

……(下接第三个问题)

注:仅仅看文字有点在向面试官科普知识的感觉,实际上跟你交流的语气有很大关系,社招招的是平等相处的同事,卑微的语气没有什么用,但也不要心高气傲,平心静气的与面试官分享你的看法和思考即可。

这里分享的是 SSR 的发展,相同的问题你也可以引申到自己使用 SSR 的过程中遇到的问题等。

3. React Server Components

3.1. 常见问题

RSC 的实现是为了解决什么问题?说说你对 RSC 的理解?

3.2. 解题思路

依然考察的是对原理的理解,毕竟 RSC 是 Next.js v13 的实现基础,如果没有接触过 React,可能对 RSC 感到陌生。

3.3. 八股答案

RSC 是 React 设计的一种新架构,这种方法旨在利用服务器和客户端环境的优势,实现用户体验、易于维护和高性能的三角平衡。

使用服务端组件有很多好处:

  1. 数据获取:通常服务端环境(网络、性能等)更好,离数据源更近,在服务端获取数据会更快。通过减少数据加载时间以及客户端发出的请求数量来提高性能
  2. 安全:在服务端保留敏感数据和逻辑,不用担心暴露给客户端
  3. 缓存:服务端渲染的结果可以在后续的请求中复用,提高性能
  4. bundle 大小:服务端组件的代码不会打包到 bundle 中,减少了 bundle 包的大小
  5. 初始页面加载和 FCP:服务端渲染生成 HTML,快速展示 UI
  6. Streaming:服务端组件可以将渲染工作拆分为 chunks,并在准备就绪时将它们流式传输到客户端。用户可以更早看到页面的部分内容,而不必等待整个页面渲染完毕

3.4. 回答参考

RSC 是一个很难理解的概念,至少当时卡了我很久,后来我还是自己实现了一个简单的 RSC,才理解了一些。(我可不是背答案,我真的研究过)

我觉得 RSC 它主要解决了 2 个问题:

第一个是 bundle size,将组件拆分为客户端组件和服务端组件后,服务端组件在服务端渲染即可,客户端只需要最后的渲染结果,所以服务端组件的依赖项不需要打包到客户端 bundle 中,这就减少了客户端 JS 的大小。

第二个是局部渲染和水合,传统的 SSR 实现中,所有的组件代码都要下载到客户端以进行水合,但是在 RSC 中,因为明确进行了组件区分,所以可以做到只有客户端组件进行水合。在后续导航的时候,RSC 将组件的渲染放在服务端,并渲染成特殊格式的 RSC Payload,根据 RSC Payload,客户端可以进行局部渲染和更新,由此实现了状态的保持。

不过这里我说的是纯 RSC,跟 Next.js 的实现还不一样,Next.js 更像是 RSC、SSR、Streaming 的结合。比如所有组件,无论客户端组件还是服务端组件都会在服务端进行渲染,Streaming 流式传输 HTML。后续导航的时候,RSC Payload 也针对流进行了优化,同样实现了 Streaming。RSC 和 SSR 相辅相成,共同提升了应用的性能。

总结

我的答案也不一定对,也不一定符合你对“面试答案”的期望,欢迎在评论区补充自己的回答!

我想告诉你的是,不用拘泥于问题本身的答案,在问题之外,可以引申到自己的真实见解和思考,增加真实度。可以引申到自己的项目经历,展现个人品质,可以引申到相似的问题,展现自己的思考。“高分答案”有很多。

© Copyright 2025 JackyLove 的技术人生. Powered with by CreativeDesignsGuru