React 服务端渲染框架:Next.js

举报
楚楚冻人玥玥仙女 发表于 2021/11/19 01:27:46 2021/11/19
【摘要】 React 服务端渲染框架:Next.js 文章出处: 拉 勾 大前端 高薪训练营 练习代码地址 Next.js是React服务端渲染应用框架.用于构建SEO友好的SPA应用...

React 服务端渲染框架:Next.js

文章出处: 拉 勾 大前端 高薪训练营

练习代码地址

Next.js是React服务端渲染应用框架.用于构建SEO友好的SPA应用.

  1. 支持两种预渲染方式,静态生成和服务器端渲染.
  2. 基于页面的路由系统,路由零配置
  3. 自动代码拆分.优化页面加载速度.
  4. 支持静态导出,可将应用导出为静态网站.
  5. 内置CSS-in-JS库styled-jsx
  6. 方案成熟,可用于生产环境,世界许多公司都在使用
  7. 应用部署简单,拥有专属部署环境Vercel,也可以部署在其他环境.

一、创建 Next.js 项目

创建: npm init next-app next-guide
运行: npm run dev
访问: localhost:3000
临时安装 create-next- app 用于创建 Next.js 项目。

二、 基于页面的路由系统

1. 创建页面

在Next.js中,页面是被放置在pages文件夹中的React组件.
组件需要被默认导出.
组件文件中不需要引入React.

pages/list.js

export default function List () {
  return (
    <div>List Page</div>
  )
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

访问地址是:http://localhost:3000/list
页面地址与文件地址是对应的关系.

2. 页面跳转

Link 组件默认使用 JavaScript 进行页面跳转.即 SPA 形式的跳转.
如果浏览器中 JavaScript 被禁用.则使用链接跳转.
Link 组件中不应添加除 href 属性以外的属性,其余属性添加到 a 标签上.
Link 组件通过预取(在生产中)功能自动优化应用程序以获得最佳性能.

import Link from 'next/link'

export default function Home() {
  return <div>
    Index Page works
    <Link href="/list"><a>Jump to List Page</a></Link>
  </div>
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

三、静态资源、元数据和 CSS

1. 静态资源

应用程序根目录中的 public 文件夹用于提供静态资源。

通过以下形式进行访问:

public/images/1.jpg -> /images/1.jpg
public/css/base.css -> /css/base.css

2. 修改页面元数据

通过 Head 组件修改元数据

import Head from 'next/head'

<>
  <Head>
    <title>next app</title>
  </Head>
</>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

3. CSS 样式

3.1 内置 styled-jsx

在 Next.js 中 内置了 styled-jsx, 它是一个 CSS-in-JS 库,允许在 React 组件中编写 CSS, CSS 仅作用于组件内部。

export default function Home() {
  return <>
    <Head>
      <title>Index Page</title>
    </Head>
    <div>
      Index Page works
      <Link href="/list"><a className="demo">Jump to List Page</a></Link>
      <img src="/images/1.jpeg" height="100" />
    </div>
    <style jsx>{`
      .demo {
        color: red
      }
    `}</style>
  </>
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
3.2 CSS 模块

通过使用 CSS 模块功能,允许将组件的 CSS 样式编写在单独的 CSS 文件中.
CSS 模块约定样式文件的名称必须为"组件文件名称.module.css"

pages/list.js

import Head from "next/head";
import style from './list.module.css'

export default function List () {
  return (
    <>
      <Head>
        <title>List Page</title>
      </Head>
      <div className={style.demo}>List Page</div>
    </>
  )
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

page/list.module.css

.demo {
  color: green;
  font-size: xx-large;
}

  
 
  • 1
  • 2
  • 3
  • 4
3.3 全局样式文件
  1. 在 pages 文件夹中新建 _app.js 文件并加入如下代码
  2. 在项目根目录下创建 styles 文件夹,并在其中创建 global.css
  3. 在 _app.js 中通过 import 引入 global.css.
  4. 重新启动开发服务器

pages/_app.js

import '../styles/globals.css'

function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />
}

export default MyApp

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

styles/globals.css

html,
body {
  padding: 0;
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
    Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
  background: tomato;
}

a {
  color: inherit;
  text-decoration: none;
}

* {
  box-sizing: border-box;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

四、预渲染

1. 预渲染概述

预渲染是指数据和 HTML 的拼接在服务器端提前完成。
预渲染可以使 SEO 更加友好。
预渲染会带来更好的用户体验,可以无需运行 JavaScript 即可查看应用程序 UI 。

2. 预渲染的两种形式

在 Next.js 中支持两种形式的预渲染:静态生成和服务器端渲染。
静态生成和服务器端渲染是生成 HTML 的时机不同。
静态生成:静态生成是在构建时生成 HTML 。以后的每个请求都共用构建时生成好的 HTML 。
服务器端渲染:服务器端渲染是在请求时生成 HTML 。每个请求都会重新生成 HTML 。

3. 两种预渲染方式的选择

Next.js 允许开发者为每个页面选择不同的预渲染方式,不同的预渲染方式拥有不同的特点,应根据场景进行渲染。
但建议大多数页面建议使用静态生成。
静态生成一次构建,反复使用,访问速度快,因为页面都是事先生成好的。
适用场景:营销页面、博客文章、电子商务产品列表、帮助和文档。
服务器端渲染访问速度不如静态生成快,但是由于每次请求都会重新渲染,所以适用数据频繁更新的页面或页面内容随请求变化而变化的页面。

4. 无数据和有数据的静态生成

如果组件不需要在其他地方获取数据,直接进行静态生成。
如果组件需要在其他地方获取数据,在构建时 Next.js 会预先获取组件需要的数据,然后再对组件进行静态生成。

5. 静态生成 getStaticProps

getStaticProps 方法的作用是获取组件静态生成需要的数据。并通过 props 的方式将数据传递给组件。
该方法是一个异步函数,需要在组件内部进行导出。
在开发模式下, getStaticProps 改为在每个请求上运行。
在生产模式下, getStaticProps 只会在构建的时候执行,而每次访问 /list 页面时不会再执行 getStaticProps 方法。

pages/list.js

import Head from "next/head";
import style from './list.module.css'
import { readFile } from "fs";
import { promisify } from "util";
import { join } from "path";

const read = promisify(readFile)

export default function List ({data}) {
  return (
    <>
      <Head>
        <title>List Page</title>
      </Head>
      <div className={style.demo}>List Page</div>
      <div>{data}</div>
    </>
  )
}

export async function getStaticProps () {
  let data = await read(join(process.cwd(), 'pages', '_app.js'), 'utf-8')
  console.log(data) // 会在 node 环境下输出,这个函数会在构建时运行
  return {
    props: {
      data
    }
  }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

6. 服务器端渲染 getServerSideProps

如果采用服务器端渲染,需要在组件中导出 getServerSideProps 方法

将 list.js 中的 getStaticProps 方法 改成 getServerSideProps 方法,其中 getServerSideProps 还有个参数为 context.

开发模式下不执行 getServerSideProps 方法。

生产模式下:
运行npm run build生成 .next 文件夹,可以看到 list 页面不会生成 HTML 页面。
然后运行npm start 启动生产环境的代码,访问 /list 页面, node 控制台会输出 getServerSideProps 方法中的打印语句。
因为使用了 getServerSideProps 则表示采用服务端渲染,而不是静态生成,所以每次访问都会执行 getServerSideProps 方法。

6. 基于动态路由的静态生成

  1. 基于参数为页面组件生成HTML页面,有多少参数就生成多少HTML页面
  2. 在构建应用时,先获取用户可以访问的所有路由参数,再根据路由参数获取具体数据,然后根据数据生成静态HTML.

7. 实现基于动态路由的静态生成

  1. 创建基于动态路由的页面组件文件,命名时在文件名称外面加上 [],比如 [id].js
  2. 导出异步函数 getStaticPaths, 用于获取所有用户可以访问的路由参数
export async function getStaticPaths () {
  // 此处获取所有用户可以访问的路由参数
  return {
    // 返回固定合适的路由参数
    paths: [{params: {id: 1}}, {params: {id: 2}}],
    // 当用户访问的路由有参数没有在当前函数中返回时,是否显示 404 页面, false 表示显示, true 表示不显示
    fallback: false
  }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  1. 导出异步函数 getStaticProps, 用于根据路由参数获取具体的数据
export async function getStaticProps ({params}) {
  // params -> {id: 1}
  // 此处根据路由参数获取具体数据
  return {
    // 将数据传递到组件中进行静态页面的生成
    props: {}
  }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

注: getStaticPaths 和 getStaticProps 只运行在服务器端,永远不会运行在客户端,甚至不会被打包到客户端 JavaScript 中,意味着这里可以随意写服务器端代码,比如查询数据库。

8. 自定义 404 页面

要创建自定义 404 页面,需要在 pages 文件夹中创建 404.js 文件

export default function Error () {
  return <div>404 ~</div>
}

  
 
  • 1
  • 2
  • 3

五、API Routes

1. 如何实现 API Routes

  1. 在 pages/api 文件夹中创建 API Routes 文件。比如 user.js
  2. 在文件中默认导出请求处理函数,函数有两个参数, req 为请求对象, res 为响应对象
export default function (req, res) {
  res.status(200).send({id: 1, name: 'TOM'})
}

  
 
  • 1
  • 2
  • 3

注:当前 API Routes 可以接受任何 Http 请求方法。

  1. 访问 API Routes: localhost:3000/api/user
    不要在 getStaticPaths 或 getStaticProps 函数中访问 API Routes, 因为这两个函数就是在服务器端运行的,可以直接写服务器端代码。

六、movie 项目

1. 创建项目

npm init next-app movie
cd movie
npm i @chakra-ui/react @emotion/react @emotion/styled framer-motion
npm install react-icons
npm install @emotion/babel-preset-css-prop -D
npm install @babel/core
npm run dev

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

访问: localhost:3000

pages/_app.js

// import '../styles/globals.css'

import { ChakraProvider } from '@chakra-ui/react'
import theme from '@chakra-ui/theme'

function MyApp({ Component, pageProps }) {
  return <ChakraProvider theme={theme}>
    <Component {...pageProps} />
  </ChakraProvider>
}

export default MyApp

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

2. 启动数据服务

npm install
npm run dev

  
 
  • 1
  • 2

数据服务地址IP: localhost:3005

在 axiosConfig.js 文件中导出 baseURL = 'http://localhost:3005'

3. 编写代码

4. 生成静态文件

npm run export
serve out

  
 
  • 1
  • 2

访问: localhost:5000

5. 自定义 next 服务

package.json

    "mydev": "nodemon server/index.js",

  
 
  • 1

server/index.js

const express = require('express')
const next = require('next')

const dev = process.env.NODE_ENV !== 'production'

const app = next({dev})

const handler = app.getRequestHandler()

// prepare 方法是准备一下 next 应用
app.prepare().then(() => {
  const server = express()

  server.get('/hello', (req, res) => {
     res.send('Hello Next.js')
  })

  server.get('*', (req, res) => {
    handler(req, res)
  })

  server.listen(3000, () => console.log('服务器启动成功,请访问: http://localhost:3000'))
})

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

6. 部署到 Vercel

我先将数据服务部署到了我的服务器,地址是 http://jiailing.com:3005, 这个地址要写到 axiosConfig.js 文件里,给 baseURL 变量。

然后在 GitHub 上创建一个仓库,将这个项目代码导入到 GitHub 仓库。然后登陆 https://vercel.com/ 选择 GitHub 的这个仓库进行部署。

文章来源: blog.csdn.net,作者:爱玲姐姐,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/jal517486222/article/details/112798540

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。