Remix框架实战踩坑记我的开发经验总结

诸葛涵博 框架 阅读 1,773
赞 18 收藏
二维码
手机扫码查看
反馈

Remix vs Next.js:这次我真的选对了吗?

最近项目重构,纠结了好久到底用Remix还是Next.js。之前一直听说Remix很牛逼,数据获取方式颠覆传统,但团队熟悉Next.js,学习成本是个问题。折腾了两周对比测试,总算有点心得了。

Remix框架实战踩坑记我的开发经验总结

先说结论:对于复杂的企业级应用,我还是更倾向于Next.js;但如果做那种需要SEO和用户交互并重的产品,Remix确实有它的优势。下面具体聊聊各种对比。

路由机制:这是最大的分歧点

这是我踩坑最多的地方。Next.js的文件系统路由虽然简单,但遇到复杂的嵌套路由时真的头疼。Remix的约定式路由看起来复杂,但实际用起来反而更清晰。

Next.js的路由就是常规的pages目录:

// pages/users/[id].js
export default function UserPage({ user }) {
  return (
    <div>
      <h1>{user.name}</h1>
      <UserProfile data={user} />
    </div>
  )
}

export async getServerSideProps({ params }) {
  const user = await fetchUser(params.id)
  return { props: { user } }
}

而Remix的路由嵌套是这样的:

// app/routes/users.$id.jsx
import { json, useLoaderData } from "@remix-run/react"

export async function loader({ params }) {
  const user = await getUser(params.id)
  return json({ user })
}

export default function User() {
  const { user } = useLoaderData()
  
  return (
    <div>
      <h1>{user.name}</h1>
      <UserProfile data={user} />
    </div>
  )
}

刚开始看Remix的loader确实懵逼,但熟悉后发现这种方式更符合直觉。特别是有多个数据源的时候,每个路由组件都有自己的loader,职责很清晰。Next.js的getServerSideProps在嵌套布局时经常让我抓狂。

数据获取:Remix真的改变了游戏规则

这里必须承认Remix的数据获取方式确实创新。传统的客户端请求-服务器响应模式,在Remix里变成了服务端直接渲染+客户端智能更新。这个理念我比较喜欢。

// Remix的action处理表单提交
export async function action({ request }) {
  const formData = await request.formData()
  const result = await updateUser(formData)
  
  if (result.error) {
    return json({ error: result.error }, { status: 400 })
  }
  
  return redirect(/users/${result.id})
}

export default function EditUser() {
  const actionData = useActionData()
  const [form, setForm] = useState({})
  
  return (
    <Form method="post">
      {actionData?.error && <p>{actionData.error}</p>}
      <input name="name" defaultValue={form.name} />
      <button type="submit">保存</button>
    </Form>
  )
}

这种做法的好处是即使JavaScript挂了,表单依然能正常工作。Next.js当然也能做到,但需要额外的配置和考虑。Remix把这些都内置了,开箱即用。

不过这里有个坑需要注意:action和loader的错误处理如果没处理好,用户体验会很差。我之前就因为错误边界设置不当,导致整个页面崩溃。现在我都习惯统一包装错误返回:

function safeAction(actionFn) {
  return async (args) => {
    try {
      return await actionFn(args)
    } catch (error) {
      console.error("Action error:", error)
      return json({ 
        error: "操作失败,请重试", 
        success: false 
      }, { status: 500 })
    }
  }
}

性能对比:差距比我预期的小

原本以为Remix会比Next.js慢,毕竟多了那么多运行时的东西。但实际上两者的SSR性能差不多,关键还是看你怎么优化。

Next.js的优势在于生态成熟,Image、Link等优化组件用起来很顺手:

import Image from 'next/image'

export default function MyComponent() {
  return (
    <Image 
      src="/hero.jpg" 
      alt="Hero" 
      width={1200} 
      height={600}
      priority
    />
  )
}

Remix没有这些内置优化,需要自己集成。不过它提供的useFetcher hook在某些场景下比Next.js的SWR还要灵活:

import { useFetcher } from "@remix-run/react"

export default function LikeButton({ postId, initialLikes }) {
  const fetcher = useFetcher()
  const likes = fetcher.data?.likes || initialLikes
  
  return (
    <fetcher.Form method="post" action="/api/like">
      <input type="hidden" name="postId" value={postId} />
      <button type="submit" disabled={fetcher.state === "submitting"}>
        👍 {likes} {fetcher.state === "submitting" ? "..." : ""}
      </button>
    </fetcher.Form>
  )
}

这里用fetcher的好处是用户点击后按钮状态立即更新,不需要等待服务器响应,体验很好。Next.js要实现类似效果需要自己封装或者用第三方库。

我的选型逻辑

经过这次对比测试,我现在有了比较清晰的选型标准:

  • 如果项目主要是营销页面、博客类需要强SEO的,选Next.js。生态成熟,部署简单
  • 如果是复杂的企业应用,特别是表单交互多的,Remix更好用。loader/action模式真的很方便
  • 团队技能栈也是重要因素。Next.js团队上手快,Remix需要一定的学习时间

还有一个重要的考虑因素是部署。Next.js的Vercel部署真的是傻瓜式操作,Remix的部署配置相对复杂一些。不过现在Remix也支持各种平台了,差别不大。

关于开发体验,两者其实都不错。Remix的HMR有时候会有些延迟,但整体影响不大。Next.js的TypeScript支持确实做得更完善一些,这也是一个加分项。

调试方面,Remix的开发工具链还在完善中,有时候出错信息不够直观。Next.js的错误提示通常更友好一些。这个可能随着版本迭代会改善,但现在确实是个痛点。

以上是我的对比总结,有不同看法欢迎评论区交流

总的来说,这两个框架各有优势,不能简单地说哪个更好。我的建议是:新项目可以先用Remix试试水,复杂的企业项目还是Next.js稳妥一些。毕竟技术选型不只是看功能特性,还要考虑团队能力、维护成本等现实因素。

这个对比花了我不少时间,希望对大家有参考价值。如果有遗漏的地方,欢迎补充讨论。

本文章不代表JZTHEME立场,仅为作者个人观点 / 研究心得 / 经验分享,旨在交流探讨,供读者参考。
发表评论

暂无评论