后端转全栈之Next.js后端及配置

本文概括:

  1. 在 Next.js 中定义 GET/POST 接口及动态路由、缓存控制。
  2. middleware.ts 用法,包括重定向、Cookie、请求/响应头、CORS 设置。
  3. 环境变量用法及前端访问前缀 NEXT_PUBLIC_
  4. next.config.js 配置技巧,如代理、图片优化、构建检查和输出模式。

接口

Next.js里可以直接写后端接口:nextjs.org/docs/app/ap...

一般接口会放在 app/api/xxx/route.ts 文件里

app/api/test/route.ts 中:

javascript 复制代码
import { NextResponse, type NextRequest } from 'next/server'

export async function GET(request: NextRequest) {
    const res = {
        code: 0,
        message: 'Hello, world!',
        data: {
            name: 'cxk',
        },
    }
    return NextResponse.json(res)
}

这样就可以定义一个GET接口,接口接受的参数如下:

javascript 复制代码
export async function GET(request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
    // 访问/test页面,返回 /test
    const pathname = request.nextUrl.pathname
    // 访问/test?name=cxk页面,返回 {name: 'cxk'}
    const searchParams = request.nextUrl.searchParams
    const res = {
        code: 0,
        message: 'Hello, world!',
        data: {
            name: searchParams.get('name'),
            pathname: pathname,
        },
    }
    return NextResponse.json(res)
}

具体内容可以看:nextjs.org/docs/app/ap...

第二个参数是context,取决于动态路由当前的route

例如如果新建 app/test/[id]/route.ts 那么就可以从这里拿到id了

缓存问题:

默认情况下,如果GET接口会缓存,如果使用了Request对象,或者POST接口,那么就不会缓存了,如果设置了:

dart 复制代码
// 强制为动态渲染
export const dynamic = 'force-dynamic'
// 置重新验证频率为 10s , 在10s之后第一次访问开始过期数据,第二次访问拿到新的数据
export const revalidate = 10

中间件

参考地址:nextjs.org/docs/app/ap...

中间件可以拦截请求和响应,做登录鉴权等很多事情

app同级目录中定义一个 middleware.ts 文件

javascript 复制代码
import { NextRequest, NextResponse } from 'next/server'

// This function can be marked `async` if using `await` inside
export function middleware(request: NextRequest) {
    return NextResponse.redirect(new URL('/', request.url))
}

export const config = {
    matcher: '/test/:path*',
}

如上代码,可以将 /test/xxx 重新向到 /

Cookie操作:

下面是Next.js文档对Cookie的操作,可以使用 NextResponse.next() 拿到Response,最后需要返回

nextjs.org/docs/app/ap...

javascript 复制代码
// This function can be marked `async` if using `await` inside
export function middleware(request: NextRequest) {
    // Assume a "Cookie:nextjs=fast" header to be present on the incoming request
    // Getting cookies from the request using the `RequestCookies` API
    let cookie = request.cookies.get('nextjs')
    console.log(cookie) // => { name: 'nextjs', value: 'fast', Path: '/' }
    const allCookies = request.cookies.getAll()
    console.log(allCookies) // => [{ name: 'nextjs', value: 'fast' }]

    request.cookies.has('nextjs') // => true
    request.cookies.delete('nextjs')
    request.cookies.has('nextjs') // => false

    // Setting cookies on the response using the `ResponseCookies` API
    const response = NextResponse.next()
    response.cookies.set('vercel', 'fast')
    response.cookies.set({
        name: 'vercel',
        value: 'fast',
        path: '/',
    })
    cookie = response.cookies.get('vercel')
    console.log(cookie) // => { name: 'vercel', value: 'fast', Path: '/' }
    // The outgoing response will have a `Set-Cookie:vercel=fast;path=/` header.

    return response
}

Header操作:

可以对请求头进行一些操作:

javascript 复制代码
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
 
export function middleware(request: NextRequest) {
  // Clone the request headers and set a new header `x-hello-from-middleware1`
  const requestHeaders = new Headers(request.headers)
  requestHeaders.set('x-hello-from-middleware1', 'hello')
 
  // You can also set request headers in NextResponse.next
  const response = NextResponse.next({
    request: {
      // New request headers
      headers: requestHeaders,
    },
  })
 
  // Set a new response header `x-hello-from-middleware2`
  response.headers.set('x-hello-from-middleware2', 'hello')
  return response
}

CORS操作:

javascript 复制代码
import { NextRequest, NextResponse } from 'next/server'
 
const allowedOrigins = ['<https://acme.com>', '<https://my-app.org>']
 
const corsOptions = {
  'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
  'Access-Control-Allow-Headers': 'Content-Type, Authorization',
}
 
export function middleware(request: NextRequest) {
  // Check the origin from the request
  const origin = request.headers.get('origin') ?? ''
  const isAllowedOrigin = allowedOrigins.includes(origin)
 
  // Handle preflighted requests
  const isPreflight = request.method === 'OPTIONS'
 
  if (isPreflight) {
    const preflightHeaders = {
      ...(isAllowedOrigin && { 'Access-Control-Allow-Origin': origin }),
      ...corsOptions,
    }
    return NextResponse.json({}, { headers: preflightHeaders })
  }
 
  // Handle simple requests
  const response = NextResponse.next()
 
  if (isAllowedOrigin) {
    response.headers.set('Access-Control-Allow-Origin', origin)
  }
 
  Object.entries(corsOptions).forEach(([key, value]) => {
    response.headers.set(key, value)
  })
 
  return response
}
 
export const config = {
  matcher: '/api/:path*',
}

环境变量

Next.js的环境变量可以放到 .env*文件里, .env.local的优先级最高,例如文件内容:

ini 复制代码
DB_HOST=localhost
DB_USER=myuser
DB_PASS=mypassword

使用的时候:

arduino 复制代码
export async function GET() {
  const db = await myDB.connect({
    host: process.env.DB_HOST,
    username: process.env.DB_USER,
    password: process.env.DB_PASS,
  })
  // ...
}

默认的变量都应该是在后端使用的,如果需要浏览器也可以使用,那么需要加前缀: NEXT_PUBLIC_ ,有这个前缀的会被浏览器使用。

ini 复制代码
NEXT_PUBLIC_ANALYTICS_ID=abcdefghijk

配置

Next.js 可以通过根目录的 next.config.js 进行配置:

官方文档:nextjs.org/docs/app/ap...

比较有用的几个配置技巧:

代理:

javascript 复制代码
  rewrites: async () => {
    if (process.env.NODE_ENV !== "development") {
      console.log("Not in development mode, skipping rewrites");
      return [];
    }
    return [
      {
        source: "/api/:path*",
        destination: `${apiUrl}/:path*`,
      },
    ];
  },

禁用图片优化:

yaml 复制代码
  images: {
    unoptimized: true, // 禁用优化
  },

构建禁用ts和eslint检查:

yaml 复制代码
  eslint: {
    ignoreDuringBuilds: true,
  },
  typescript: {
    ignoreBuildErrors: true,
  },

构建是否需要后端:

arduino 复制代码
  output: "standalone", // 不需要后端,就用 export 静态页面即可, 需要后端,就standalone
相关推荐
Johnny_FEer4 小时前
什么是 React 中的远程组件?
前端·react.js
艾小码4 小时前
用了这么久React,你真的搞懂useEffect了吗?
前端·javascript·react.js
Mintopia5 小时前
🧑‍💻 用 Next.js 打造全栈项目的 ESLint + Prettier 配置指南
前端·javascript·next.js
江城开朗的豌豆5 小时前
React 跨级组件通信:避开 Context 的那些坑,我还有更好的选择!
前端·javascript·react.js
江城开朗的豌豆6 小时前
Redux 与 MobX:我的状态管理选择心路
前端·javascript·react.js
薛定谔的算法20 小时前
低代码编辑器项目设计与实现:以JSON为核心的数据驱动架构
前端·react.js·前端框架
小lan猫1 天前
React学习笔记(一)
前端·react.js
江城开朗的豌豆1 天前
解密React虚拟DOM:我的高效渲染秘诀 🚀
前端·javascript·react.js
前端人类学1 天前
React框架详解:从入门到精通(详细版)
react.js·redux