Comments
Loading Translate Section...Loading Comment Form...
Loading Comment Form...
deleted
这个网站『支持自动翻译文章和评论的多语言社区Evame』的元框架已从Remix迁移到Next.js,基础设施也从Render迁移到Vercel。
迁移过程耗时两周左右,规模较大,但结果令人满意。最终结论是:对于小型到中型网站,选择Remix/React Router是值得的;而对于大型网站,选择Next.js则更有价值。
本文将记录从Remix迁移到Next.js的过程,以及我对Remix和Next.js的个人比较。如果您正在纠结选择哪个框架,或者正在考虑迁移,请务必阅读!
网站发展方向的改变和规模的扩大
最初,创建Evame是为了为青空文庫、Project Gutenberg和古代佛经等公共领域的文本添加对译。但在开发过程中,我们希望能够为用户投稿的文章也添加对译。Evame的初衷是知识和故事的循环,为此,用户可以投稿的文章系统必不可少。这一方向的改变导致网站规模扩大,所需功能增多,我们开始被拥有庞大生态系统的Next.js所吸引。
Remix未来发展的不确定性
2024年11月22日,Remix v2与React Router v7合并。https://remix.run/blog/react-router-v7
我原本以为Remix会消失,以React Router的形式继续存在,但上述博客的作者,也是Remix的联合创始人,在Twitter上表示接下来是Remix v3。
I don't have any further plans to work on RR v7. I'm personally done with that project.
— MJ (@mjackson) December 21, 2024
Remix v3 is just something I've been calling it internally. Since we haven't released a v3 yet, it would make sense to publish the next version of Remix as v3.
更名会迫使整个生态系统发生巨大的变化。事实上,在另一个项目中,我们将Remix v2更新到React Router v7后,许多与Remix相关的库都无法使用,需要大量工作才能解决,耗费了相当大的精力。如果再次更名,我们可能面临同样的问题,许多库可能再次失效,这让我们感到担忧。
React与Next.js的紧密结合
https://nextjs.org/blog/next-12
正如上文所述,React和Next.js正日益紧密地结合在一起,Next.js比其他框架更早地使用了许多新技术。
RSC在2023年发布,至今已近两年,但仍然很少有框架能够使用RSC,这足以证明Next.js的领先性。
未来能够优先使用新功能,这一点是一个巨大的优势。
能够充分利用React 19
在Remix/React Router v7中,数据处理在route modules的loader/action中进行,组件和数据部分往往分离。而在Next.js(App Router)中,通过使用RSC(React Server Components)、Server Actions和useActionState等,组件和数据的距离缩短,开发效率得到提升。此外,基于协同定位的目录结构也比Remix更容易实现,进一步提高了开发效率。
丰富的生态系统
Next.js拥有许多服务的官方示例,例如Sentry、Supabase、Stripe等,并且周边库也很丰富。next/font和next/image也非常出色,它们使Lighthouse的性能得分达到100分,最佳实践也达到100分。
迁移前,得分如下(可访问性方面还需要努力)。
AI友好
我经常向Claude或GPT提出用Remix编写代码的请求,但它们经常输出Next.js的代码。由于用户众多,Next.js从一开始就能提供可用代码的概率更高。这或许可以被称为AI时代的新型生态系统。
构建速度慢
Remix的HMR速度很快,本地开发体验非常舒适。Next.js中,某些文件的构建需要几秒钟,有时甚至需要强制重新加载,开发体验上会有些压力。
更复杂的思维模型
Remix的思维模型是loader→component→action,流程简单明了。
Next.js中出现了RSC/Server Actions/revalidatePath/revalidateTag/next/dynamic/Request Memoization等多种概念。虽然优化后Lighthouse的得分提高了,但实际体验与Remix没有速度差异。作为用户,如果体验速度够快就可以了,我希望它能够自动变快。
黑魔法
Remix生成的HTML非常简洁,感觉写的代码就是直接输出的,易于理解。
Next.js使用框架特有的逻辑插入className和canvas标签等,调试比较复杂。而且,与Edge Runtime结合时,经常会出现本地运行正常,但生产环境运行失败的问题。
首先创建分支并使用create next,从库迁移开始。具体来说,需要迁移以下库:
remix-auth → auth.js
react-i18next → next-intl
remix-auth → auth.js的更改需要更改数据库模式,并且需要使用Prisma作为ORM进行Edge Runtime的适配,这是整个迁移过程中最困难的部分。
数据库模式采用与auth.js一致的模式,迁移现有数据,并减少自定义以降低更新时的风险。
对于Edge Runtime,Prisma Accelerate的案例还很少,本地和生产环境的差异似乎很大,让人担心;而迁移到Drizzle虽然自由度高,但工作量也很大。最终,我们选择Neon + Prisma,将工作量降到最低。
接下来,将现有的Remix路由和loader/action部分替换为Next.js App Router中的RSC/Server Actions。这里AI帮了很大的忙。不过,useActionState和Server Action目前还无法用AI编写,需要人工完成。
避免在Server Actions中包含公共逻辑
所有Server Actions都是公开的,因此需要编写认证代码。我们需要考虑是否可以将认证逻辑整合到函数中,或者使用中间件来处理。
RSC组件的测试
目前RSC的测试方法尚未完全确立,建议将业务逻辑和认证逻辑分开,以便进行单元测试。
useActionState的类型化
目前还没有确立为useActionState返回值添加类型信息的机制。目前最好自己定义。我个人是这样做的(参考了about_hiroppy的推文)。
export type ActionResponse<T = void, U = Record<string, unknown>> = {
success: boolean;
message?: string;
data?: T;
zodErrors?: typeToFlattenedError<U>["fieldErrors"];
};
表单的类型验证
最好在Server Action中进行验证。我个人使用zod,如下所示。
const editPageContentSchema = z.object({
slug: z.string().min(1),
title: z.string().min(1).max(100),
pageContent: z.string().min(1),
});
const parsedFormData = editPageContentSchema.safeParse({
slug: formData.get("slug"),
title: formData.get("title"),
pageContent: formData.get("pageContent"),
});
小型到中型应用
如果不需要使用最新的React功能,Remix/React Router可以提供简单、快速的开发体验。思维模型也很清晰。
对于B端应用或单页应用,我个人推荐Remix/React Router。
中型到大型应用或希望利用生态系统
选择Next.js可以更容易地与服务和库集成,并能够抢先体验React的未来更新。
对于C端应用或服务器端渲染,我推荐Next.js。
我个人认为,“发布后增长后再迁移到Next.js”这种方法也很可行。如果使用Cloudflare,Remix/React Router的成本也可以大幅降低。但是,迁移时仍然需要投入大量工作,如果考虑到未来的扩展性,从一开始就使用Next.js也是一个不错的选择。
这次对框架、数据库和基础设施进行了大规模的更改,但由于我们为重要部分编写了测试代码,并且将数据库代码用CQRS分离,因此除了认证部分以外,迁移过程相对顺利。再次体会到,对代码质量和架构的投入非常重要。
这个网站“Evame”是一个多语言社区,可以自动使用AI翻译文章和评论。通过这次迁移,我可以用日语编写迁移记录,并分享给英语国家。
如果您感兴趣,请用您喜欢的语言撰写文章,并将其分享到全世界!
以上就是我将Remix/React Router v7迁移到Next.js的心得、比较和迁移步骤。如果对您有所帮助,我将非常高兴!