Next.js从入门到实战保姆级教程:表单处理与 Server Actions

从0死磕全栈之Next.js 表单开发终极指南:使用 Server Actions 构建高效、安全、现代化的表单 能力实现方式基础提交参数传递bind()验证与错误加载状态乐观更新多操作formAction属性Server Actions 不仅简化了表单开发,更代表了“服务端优先”的现代 Web 开发哲学。掌握它,你就能构建出更快、更安全、更易维护的 Next.js 应用。 阅读详情

本系列文章将围绕Next.js技术栈,旨在为AI Agent开发者提供一套完整的客户端侧工程实践指南。

表单是 Web 应用中最常见的用户交互方式,也是最容易产生代码混乱的区域。Server Actions 提供了一种全新的架构思路:将表单提交逻辑直接编写在服务端函数中,消除传统 API 路由的样板代码,实现前后端逻辑的无缝衔接。

一、传统方式的局限性

在 Server Actions 出现之前,表单提交通常遵循以下流程:

  1. 前端组件监听 onSubmit 事件
  2. 事件处理函数通过 fetch 调用 API 路由
  3. API 路由(/api/xxx)处理业务逻辑、数据验证和数据库操作
  4. 前端接收响应并更新 UI

这种模式存在明显缺陷:

  • 大量胶水代码:需定义前后端 API 接口、错误处理和数据序列化逻辑
  • 代码分散:完整的数据流需要在多个文件间追踪
  • 维护成本高:前后端代码分离,修改时需同步更新多处

Server Actions 通过将前后端逻辑统一,有效解决了这些问题。


二、Server Actions 核心概念

Server Actions 是在服务端执行的异步函数,可直接从客户端组件调用,无需显式创建 API 路由。

// Server Action 示例
async function createPost(title: string, content: string) {
  'use server';  // 标记此函数在服务端执行

  // 直接操作数据库
  await db.insert(posts).values({ title, content });
  
  // 重新验证缓存
  revalidatePath('/blog');
}

当客户端调用此函数时,Next.js 自动发起 HTTP POST 请求至服务端执行,并将结果返回。整个过程对开发者透明——只需关注函数调用,无需处理底层通信细节。

工作原理

数据库服务端Next.js Runtime客户端组件数据库服务端Next.js Runtime客户端组件调用 Server Action发送 POST 请求执行数据库操作返回结果返回响应解析并返回结果

三、定义 Server Actions

方式一:服务端组件内联定义

// app/posts/new/page.tsx(服务端组件)
import { redirect } from 'next/navigation';
import { revalidatePath } from 'next/cache';

export default function NewPostPage() {
  // 在服务端组件内直接定义 Server Action
  async function createPost(formData: FormData) {
    'use server';

    const title = formData.get('title') as string;
    const content = formData.get('content') as string;

    // 服务端验证
    if (!title || title.length < 5) {
      throw new Error('标题至少需要 5 个字符');
    }

    // 数据库操作
    await db.posts.create({ data: { title, content } });
    
    // 缓存失效
    revalidatePath('/blog');
    
    // 重定向
    redirect('/blog');
  }

  return (
    // form 的 action 属性接收 Server Action
    <form action={createPost}>
      <input name="title" placeholder="文章标题" required />
      <textarea name="content" placeholder="文章内容" required />
      <button type="submit">发布</button>
    </form>
  );
}

关键特性:

  • <form action={createPost}> 使用 HTML 原生语义,传入函数而非 URL
  • 渐进增强:即使 JavaScript 禁用,表单仍可正常工作(降级为标准 HTML 提交)
  • 适用于简单表单场景

方式二:独立 Actions 文件

复杂项目推荐将 Server Actions 集中管理:

// app/actions/posts.ts
'use server';  // 文件级指令,整个模块均为 Server Actions

import { revalidatePath } from 'next/cache';
import { redirect } from 'next/navigation';
import { z } from 'zod';

// Zod Schema 定义
const PostSchema = z.object({
  title: z.string().min(5, '标题至少 5 个字符').max(100),
  content: z.string().min(20, '内容至少 20 个字符'),
  category: z.enum(['tech', 'life', 'thoughts']),
});

// 表单状态类型
export type PostFormState = {
  errors?: {
    title?: string[];
    content?: string[];
    category?: string[];
  };
  message?: string;
};

/**
 * 创建文章
 * @param prevState - 前一状态(用于 useActionState)
 * @param formData - 表单数据
 */
export async function createPost(
  prevState: PostFormState,
  formData: FormData
): Promise<PostFormState> {
  // 提取表单数据
  const rawData = {
    title: formData.get('title'),
    content: formData.get('content'),
    category: formData.get('category'),
  };

  // Zod 验证
  const validatedData = PostSchema.safeParse(rawData);

  if (!validatedData.success) {
    return {
      errors: validatedData.error.flatten().fieldErrors,
      message: '提交失败,请检查输入内容',
    };
  }

  try {
    // 数据库操作
    await db.posts.create({ data: validatedData.data });
  } catch (error) {
    console.error('Database error:', error);
    return { message: '数据库错误,请稍后重试' };
  }

  // 缓存失效
  revalidatePath('/blog');
  
  // 重定向
  redirect('/blog');
}

优势:

  • 集中管理所有表单逻辑
  • 便于复用和测试
  • 清晰的类型定义

四、客户端组件中使用 Server Actions

需要复杂交互(加载状态、错误反馈等)时,在客户端组件中使用useActionState:

// components/CreatePostForm.tsx
'use client';

import { useActionState } from 'react';
import { createPost, type PostFormState } from '@/app/actions/posts';

const initialState: PostFormState = {};

export function CreatePostForm() {
  /**
   * useActionState Hook
   * - 专为 Server Actions 设计
   * - 参数:(action, 初始状态)
   * - 返回:[当前状态, 绑定的 action, 是否执行中]
   */
  const [state, formAction, isPending] = useActionState(
    createPost, 
    initialState
  );

  return (
    <form action={formAction} className="space-y-4">
      {/* 标题字段 */}
      <div>
        <label htmlFor="title" className="block text-sm font-medium">
          文章标题
        </label>
        <input
          id="title"
          name="title"
          type="text"
          className="mt-1 block w-full rounded-md border-gray-300 shadow-sm"
          disabled={isPending}
          aria-describedby="title-error"
        />
        {/* 字段级错误提示 */}
        {state.errors?.title && (
          <p id="title-error" className="text-red-500 text-sm mt-1">
            {state.errors.title[0]}
          </p>
        )}
      </div>

      {/* 内容字段 */}
      <div>
        <label htmlFor="content" className="block text-sm font-medium">
          文章内容
        </label>
        <textarea
          id="content"
          name="content"
          rows={8}
          className="mt-1 block w-full rounded-md border-gray-300 shadow-sm"
          disabled={isPending}
          aria-describedby="content-error"
        />
        {state.errors?.content && (
          <p id="content-error" className="text-red-500 text-sm mt-1">
            {state.errors.content[0]}
          </p>
        )}
      </div>

      {/* 全局错误提示 */}
      {state.message && (
        <div 
          role="alert"
          className="bg-red-50 text-red-700 p-3 rounded-md"
        >
          {state.message}
        </div>
      )}

      {/* 提交按钮 */}
      <button 
        type="submit" 
        disabled={isPending}
        className="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 disabled:opacity-50"
      >
        {isPending ? (
          <>
            <span className="animate-spin mr-2">⏳</span>
            发布中...
          </>
        ) : (
          '发布文章'
        )}
      </button>
    </form>
  );
}

useActionState 核心价值:

  • React 19 新引入的专用 Hook
  • 自动管理 action 绑定、状态更新和执行状态追踪
  • 简化表单状态管理复杂度

五、乐观更新:提升用户体验

乐观更新(Optimistic Update) 是一种 UX 优化技术:在服务器确认前假设操作成功,立即更新 UI。若服务器返回错误则回滚。这使界面响应更加流畅,即使网络延迟也不会有明显卡顿。

React 19 提供 useOptimistic Hook 配合 Server Actions 实现:

'use client';

import { useOptimistic, useTransition } from 'react';
import { toggleLike } from '@/app/actions/likes';

interface Post {
  id: string;
  title: string;
  likes: number;
  isLiked: boolean;
}

interface PostCardProps {
  post: Post;
}

export function PostCard({ post }: PostCardProps) {
  const [isPending, startTransition] = useTransition();

  /**
   * useOptimistic Hook
   * - 参数:(当前值, 乐观更新函数)
   * - 返回:[乐观状态, 更新函数]
   */
  const [optimisticPost, addOptimisticLike] = useOptimistic(
    post,
    // 乐观更新逻辑
    (currentPost, liked: boolean) => ({
      ...currentPost,
      likes: liked ? currentPost.likes + 1 : currentPost.likes - 1,
      isLiked: liked,
    })
  );

  const handleLike = () => {
    startTransition(async () => {
      // 1. 立即更新 UI(乐观更新)
      addOptimisticLike(!optimisticPost.isLiked);
      
      // 2. 执行实际服务端操作
      try {
        await toggleLike(post.id);
      } catch (error) {
        // 3. 若失败,React 自动回滚乐观更新
        console.error('Like failed:', error);
      }
    });
  };

  return (
    <article className="border rounded-lg p-4">
      <h2 className="text-xl font-bold">{post.title}</h2>
      <button
        onClick={handleLike}
        disabled={isPending}
        className={`mt-2 flex items-center gap-1 ${
          optimisticPost.isLiked ? 'text-red-500' : 'text-gray-400'
        }`}
        aria-label={optimisticPost.isLiked ? '取消点赞' : '点赞'}
      >
        <span>{optimisticPost.isLiked ? '❤️' : '🤍'}</span>
        <span>{optimisticPost.likes}</span>
      </button>
    </article>
  );
}

(1)适用场景:

  • 点赞/收藏/关注等社交互动
  • 购物车数量增减
  • 任务完成状态切换

(2)注意事项:

  • 必须配合 useTransition 使用
  • 需在 try-catch 中处理错误以实现回滚
  • 不适合关键业务操作(如支付)

六、文件上传处理

文件上传也是常见的表单交互,在Next.js中也可以使用Server Action轻松实现。

1. Server Action 实现

// app/actions/upload.ts
'use server';

import { writeFile } from 'fs/promises';
import path from 'path';

interface UploadResult {
  url?: string;
  error?: string;
}

/**
 * 上传头像
 * @param formData - 包含文件的表单数据
 */
export async function uploadAvatar(formData: FormData): Promise<UploadResult> {
  const file = formData.get('avatar') as File;

  // 验证文件存在性
  if (!file || file.size === 0) {
    return { error: '请选择文件' };
  }

  // 验证文件类型
  const allowedTypes = ['image/jpeg', 'image/png', 'image/webp'];
  if (!allowedTypes.includes(file.type)) {
    return { error: '仅支持 JPG、PNG、WebP 格式' };
  }

  // 验证文件大小(5MB)
  const maxSize = 5 * 1024 * 1024;
  if (file.size > maxSize) {
    return { error: '文件大小不能超过 5MB' };
  }

  try {
    // 读取文件内容
    const bytes = await file.arrayBuffer();
    const buffer = Buffer.from(bytes);

    // 生成唯一文件名
    const filename = `avatars/${Date.now()}-${file.name.replace(/\s/g, '_')}`;
    const filepath = path.join(process.cwd(), 'public', filename);

    // 写入文件系统(生产环境应使用云存储)
    await writeFile(filepath, buffer);

    // 返回访问 URL
    return { url: `/${filename}` };
  } catch (error) {
    console.error('Upload error:', error);
    return { error: '上传失败,请稍后重试' };
  }
}

2. 客户端组件实现

// components/AvatarUpload.tsx
'use client';

import { useState } from 'react';
import Image from 'next/image';
import { uploadAvatar } from '@/app/actions/upload';

interface AvatarUploadProps {
  currentAvatar: string;
  onUploadSuccess?: (url: string) => void;
}

export function AvatarUpload({ 
  currentAvatar,
  onUploadSuccess 
}: AvatarUploadProps) {
  const [preview, setPreview] = useState(currentAvatar);
  const [isUploading, setIsUploading] = useState(false);
  const [error, setError] = useState<string>('');

  /**
   * 文件选择时生成预览
   */
  const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (!file) return;

    // 创建临时预览 URL
    const objectUrl = URL.createObjectURL(file);
    setPreview(objectUrl);
    setError('');

    // 清理之前的 URL
    return () => URL.revokeObjectURL(objectUrl);
  };

  /**
   * 表单提交处理
   */
  const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    setIsUploading(true);
    setError('');

    const formData = new FormData(e.currentTarget);
    const result = await uploadAvatar(formData);

    setIsUploading(false);

    if (result.error) {
      setError(result.error);
      // 恢复原头像
      setPreview(currentAvatar);
    } else if (result.url) {
      // 上传成功回调
      onUploadSuccess?.(result.url);
    }
  };

  return (
    <form onSubmit={handleSubmit} className="space-y-4">
      {/* 头像预览 */}
      <div className="relative w-24 h-24 mx-auto">
        <Image
          src={preview}
          alt="头像预览"
          fill
          className="rounded-full object-cover border-2 border-gray-200"
        />
      </div>

      {/* 文件选择 */}
      <div className="flex justify-center">
        <input
          type="file"
          name="avatar"
          accept="image/*"
          onChange={handleFileChange}
          className="hidden"
          id="avatar-input"
          disabled={isUploading}
        />
        <label 
          htmlFor="avatar-input" 
          className="px-4 py-2 bg-gray-100 hover:bg-gray-200 rounded-md cursor-pointer transition-colors"
        >
          选择图片
        </label>
      </div>

      {/* 错误提示 */}
      {error && (
        <p role="alert" className="text-red-500 text-sm text-center">
          {error}
        </p>
      )}

      {/* 提交按钮 */}
      <button 
        type="submit" 
        disabled={isUploading}
        className="w-full px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 disabled:opacity-50 transition-colors"
      >
        {isUploading ? '上传中...' : '确认上传'}
      </button>
    </form>
  );
}

生产环境建议:

  • 使用云存储服务(AWS S3、Cloudinary、Vercel Blob)
  • 实施图片压缩和格式转换
  • 添加 CDN 加速

七、表单安全防护

1. CSRF 保护

Next.js Server Actions 内置 CSRF 保护机制,通过 Origin 请求头验证来源,防止跨站请求伪造攻击。

2. 安全最佳实践

(1) 服务端验证不可省略
// ❌ 危险:仅依赖客户端验证
// 客户端验证可被轻易绕过

// ✅ 正确:服务端必须再次验证
export async function createPost(formData: FormData) {
  'use server';

  const title = formData.get('title') as string;

  // 服务端验证是最后一道防线
  if (!title || title.length < 5) {
    return { error: '标题太短了' };
  }

  // ...
}
(2) 权限验证
export async function deletePost(postId: string) {
  'use server';

  // 1. 验证用户登录状态
  const session = await getSession();
  if (!session?.user) {
    throw new Error('未授权访问');
  }

  // 2. 验证资源所有权
  const post = await db.posts.findUnique({ 
    where: { id: postId } 
  });
  
  if (!post || post.authorId !== session.user.id) {
    throw new Error('无权操作此资源');
  }

  // 3. 执行删除
  await db.posts.delete({ where: { id: postId } });
  
  // 4. 缓存失效
  revalidatePath('/blog');
}
(3) 防止注入攻击

SQL 注入防护:使用 ORM(Prisma、Drizzle)自动参数化查询

XSS 防护:React 默认转义 HTML,但使用 dangerouslySetInnerHTML 时需做净化(过滤)处理:

import DOMPurify from 'isomorphic-dompurify';

// 对用户输入的 HTML 进行净化
const cleanContent = DOMPurify.sanitize(userInputHtml);

// 安全渲染
<div dangerouslySetInnerHTML={{ __html: cleanContent }} />

八、最佳实践总结

1. Server Actions vs API Routes 选择指南

场景推荐方案理由
表单提交Server Actions简洁、类型安全、自动 CSRF 保护
数据变更操作Server Actions直接调用、无需额外 API 层
Webhook 接收端Route Handlers第三方服务需 HTTP 端点
流式响应(SSE)Route Handlers需精确控制响应流
公开 APIRoute Handlers外部客户端调用

2. Server Action 标准流程

每个数据变更的 Server Action 应遵循三步原则:

export async function updatePost(id: string, data: PostData) {
  'use server';

  try {
    // 1. 执行业务逻辑
    await db.posts.update({ where: { id }, data });
    
    // 2. 使相关缓存失效
    revalidatePath(`/posts/${id}`);
    revalidateTag('posts');
    
    // 3. 重定向或返回状态
    redirect('/blog');
    // 或 return { success: true };
  } catch (error) {
    // 错误处理
    return { error: '更新失败' };
  }
}

3. 职责分离原则

避免将所有逻辑堆砌在 Server Action 中:

// ❌ 不佳:逻辑混杂
export async function createPost(formData: FormData) {
  'use server';
  // 200+ 行代码...
}

// ✅ 推荐:职责清晰
export async function createPost(formData: FormData) {
  'use server';
  
  // 1. 数据解析
  const data = parsePostFormData(formData);
  
  // 2. 数据验证
  const errors = validatePostData(data);
  if (errors) return { errors };

  // 3. 业务逻辑(抽离到服务层)
  await postService.create(data);
  
  // 4. 缓存管理
  revalidatePath('/blog');
  
  // 5. 导航
  redirect('/blog');
}

4. 错误处理策略

  • 字段级错误:返回结构化错误对象,配合 useActionState 展示
  • 全局错误:使用 try-catch 捕获异常,返回友好提示
  • 意外错误:记录日志,返回通用错误消息(避免泄露敏感信息)

九、本章小结

通过本章学习,你应该掌握了:

  • Server Actions 的核心概念和工作原理
  • 两种定义方式:内联定义和独立文件
  • 客户端组件中的使用方法(useActionState)
  • 乐观更新的实现(useOptimistic)
  • 文件上传的完整流程
  • 表单安全防护(CSRF、权限验证、注入防护)
  • Server Actions 与 API Routes 的选择策略

下一章将探讨错误处理与加载状态管理——这是构建健壮应用的关键环节,确保在任何异常情况下都能提供良好的用户体验。

从0死磕全栈之Next.js Server Actions 入门实战:在服务端安全执行逻辑,告别 API 路由! 是 Next.js 提供的一种新机制,允许你在服务端组件中定义函数,并通过客户端(如表单)直接调用它,而无需创建单独的/api路由。Server Actions 是 Next.js 向“全栈一体化”迈出的重要一步。它让开发者用更少的代码、更安全的方式处理服务端逻辑,尤其适合表单交互场景。记住:能用 Server Actions 解决的,就别写 API 路由了! 阅读详情

相关推荐

Next.js Server Actions 详解: 无缝衔接前后端的革命性技术(八)

构建一个网站,需要处理一个简单的用户反馈表单。在前端,精心编写一个表单组件。在后端,创建一个专门的 API 路由(比如前端通过fetch函数,将表单数据打包发送到这个 API 端点。后端接收数据,进行验证,然后与数据库“沟通”。最后,后端向前端返回一个结果,告诉它:“嘿,我处理完了!这套流程虽然行得通,但就像是为了寄一封信,却不得不自己开车去邮政总局,绕了好大一圈。如果有一种方式,能让你在写前端代码的地方,直接“喊一嗓子”,服务器就能听到并行动,那该多好?

2501_92798394的博客 1041

《Next.js 14 App Router 实战:用「Server Actions」重构全栈表单的最佳实践》

《Next.js 14 App Router 实战:用「Server Actions」重构全栈表单的最佳实践》

idree的博客 1707

RK3588 Linux启动优化至亚秒级全链路剖析

本文深入探讨RK3588平台Linux系统启动加速技术,涵盖从BL1/ATF安全固件、U-Boot剪裁到内核精简化等全链路优化方案,实现从上电到用户脚本800ms内完成的实战经验。​​文末提供完整解决方案获取方式​​。由于在 ARMv6 之后引入了 TrustZone 模块, 目前市面上 ARMv7 和 ARMv8 之后的系统都会包含了该模块, 这个模块由 BL1 启动, 且在 ATF(ARM Trust Firmware) 固件中, 既安全世界中引导到 BL33 (UBOOT)的系统。

韩若明溪 1777

Next.js Server Actions 处理生活数据:表单不只是提交,还要校验和降级

Next.js Server Actions 处理生活数据应做三层校验:容忍模糊输入、结构化转化、确认补充提示。校验失败时收集所有问题一次性返回,不让用户反复填表。Server Actions 缺少中间件链,鉴权和限流需要额外处理。大文件上传应走专用接口,Server Actions 只负责文本元数据。生活数据丢失代价高,写入失败必须明确提示。

specter__的博客 4698

LVGL按键触发回调函数的完整流程

如果是我的话我会怎么写:例如按键,我先定义一个结构体里面包含ID,事件名等和回调函数的链表节点结构体里面有具体函数的指针,也有指向下一个回调函数的链表节点的指针,初始化一个结构体变量的,通过BSP层来驱动触摸屏幕,再通过中间层与被按下时就会判断是长按还是短按还是其他,改变变量的事件例如:改成长按,生成事件包后再注册你长按的回调函数链表节点,再根据变量的事件到链表中遍历最后实现功能.父容器监听所有子列表项的点击事件,无需为每个列表项单独注册回调。的回调,打印所有事件日志,观察事件触发顺序。

solomonzw的博客 3239

【Qt实战项目】记事本完整项目

效果图如下所示: 全部代码如下: #include “notepad.h” #include int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.showMaximized(); return a.exec(); }

YIZHILIUSHA2020的博客 575

总结 Next.js 中的 Server Actions

摘要: Next.js 的 Server Actions 允许直接在服务端执行异步数据库操作,无需创建 API 端点。与传统 API 相比,它简化代码结构、减少网络请求并提升安全性,但复用性和测试难度较高。适用于小型项目或简单数据交互,而传统 API 更适合复杂场景。示例展示了通过 Server Actions 增删改数据库数据,结合 revalidatePath 更新缓存。两者各有优劣,需根据项目需求选择。 (字数:150)

林恒的博客 892

防止通达信公式被盗?手把手教你用DLL加密+互联网验证(含易语言后台管理)

本文详细介绍了如何通过DLL加密与互联网验证技术保护通达信公式安全。从DLL加密实现、设备绑定到易语言后台管理,提供了一套完整的防护方案,有效防止公式被盗用。重点讲解了互联网验证登录和绑定设备等核心技术,帮助量化交易者守护核心资产。

weixin_29323551的博客 501

Next.js Server Actions在生活表单场景的实践:从传统API到渐进增强

Server Actions消除了传统API的样板代码:不需要创建路由、处理CORS、手动fetch,表单逻辑收敛在服务端。useActionState是状态管理的统一接口:loading(pending)、error(state.message)、success通过框架统一管理。Zod+Server Action构建了编译时安全的验证层:验证Schema在客户端和服务端共享类型推理。渐进增强是生活工具的核心优势:JS禁用时表单仍能通过传统POST提交,保障中老年用户群体的可用性。不适合实时交互场景。

specter__的博客 2248

RH850从0搭建Autosar开发环境【3X】- Davinci Configurator之BswM模块配置详解(上)

RH850从0搭建Autosar开发环境【3X】- Davinci Configurator之BswM模块配置详解(上)

weixin_42412049的博客 740

车载网络测试实操源码_使用CAPL脚本实现安全访问解锁,并模拟各种测试场景

在车载诊断中,我们经常会使用到安全访问解锁,常见的场景包括软件刷写前、通过2E服务写入某个DID前、通过31服务执行某个例程前等,都必须先通过27服务进行安全访问,解锁相应安全等级后才能执行上述操作。在开发调试或测试时,有时候需要模拟正常的安全解锁、安全访问秘钥错误、连续多次请求安全访问等,手动操作极为不便。本文将介绍如何使用CAPL脚本实现安全访问解锁,并模拟各种测试场景。

文章主要涉及嵌入式软件开发、测试、项目管理等,欢迎交流,共同进步。 1201

Next.js Server Actions 实战全解:表单提交、数据校验、乐观更新与缓存失效(基于 claude-skills nextjs-developer 技能)

本指南以 claude-skills 仓库中 [nextjs-developer 技能](https://link.gitcode.com/i/7022e0632de379b5573434e1dbfae831) 的 [server-actions.md](https://link.gitcode.com/i/eda259bca6d6e4ea82cfe21e35e2d936) 参考文档为骨架,系统讲

gitblog_00697的博客 1037

英伟达 DGX Spark & Reachy Mini 入门教程(一)

英伟达在2026年CES上发布多款开放模型,包括Nemotron推理LLM、Isaac GR00T VLA和Cosmos世界模型,助力开发者构建个性化AI代理。文章详细介绍了如何通过DGXSpark和Reachy Mini机器人打造办公助手,涵盖材料准备(推理/视觉模型、文本转语音服务)、智能体构建(NeMo Agent Toolkit框架)、工具调用和路由策略实现。系统支持本地/云端部署,提供语音交互、视觉识别和动作执行功能,并保持完全开源可定制。最后给出运行演示的终端配置步骤和测试用例,鼓励开发者在此基

2506_90492529的博客 2713

Next.js 全栈实战:Server Actions 与数据流架构的深度工程化

Next.js Server Actions 的核心价值在于消除了前后端之间的类型裂缝和集成胶水代码。但这一便利性以牺牲中间件层和细粒度缓存控制为代价。正确使用 Server Actions 的关键是:始终在 Action 内部进行输入验证和认证检查,精确控制缓存失效范围,并在复杂交互场景中审慎评估是否需要回退到传统 API Route。落地路线建议:首先建立统一的 Action 工具函数(认证包装、错误格式化、日志记录),确保每个 Action 遵循相同的结构。

qq_40635035的博客 5102

Autosar EcuM配置-初始化及下电执行函数-基于ETAS软件

Autosar EcuM学习笔记-上电初始化执行函数及下电前执行函数,本文介绍在EcuM中的配置及使用。

赞的博客 849

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Next.js从入门到实战保姆级教程:错误处理与加载状态

系统讲解 Next.js 的错误边界体系与加载状态管理,掌握 error.tsx、loading.tsx、not-found.tsx 等特殊文件,构建健壮的用户体验。

FrontAI的博客 505

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Next.js 15 Server Actions 实战:从表单提交到乐观更新

在 Next.js App Router 里,Server Actions 让你可以在不手写 API 路由的情况下,直接从组件里调用运行在服务端的函数。它把「表单提交 → 请求接口 → 更新界面」这条老链路压缩成了一个async函数。这篇教程带你从零跑通一个待办列表,覆盖表单提交、校验、重新验证缓存,以及乐观更新。

weixin_42662753的博客 489

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

Next.js服务器操作(Server Actions)详解:数据 mutations新范式

你是否还在为React应用中的数据提交逻辑而烦恼?传统的API路由不仅需要手动处理表单验证、错误处理,还得编写大量客户端-服务器通信代码。Next.js的服务器操作(Server Actions)彻底改变了这一现状,让你可以直接在React组件中调用服务器函数,实现数据变更(Mutations)的无缝集成。本文将带你掌握这一革命性特性,从基础配置到高级应用,让数据操作变得前所未有的简单高效。 #...

gitblog_00260的博客 1076

Next.js 数据获取与 Server Actions 实战:从 API Routes 到 SWR 的完整指南

本文围绕 Next.js 的三大核心能力展开:**客户端/服务端数据获取**、**Server Actions(服务端动作)** 与 **API Routes**,并结合当前仓库中的 [with-nextjs 示例](https://link.gitcode.com/i/1d359b670b28f313eacba84cb5f05ed1) 与 [@refinedev/nextjs-router](h

gitblog_00700的博客 345

Zact完全指南:从安装到实战的NextJS Server Actions验证工具

在Next.js 13+的Server Actions时代,开发者们渴望一种简单而强大的验证方案。Zact正是为此而生的终极解决方案,它巧妙地将Zod验证与NextJS Server Actions结合,为你的应用提供完整的类型安全保障。这个快速、简单的工具让服务器端验证变得轻而易举,即使是初学者也能快速上手。本文将为你提供完整的Zact使用指南,从基础安装到实战应用,帮助你掌握这个强大的验证工具

gitblog_00551的博客 1015

React 19 Server Actions 与表单处理:从 API 路由到全栈组件

React 19 Server Actions 将表单处理从"客户端 + API 路由"推进到"全栈组件"。标记的函数编译为 RPC 端点,管理调用状态,自动刷新缓存。落地建议:第一,所有 Server Action 必须在服务端进行输入验证,不信任客户端数据;第二,表单提交用 Server Actions,数据查询用 Server Components;第三,注意redirect()不能在 try/catch 中调用。

qq_40635035的博客 4777

Next.js与NeuroLink构建AI应用:Server Actions与流式响应实战

在现代Web开发中,全栈框架与AI能力集成已成为技术热点。其核心原理在于通过服务器端执行确保API密钥安全,并利用流式传输技术降低用户感知延迟。这种架构的技术价值在于将复杂的AI推理逻辑与前端交互解耦,让开发者能专注于构建自然流畅的用户体验。应用场景广泛覆盖智能客服、代码生成、内容创作等实时交互型AI产品。本文以Next.js的Server Actions和Streaming为核心,结合NeuroLink这类AI SDK,深入探讨如何实现安全、高效的流式AI应用开发,其中Server Actions负责后端

weixin_30756499的博客 621

Next.js从入门到实战保姆级教程:实战项目(上)——全栈博客系统架构与核心功能

从需求分析到数据库设计,逐步构建生产级博客系统的后端架构。涵盖 Prisma 数据建模、认证系统集成、Server Actions 实践等核心知识点,为 AI 时代的全栈开发打下坚实基础。

FrontAI的博客 842

Next.js从入门到实战保姆级教程:导读——建立 Next.js 的认知框架

Next.js 框架全面介绍,涵盖核心特性、技术优势、应用场景及学习路径,帮助开发者建立完整的认知框架。

FrontAI的博客 854

Next-Safe-Action:革命性的Next.js Server Actions安全解决方案

还在为Next.js Server Actions的类型安全和验证问题头疼吗?每次处理表单提交都要重复编写繁琐的验证逻辑?`next-safe-action`为你带来全新的开发体验——类型安全、端到端验证、中间件支持的Server Actions解决方案。 ## 读完本文你将获得 - 🚀 掌握next-safe-action的核心概念和安装配置 - 🔒 学会创建类型安全的Server Ac

gitblog_00304的博客 1002

Next.js从入门到实战保姆级教程:数据获取与缓存策略

深入理解 Next.js 的数据获取哲学:服务端数据获取、多层缓存机制、流式渲染与 Suspense、按需重新验证,以及选择合适策略的思维框架。

FrontAI的博客 809
上一篇: Next.js从入门到实战保姆级教程:元数据与 SEO 优化
下一篇: Next.js从入门到实战保姆级教程:从原理到实践深度剖析缓存策略
FrontAI
博客等级 码龄1年 61粉丝 61原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值