Update avaliable. Click RELOAD to update.
目录

NextJS 13 知识点整理

1. 动态路由的参数传递

1.1. 单个参数

|- posts
  |- [id]       # 单个参数
    |- page.jsx # 获取传入参数
  |- page.jsx
// http://127.0.0.1:3000/posts/1
const PostDetail = ({params}) => {
  const id = params.id;
}

1.2. 多个参数

|- posts
  |- [...slug] # 使用三个点方式
    |- page.jsx # 获取传入参数
  |- page.jsx
// http://127.0.0.1:3000/posts/1/2
const PostDetail = ({params}) => {
  const post_id = params.slug[0];
  const user_id = params.slug[1];
}

1.3. 查询参数

使用 searchParams 获取类似 http://localhost:3000/post/15/2?name=zhangsan 获取里面的查询参数 name

const PostDetail = async ({params, searchParams}) => {
  console.log(searchParams.name);
}

2. Rest 风格的 API

NextJS 13 中有个 Route Handler,可实现标准的 Rest,下面主要从几个方面了解如何处理:

Route.js Special File

目录不一定是 api,可以是 users 、 products 或者任意你想访问的路径,如 users 则最终的 restful 访问路径是:GET https://xxx.xxx.xxx/users/

2.1. 获取请求参数

export async function GET(request) {
  // GET URL参数
  const { searchParams } = new URL(request.url);
  const id = searchParams.get('id');

  // Form提交的参数
  const formData = await request.formData();
  const name = formData.get('name');
  const age = formData.get('age');
  console.log('name', name, 'age', age)

  // POST json体
  const res = await request.json();
  console.log(res);

  return new Response('Result Content', {
    status: 200,
  });
}

export async function GET(request, { params }) {
  // Rest参数
  const id = params.id;

  const res = await fetch(`http://jsonplaceholder.typicode.com/users/${id}`, { 'cache': 'no-cache' });
  const users = await res.json();
  return NextResponse.json(users);
}

2.2. 返回响应方式

export async function GET(request) {
  // 使用 NextResponse
  const res = await fetch(`http://jsonplaceholder.typicode.com/users/${id}`, { 'cache': 'no-cache' });
  const users = await res.json();
  return NextResponse.json(users);

  // 使用 Response
  return new Response('{"status":"ok"}', {
    status: 200,
    headers: {
      'Content-type': 'application/json'
    }
  })
}

2.3. 跨域、cookie、header

import { cookies, headers } from 'next/headers'

export async function GET(request) {
  // 使用 cookie
  const cookieStore = cookies()
  const token = cookieStore.get('token')

  // 使用 header
  const headersList = headers()
  const referer = headersList.get('referer')

  // 跨域
  return new Response('success', {
    status: 200,
    headers: {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
      'Access-Control-Allow-Headers': 'Content-Type, Authorization',
    },
  })
}

3. 表单数据的处理

下面是一个填写表单内容,提交并处理的示例代码,三个知识点:

'use client'
import React, { useRef } from "react";
import { experimental_useFormStatus as useFormStatus } from 'react-dom'

export default function Home() {
  const formRef = useRef();

  // 试验性功能,为表单提供一个 pending 的状态
  const { pending } = useFormStatus()

  async function handleSubmit(formData) {
    // get 获取对应值
    const username = formData.get('username');
    const password = formData.get('password');

    // 不需要使用 { 'username': username, 'password': password } 组装
    // 使用这种方式会默认生成 key
    console.log({username, password});

    // 使用 useRef 重制表单
    formRef.current.reset();
  }

  return (
    <div>
      <form action={handleSubmit} style= ref={formRef}>
        <input type="text" name="username" placeholder="username" required />
        <input type="password" name="password" placeholder="password" required />

        <button type="submit" disabled={pending}>
          { pending ? 'Loading...' : 'Submit' }
        </button>
      </form>
    </div>
  )
}

4. 环境变量.env

nextjs 不需要手动安装 dotenv,默认已经集成,且不需要在代码中显示去加载。根路径创建 .env 文件,配置好 key-value,直接使用如下方式获取

const API_KEY = process.env.API_KEY;
console.log(API_KEY);

也可在 next.config.js 中使用配置 key-value 使用,见 next.config.js Options env

5. 图片静态资源

默认图片等静态资源放置在 /public 目录中,使用内置的 Image 标签可自动获取

<image src="/spinner.gif" alt="loading" width="{150}" height="{150}" />

但通常生产环境下,/public 目录中的静态资源往往需要上传到某个 CDN 中以加速请求,减少自身服务器处理耗时,这时需要通过以下几个步骤完成

在 next.config.js 文件中新增下面配置,告诉 nextjs 针对 Image 需要通过自定义过滤处理一遍在渲染https://fla.cdn.bosyun.com/upload/vod/20230509-1/78502762fea1126dd2c3cf3364f198a3.jpg?imageView2/0/format/webp/q/75

images: {
  loader: 'custom',
  loaderFile: './app/custom/image.jsx',
},

创建 /app/custom 目录,新增一个 image.jsx 的文件,src 参数就是 Image 标签的 src,渲染时会追加整个 CDN 地址,组成有效的图片路径

export default function cloudinaryLoader({ src }) {
  return `https://fla.cdn.bosyun.com/upload/vod/20230509-1/${src}`
}

更多关于图片的处理参看,Imagenext.config.js Options images

6. 关于如何调试

NextJS 13 有 Server 与 Client 的特性,某些情况 Server 的调试并不能像如前这样,浏览器打开调试模式,代码增加 debugger 段等等,使用 vscode 启动进行调试是一个好办法,如下:

[.vscode/launch.json]

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Next.js: debug server-side",
      "type": "node-terminal",
      "request": "launch",
      "command": "npm run dev"
    },
    {
      "name": "Next.js: debug client-side",
      "type": "chrome",
      "request": "launch",
      "url": "http://localhost:3000"
    },
    {
      "name": "Next.js: debug full stack",
      "type": "node-terminal",
      "request": "launch",
      "command": "npm run dev",
      "serverReadyAction": {
        "pattern": "started server on .+, url: (https?://.+)",
        "uriFormat": "%s",
        "action": "debugWithChrome"
      }
    }
  ]
}

7. 如何转成PWA

7.1. 创建 manifest.json 文件

public 目录创建一个有效的 manifest.json 文件

7.2. 配置 manifest.json 文件

app/layout.js 文件中通过 metadata 新增 manifest.json 以及 PWA 其他的配置

export const metadata = {
  title: 'Life TimeLine',
  description: '只是想做个记录',
  viewport: 'width=device-width, initial-scale=1.0',
  manifest: '/manifest.json',
  themeColor: '#FFFFFF',
};

7.3. 安装 next-pwa 依赖

yarn add next-pwa
# 或者
npm i next-pwa

7.4. 增加pwa忽略文件

安装完 next-pwa,编译后会在 public 目录生成 sw 的 js 文件,不需要提交到 Git 仓库,加到忽略文件 .gitignore

**/public/sw.js
**/public/workbox-*.js
**/public/worker-*.js
**/public/sw.js.map
**/public/workbox-*.js.map
**/public/worker-*.js.map
版权所有,本作品采用知识共享署名-非商业性使用 3.0 未本地化版本许可协议进行许可。转载请注明出处:https://www.wangjun.dev//2023/07/nextjs-13-question/