在 Next.js 中使用 Netlify Forms
Netlify Forms 通过在部署时扫描存在或在构建过程中生成的静态 HTML 文件,使用自动检测表单标签属性 (opens in a new tab)的方式(例如:data-netlify
)。
作为安全和反垃圾邮件措施,Netlify 只识别在部署时检测到的表单和字段名称。当提交表单时,表单的目标 URL 也必须是静态文件。
然而,现代 Next.js 版本不会生成完全静态的 HTML 页面,因为任何页面都可以在运行时重新验证。相反,相关页面会在构建时预渲染,然后存储在 Next.js 的缓存中以供服务。这意味着您的 Next.js 页面(包括任何表单标签和属性)在部署时不会写入静态 HTML 文件,因此不能作为表单的目标页面。在这些页面中设置的与 Netlify Forms 相关的属性将不会生效。
Netlify Forms 的变通解决方案
以下是解决这一限制的一种方法:
-
在站点的
public
目录中创建一个新的 HTML 文件。该文件仅用于部署时的表单检测,可以任意命名,例如public/__forms.html
。 -
在该文件中,添加所有 Netlify 表单和字段的表单标签。如下例所示,只需包含最基础的内容即可,因为用户完全不会看到这个 HTML 页面。
<html> <head></head> <body> <form name="feedback" data-netlify="true" hidden> <input type="hidden" name="form-name" value="feedback" /> <input name="name" type="text" /> <input name="email" type="text" /> <input name="message" type="text" /> </form> </body> </html>
-
在动态页面或表单组件中,通过向上述创建的静态 HTML 文件(使用上面的示例:
/__forms
)发送POST
请求来处理提交。 -
请求完成后,应显示成功通知或导航到另一个页面。以下是表单组件的简化示例:
"use client"; export function FeedbackForm() { const handleFormSubmit = async (event) => { event.preventDefault(); const formData = new FormData(event.target); await fetch("/__forms.html", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams(formData).toString(), }); // 成功和错误处理 ... }; return ( <form name="feedback" onSubmit={handleFormSubmit}> <input type="hidden" name="form-name" value="feedback" /> <input name="name" type="text" placeholder="姓名" required /> <input name="email" type="text" placeholder="邮箱 (选填)" /> <button type="submit">提交</button> </form> ); }
实时演示
如需查看包含提交状态处理(成功、错误或待处理)的更完整示例,请访问实时演示 (opens in a new tab)或查看表单组件 (opens in a new tab)和必需的静态文件 (opens in a new tab)的代码。
防止静默失败
为防止表单检测或提交的静默失败,当检测到代码可能存在兼容性问题时,我们会触发一个明确的构建失败提示:
@netlify/plugin-nextjs@5 需要执行迁移步骤以支持 Netlify Forms。请参考 https://ntl.fyi/next-runtime-forms-migration 获取迁移示例。
当同时满足以下两个条件时,会触发此失败:
- 适配器在您的 React 代码中发现了
netlify
或data-netlify
表单属性的使用(这些属性将不会生效) - 在您的
public
目录中未找到包含表单属性的静态 HTML 文件(表明您尚未按照上述方法实现)
跳过检查
如果您认为检查失败是错误的,或者希望将问题推迟到以后处理,可以通过向站点添加值为 false
的 NETLIFY_NEXT_VERIFY_FORMS
环境变量来跳过此检查。