Next.js学习与实战

Next.js

github Next.js相关代码

一.介绍

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

二.创建 Next.js 项目

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

三.基于页面的路由系统

创建页面

  • 在Next.js中,页面是被放置在pages文件夹中的React组件
  • 组件需要被默认导出
  • 组件文件中不需要引入React
  • 页面地址与文件地址是对应的关系
  • index页面可以直接通过/访问

页面跳转

  • 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>
}

四.静态资源、元数据和 CSS

静态资源

  • 应用程序根目录中的 public 文件夹用于提供静态资源。
  • public/images/1.jpg直接用/images/1.jpg访问
  • public/css/base.jpg直接用/css/base.css访问

通过 Head 组件修改元数据

import Head from 'next/head'
function List() {
     
  return (
    <>
      <Head>
        <title>list page</title>
      </Head>
      <div>这是list页面</div>
    </>
  )
}
export default List

在Next应用中添加样式的方式

内置 styled-jsx

<>
  <Link href="/list">
    <a className="demo">jump to list page</a>
  </Link>
  <style jsx>{
     `
    .demo {
      color : red
    }
  `}
  </style>
</>

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>
    </>
  )
}
/* page/list.module.css */
.demo {
     
  color: green;
  font-size: xx-large;
}

添加全局样式文件

  • 在 pages 文件夹中新建 _app.js 文件并加入如下代码
  • 在项目根目录下创建 styles 文件夹,并在其中创建 global.css
  • 在 _app.js 中通过 import 引入 global.css.
  • 重新启动开发服务器
import '../styles/globals.css'
function MyApp({
      Component, pageProps }) {
     
  return <Component {
     ...pageProps} />
}
export default MyApp

五.预渲染

概述

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

预渲染的两种形式

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

如何选择

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

无数据静态生成

  • next默认使用的是静态生成
    • npm run build之后在.next下生成的pagesstatic就是无数据生成
  • 如果组件不需要外部数据,直接进行静态生成。

有数据静态生成getStaticProps

  • 有数据静态生成是在组件需要外部数据时,在构建过程中 Next.js 会预先获取组件需要的数据,然后再对组件进行静态生成。

  • getStaticProps 方法的作用是获取组件静态生成需要的数据。并通过返回 props 的方式将数据传递给组件。

  • 该方法是一个异步函数,需要在组件内部进行导出

  • 开发模式下, getStaticProps在每个请求上运行

  • 生产模式下, getStaticProps 只会在构建的时候执行,而每次访问 /list 页面时不会再执行 getStaticProps 方法。

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

const read = promisify(readFile)

function List({
     data}) {
     
  return (
    <>
      <Head>
        <title>list page</title>
      </Head>
      <div className={
     styles.demo}>这是list页面</div>
      <div>{
     data}</div>
    </>
  )
}

export default List

export async function getStaticProps () {
     
  let data = await read(join(process.cwd(),'pages','_app.js'),'utf-8')
  console.log(data)
  return {
     
    props : {
     
      data
    }
  }
}

服务器端渲染 getServerSideProps

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

    • 将 list.js 中的 getStaticProps 方法 改成 getServerSideProps 方法,其中 getServerSideProps 还有个参数为 context.
    • context.query能拿到客户端向服务端的请求参数,比如在浏览器url中的参数
  • 开发模式下每次访问都会执行 getServerSideProps 方法。

  • 生产模式下每次访问都会执行 getServerSideProps 方法:

    • 运行npm run build生成 .next 文件夹,可以看到 list 页面不会生成 HTML 页面(说明不是静态生成)。
    • 然后运行npm start 启动生产环境的代码,访问 /list 页面, node 控制台会输出 getServerSideProps 方法中的打印语句。
    • 因为使用了 getServerSideProps 则表示采用服务端渲染,而不是静态生成,所以每次访问都会执行 getServerSideProps 方法。
// export async function getStaticProps () {
     
export async function getServerSideProps (context) {
     
  let data = await read(join(process.cwd(),'pages','_app.js'),'utf-8')
  console.log(context.query) //能拿到客户端向服务端的请求参数,比如在浏览器url中的参数
  console.log('hello')
  return {
     
    props : {
     
      data
    }
  }
}

基于动态路由的静态生成

  1. 创建基于动态路由的页面组件文件,命名时在文件名称外面加上 [],比如 [id].js

  2. 导出异步函数 getStaticPaths,用于获取所有用户可以访问的路由参数

  3. 导出异步函数 getStaticProps,用于根据路由参数获取具体的数据

  4. npm run build 会根据getStaticPaths返回的paths 去生成对应的html静态文件

    • 生成的html静态文件名就是文件命名对应paths参数的值
    • 如下会生成1.html 2.html
  5. getStaticPaths 和 getStaticProps 只运行在服务器端,永远不会运行在客户端,甚至不会被打包到客户端 JavaScript 中,意味着这里可以随意写服务器端代码,比如查询数据库。

export default function Post ({
     data}) {
     
    return <div>
        <span>{
     data.id}</span>
        <span>{
     data.title}</span>
    </div>
}

// 1.创建[].js 文件,这里是[id].js
// 2.返回用户可以访问到的所有的路由参数
export async function getStaticPaths () {
     
    return {
     
        paths:[{
     params:{
     id:'1'}},{
     params:{
     id:'2'}}],
        fallback:false
    }
}

// 3.返回路由参数所对应的具体数据
// 4.npm run build 会根据getStaticPaths返回的paths 去生成对应的html文件
export async function getStaticProps (context) {
     
    const id = context.params.id;
    let data;
    switch (id) {
     
        case "1":
            data = {
     id:"1",title:'hello'}
            break;
        case "2":
            data = {
     id:"2",title:'world'}
            break;
        default:
            data = {
     }
            break;
    }
    return {
     
        props : {
     
            data
        }
    }
}

自定义 404 页面

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

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

六.API Routes

概念

  • API Routes可以理解为接口,客户端向服务端发送请求获取数据的接口
  • Next.js应用允许React开发者编写服务器端代码创建数据接口

实现

  1. pages/api 文件夹中创建 API Routes 文件。比如 user.js

  2. 在文件中默认导出请求处理函数,函数有两个参数, req 为请求对象res 为响应对象

    export default (req, res) => {
           
        res.send({
           name:'张三',age:20})
    }
    
  3. 访问 API Routes: localhost:3000/api/user 页面上就能展示 {“name”:“张三”,“age”:20}

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

七.项目实战

学习了以上这些next相关概念即可实战了,这里贴一下实战项目的地址项目实战github地址

你可能感兴趣的:(Next.js)