【青训营】Next.js课程理论小结(不完整)

293 阅读6分钟

这是我参与「第五届青训营 」笔记创作活动的第8天

1.CSR,SSR,SSG介绍

CSR(客户端渲染):页面的渲染过程在浏览器端完成,服务器端只负责返回HTML模板,由浏览器加载JavaScript,然后再使用JavaScript动态生成页面。

SSR(服务器端渲染):页面的渲染过程在服务器端完成,完整的HTML页面直接返回给浏览器,浏览器端没有渲染过程,快速响应,有利于SEO。

SSG(静态生成):通过在构建阶段生成静态页面,服务器只返回静态页面,不再需要服务器端渲染。

区别:

  1. 消耗服务器资源:由于SSR需要在服务端生成完整的HTML页面,才能展现给用户,因此它需要在服务端执行JavaScript代码,动态生成页面,这样需要更多的服务器资源,比如更多的内存和CPU使用,也会造成服务器负载增加。

  2. 加载速度慢:由于SSR需要在服务端生成完整的HTML页面,再返回给客户端,因此响应速度相对较慢。同时,由于在服务端生成页面的过程中,还需要加载模板、数据等资源,进一步降低了生成页面的速度。

  3. SEO友好:SSR生成的页面包含完整的HTML内容,因此在搜索引擎抓取页面内容时,可以得到更多的信息。而CSR生成的页面则只包含部分内容,因此不够友好。

  4. 性能:因为SSR需要在服务端生成页面,页面内容已经存在,因此页面加载速度较快,但是SSR生成的页面需要通过网络传输到客户端,因此对带宽的消耗较大,而且还需要客户端对生成的页面进行渲染,因此对客户端的性能也有一定的影响。而CSR的性能较高,因为它在客户端进行页面渲染,不需要通过网络传输,对带宽的消耗较小,且对客户端的性能影响较小。

  5. 用户体验:SSR生成的页面可以在客户端立即呈现,但是页面生成速度较慢,可能导致用户体验不够好。而CSR生成的页面在加载时可能存在空白,用户体验不够流畅。

  6. 支持动态数据:SSR生成的页面可以动态生成,支持动态数据,但是对于每个请求都需要生成一次,因此不太适合大量请求的场景。而CSR生成的页面只需要在客户端加载一次,然后通过Ajax请求获取数据,因此更适合大量请求的场景。

  7. 易开发:SSR开发过程比较复杂,需要在服务端渲染页面,维护服务端的代码,需要熟练掌握后端技术。而CSR开发过程比较简单,只需要在客户端使用JavaScript编写,不需要维护服务端代码,易于学习。

因此,在选择SSR, CSR, SSG等技术时,需要根据实际项目需求进行选择。一般来说,对于加载速度要求高、数据不太动态的项目,可以选择SSR或SSG;对于大量请求、数据动态的项目,可以选择CSR。

2.同构概念

"同构"是指在服务端和客户端同时运行相同的代码。

SSR的原理是,在服务端运行React代码生成HTML,并将HTML作为响应发送到客户端。客户端接收到HTML后,再加载JavaScript代码,使页面实现交互效果。

实现同构的操作步骤如下:

  1. 在服务端渲染React组件,生成HTML
  2. 将HTML作为响应发送到客户端
  3. 客户端接收到HTML后,加载JavaScript代码
  4. JavaScript代码获取数据并更新页面

这样,客户端和服务端都运行了相同的代码,实现了同构的效果。 这里以Next.js为例,展示如何使用同构的代码实现SSR。

以下是服务端渲染的代码:

javascript
import React from 'react'
import Head from 'next/head'

const Home = () => {
  return (
    <div>
      <Head>
        <title>Home Page</title>
        <meta name="viewport" content="initial-scale=1.0, width=device-width" />
      </Head>
      <h1>Welcome to the Home Page</h1>
      <p>This is a sample Next.js application.</p>
    </div>
  )
}

export default Home

以下是客户端渲染的代码:

javascript
import React from 'react'
import Head from 'next/head'

const Home = () => {
  return (
    <div>
      <Head>
        <title>Home Page</title>
        <meta name="viewport" content="initial-scale=1.0, width=device-width" />
      </Head>
      <h1>Welcome to the Home Page</h1>
      <p>This is a sample Next.js application.</p>
    </div>
  )
}

export default Home

这段代码演示了如何使用React和Next.js在服务端和客户端同时运行相同的代码,从而实现同构。

3.脱水和注水

以下是一个简单的代码示例,使用 React 和 Next.js 实现脱水注水:

javascript
// 首先,在服务端进行首屏渲染:
import React from 'react'
import App from './app'

export default function Home() {
  return (
    <App />
  )
}

// 然后,客户端代码进行“脱水”,即把服务端渲染的内容重新激活:
import React from 'react'
import { hydrate } from 'react-dom'
import App from './app'

hydrate(<App />, document.getElementById('root'))

在此代码示例中,首先在服务端执行 React 组件的渲染,并将结果呈现给用户。然后,客户端代码会读取服务端的结果,使用 React DOM 库的 hydrate 方法进行“脱水”。这样,我们就实现了高效的首屏加载体验,同时又保证了客户端交互性。

“注水”指的是客户端加载完成后,将 React 应用的状态进行“注入”,使其在浏览器中正常运行。具体实现方式是通过在首屏加载完成后,通过 JavaScript 调用 React DOM 库的方法,将 React 应用的状态“注入”到页面中。

以下是一个简单的代码示例,使用 React 实现注水:

javascript
import React from 'react'
import ReactDOM from 'react-dom'
import App from './app'

// 客户端代码进行注水:
ReactDOM.render(<App />, document.getElementById('root'))

在此代码示例中,通过调用 React DOM 库的 render 方法,将 React 应用的状态“注入”到页面中,使其正常运行。

补充:props包裹

Props 包裹是指在 React 组件中使用 props 传递数据的过程。

props 可以被视为父组件对子组件的数据传递。父组件通过属性的形式向子组件传递数据,子组件可以使用这些数据渲染 UI。

下面是一个简单的 props 包裹的代码示例:

javascript
// 父组件
import React from 'react';
import ChildComponent from './ChildComponent';

const ParentComponent = () => {
  return (
    <ChildComponent name="John Doe" />
  );
};

export default ParentComponent;

// 子组件
import React from 'react';

const ChildComponent = (props) => {
  return (
    <div>
      <h1>Hello, {props.name}!</h1>
    </div>
  );
};

export default ChildComponent;

在上面的代码示例中,父组件通过属性的形式向子组件传递了 name 属性,子组件通过使用 props.name 访问这个属性,并将其作为字符串渲染出来。