00:00:00TanStack Start 最近风头正劲,问题是,你应该从 Next.js 切换过来吗?
00:00:06它比 Next.js 更好吗?
00:00:08昨天我做了一场完整的直播,
00:00:10对比了这两个框架,
00:00:11并构建了两个应用,
00:00:13或者说同一个应用构建了两次——一次用 Next.js,
00:00:17一次用 TanStack Start,
00:00:20如果你想看的话可以去观看,
00:00:21但在这里我会给你简短总结一下两者的不同之处、
00:00:25各自的优势以及你应该选择哪一个。
00:00:27当然,
00:00:28这只是我的个人观点,
00:00:29显然不是客观的对比,
00:00:30但我会分享我对这两者的使用体验,
00:00:32以及我对 Next.js 和 TanStack Start 的看法。
00:00:37我总结了几个维度来对比这两个框架,你也可以添加更多维度,也可以加入更多框架进行比较。
00:00:47我是说,
00:00:47我们可以把 Remix、
00:00:49React Router 包括进来,
00:00:51可以加入 Vue 的 Nuxt,
00:00:52可以讨论 SvelteKit,
00:00:54但我不会这么做。这个视频只讨论 Next.js 和 TanStack Start,
00:00:58不是因为其他框架不好,
00:01:00而是因为这两个框架经常被拿来比较。
00:01:01首先值得注意的是,TanStack Start 本质上就是 TanStack Router 加上一些服务端功能。
00:01:10所以如果你想构建一个不需要服务端渲染和服务端函数的单页应用,你可以单独使用 TanStack Router。
00:01:19例如,你可以在 React Vite 应用中使用 TanStack Router 来替代 React Router。
00:01:25如前所述,
00:01:25TanStack Start 只是在 TanStack Router 的基础上添加了服务端功能,
00:01:30使其成为一个完整的 React 全栈框架。
00:01:32就像 Next.js 一样,它当然也是一个全栈 React 框架。
00:01:37这一点也很重要。
00:01:38我有时会被问到应该使用 Next.js 还是 React Vite 配合 React Router,
00:01:45我认为这是错误的对比。
00:01:47如果你不需要服务端逻辑,
00:01:48不需要服务端渲染,
00:01:50那你应该直接使用 React Vite,
00:01:52也就是一个带 React 的 Vite 项目,
00:01:55然后添加 React Router 或 TanStack Router。
00:02:00在这种情况下,没有必要选择 Next.js 这条路线。
00:02:02好了,让我们开始对比吧。
00:02:05我选择的第一个维度是两者的 AI 友好程度,因为这在当下显然很重要。
00:02:12你很可能在使用 AI 生成一些代码,
00:02:15也许是你 Next.js 或 TanStack Start 项目中所需的全部代码,
00:02:22因此 AI 当然需要知道如何编写这些代码。
00:02:25显然,
00:02:26你可以也应该提供适当的上下文,
00:02:28比如复制文档页面,
00:02:30或者使用像 Context 7 这样的 MCP 让 AI 访问文档,
00:02:36或者告诉 AI 进行网络搜索,
00:02:39或者添加代理技能来教 AI 如何使用 TanStack Start 或 Next.js。
00:02:47但如果你直接问 ChatGPT 一个关于 TanStack Start 的问题,
00:02:53它对此的了解很可能远不如对 Next.js 的了解,
00:02:57而且它知道的内容可能是错误的。
00:02:59因为即使是现在我录制这个视频的时候,
00:03:02TanStack Start 仍处于候选发布阶段,
00:03:06这意味着不会再有重大的破坏性更改,
00:03:08但也还没有完全稳定。
00:03:10在过去的一年里,
00:03:11它主要处于 beta 和 alpha 阶段,
00:03:14而这些 AI 聊天机器人掌握的正是那个时期的知识,
00:03:18这就是为什么它们对 TanStack Start 的了解是错误的。
00:03:23所以开箱即用的 AI 友好程度不是很好,Next.js 在这方面肯定更胜一筹。
00:03:31当然,
00:03:31Next.js 这些年来也有很多变化,
00:03:34有新的 use cache 指令,
00:03:37AI 开箱即用对此也不太了解,
00:03:39但 AI 对 app router、
00:03:42React 服务端组件等内容有相当好的理解,
00:03:45所以对于 Next.js 来说肯定比 TanStack Start 要好。
00:03:51但正如前面提到的,你应该确保为 AI 提供所需的适当额外上下文,否则你只是在错误地使用 AI。
00:04:02生态系统方面如何呢?我指的是你能找到的其他资源,比如教程、YouTube 视频、课程,也许还有这些框架的额外包。
00:04:13当然,在这里 Next.js 看起来也比 Tan Stack Start 好得多,仅仅是因为它更老,存在的时间更长,你会找到更多相关资源,因为它也更大。
00:04:27当然也值得注意的是,它更大意味着更多的使用量,因为 Next.js 是 AI 默认技术栈的一部分,基本上对于你请求的大多数 Web 应用,AI 会给你 Next.js、
00:04:38React、
00:04:39Tailwind 和 TypeScript,Tan Stack Start 可能永远不会成为它的默认选择。
00:04:47因此毫不意外,如果你比较两者的下载量图表,是的,Tan Stack Start 的下载量确实要少得多,正如你所看到的。
00:04:56如果你移除 Next.js,你可以看到 Tan Stack Start 有一个不错的上升趋势。
00:05:01与生态系统这一点相关的当然是学习的难易程度,但不仅仅是这样。
00:05:07我所说的学习难易程度是指学习这个东西有多简单?
00:05:11我当然知道现在在 AI 时代你对学习它不感兴趣,但作为一个好的开发者,你应该理解你正在使用的东西。
00:05:19你可能不再手写所有代码,但你应该理解 AI 为你生成的代码。
00:05:25所以学习它仍然很重要。
00:05:28在这里我会说对于 Next.js 来说是喜忧参半的。
00:05:33你可以给它,我不确定我是想给一个加号还是两个加号,因为使用 App Router 开始使用 Next.js——顺便说一下,这里所有内容都是指 App Router——是相当简单的。
00:05:46这很合理。
00:05:47昨天在直播中,我构建了一个小型笔记应用,可以创建、保存和渲染笔记。
00:05:56你用 Next.js 做这件事只需指定几个 page.tsx 文件,它们就是你的,你猜对了,页面。
00:06:03你可以有动态段。
00:06:04学习这种语法和构建应用程序的方法最终是相当简单的。
00:06:12我也认为文档在逐步引导你了解核心概念并开始使用 Next.js 方面做得很好。
00:06:22但是当你构建更复杂的应用程序,以及当你深入研究像缓存这样的更高级概念时,事情会变得更复杂。
00:06:30尤其是缓存部分可能会非常令人困惑,因为 Next.js 做出了一个决定,即随着 App Router 的引入,他们想在不同层面做一些超级激进的缓存,理解这一点并理解如何配置你的组件以便与内置缓存良好配合,并为你的用户提供你想要他们获得的行为,可能会很棘手。
00:06:55我会这么说。
00:06:56所以入门很棒。
00:06:59学习更高级的功能是困难的。
00:07:02我可能会在这里给两个加号。
00:07:05我会给 Tan Stack Start 同样的评分,但原因非常不同。
00:07:09对于 Tan Stack Start,我会说入门可能比 Next.js 稍微难一点,因为他们的入门文档不如 Next.js 的文档好。
00:07:20我会说这里缺少重要的概念,比如数据获取或变更操作。
00:07:27不过,如果你已经有 Next.js 知识,有一个相当不错的比较文档,比较了包括数据获取和变更操作在内的关键功能。
00:07:36但我认为可能会更难一点,因为文档即使我要说它们已经得到了极大的改进,仍然有一点信息堆砌的感觉,不太清楚你需要哪篇文章,比如这里没有数据获取的文章之类的。
00:07:54此外,由于 Tan Stack Start 是建立在 Tan Stack Router 之上的,对于所有与路由相关的内容,你必须进入 Tan Stack Router 文档,当你第一次看到它时也是相当令人不知所措的。
00:08:07但是一旦你克服了最初的障碍,它就会变得容易得多,在我看来这一切都很有意义,并不那么困难,也没有像 Next.js 可能存在的缓存相关问题那样的隐藏陷阱。
00:08:22这就是为什么我会说使用 Tan Stack Start 入门更难,但一旦你开始运行,与 Next.js 相比,进步和深入研究更高级的功能会更容易。
00:08:32如前所述,这当然只是我个人的看法。
00:08:36那么从开发者的角度来看易用性如何呢?
00:08:41使用它的体验有多好?
00:08:43这当然是完全主观的,但 Next.js 在这方面确实存在一些问题。
00:08:48不仅仅是与学习相关的问题,还有其他问题。
00:08:53例如在缓存方面,
00:08:54你的应用在开发模式下的行为可能与生产模式不同,
00:08:58这意味着你总是必须在生产模式下测试它,
00:09:02虽然你本来就应该这样做,
00:09:04但如果在开发过程中你必须一直这样做的话就会变得相当烦人,
00:09:09因为这会拖慢你的速度。
00:09:11所以这是我过去遇到的一个大问题。
00:09:14开发服务器也可能会变得相当慢。
00:09:18至少如果你使用 webpack 版本的话是这样,
00:09:21新的默认 turbo pack 版本在这方面要好得多,
00:09:24但根据我的经验,
00:09:25它还是比不上 Tan Stick Start 提供的基于 Vite 的设置。
00:09:30所以我在这里给它三个加号,因为根据我的经验,从开发者体验的角度来看,使用它非常流畅。
00:09:40它速度快,
00:09:41可预测,
00:09:42大部分情况下没有奇怪的行为,
00:09:45虽然这里那里仍有一些小问题,
00:09:47而且它仍处于候选发布阶段,
00:09:49但总的来说我更喜欢 Tan Stick Start 的开发者体验,
00:09:55而不是 Next.js。
00:09:57当然,对你来说可能会有所不同。
00:10:01那么 Next.js 和 Tan Stick Start 提供的具体功能如何呢?
00:10:06对于路由,
00:10:07正如我向你展示的,
00:10:08在 Next.js 中你使用基于文件的方法,
00:10:12你设置作为路由的文件,
00:10:14在那里你必须遵循各种命名约定。
00:10:16文档在解释它们方面做得很好,但也确实有一些更复杂的功能,比如并行路由,设置起来可能会很棘手。
00:10:25Tan Stick Start 也有基于文件的方法,
00:10:28如前所述,
00:10:29它底层使用 Tan Stick Router,
00:10:32你在这里也有要遵循的文件名约定,
00:10:34这些约定同样容易学习。
00:10:36Tan Stick Start 给你带来的一个优势是,通过它基于文件的路由,它为你提供完整的类型安全,这非常不错。
00:10:45所以两者都是基于文件的,
00:10:47这取决于你更喜欢哪种命名模式,
00:10:50但 Tan Stick Start 还具有其基于文件的路由器带来的 100% 类型安全,
00:10:59这很好。
00:11:00这也回答了下一个问题,
00:11:01Next.js 有非常好的 TypeScript 支持,
00:11:05而根据我的经验,
00:11:06Tan Stick Start 有更好的 TypeScript 支持。
00:11:11在服务器操作或服务器函数或者你想怎么称呼它们以及数据获取方面也是如此。
00:11:18所以是的,当你使用 TypeScript 时(我认为你应该用),Tan Stick Start 真的是一种享受。
00:11:24现在说到数据获取和数据变更,
00:11:26正如我提到的,
00:11:27它们都允许你在服务器上运行代码,
00:11:30它们都是全栈 React 应用程序,
00:11:33但它们采用了不同的方法。
00:11:35Next.js 使用 React 服务器组件,在很长一段时间里,它是唯一支持 React 服务器组件的框架。
00:11:43这意味着你的页面组件默认只在服务器上渲染。
00:11:48它们永远不会在客户端重新渲染,
00:11:50这意味着你可以将数据获取代码(如这个会在后台访问数据库的代码)放入你的组件中,
00:11:57而不会泄漏到客户端。
00:11:59Tan Stick Start 有不同的方法。
00:12:01React 服务器组件支持也将很快登陆那里,
00:12:05在我录制这个视频时还没有发布,
00:12:08但我在这里向你展示的以及我在所有项目中使用的方法也将继续存在,
00:12:14在这种方法中,
00:12:16你的路由组件默认在服务器端和客户端都会渲染,
00:12:20在服务器端预渲染,
00:12:22在客户端更新,
00:12:23因此你不能将服务器端代码放入组件函数中。
00:12:27相反,
00:12:27它使用了一种加载器模式,
00:12:29你可能从 Remix 中了解过这种模式,
00:12:33你可以将加载器附加到路由上,
00:12:35它也会在客户端和服务器端运行,
00:12:38但你可以调用被装饰或包装了 create server functions 的函数,
00:12:45也就是 Tan Stack Start 提供的一个函数,
00:12:50它将函数标记为仅在服务器端运行,
00:12:52但可以从客户端调用。
00:12:54这就是服务器函数的含义。
00:12:56如果你有这样一个函数,你可以安全地在加载器中调用它,也可以从组件函数体中调用它,代码将保留在服务器端。
00:13:05在幕后会发送一个 HTTP 请求。
00:13:07所以 Next.js 主要依赖 RSC,
00:13:10尽管你当然也可以在那里设置 API 端点并使用 useEffect 配合 Fetch API。
00:13:15Tan Stack Start 使用加载器和服务器函数,
00:13:19不过值得注意的是,
00:13:20在那里你也可以设置 API 路由并使用 Fetch API、
00:13:24Tan Stack Query 或类似的东西,
00:13:27但主要的内置方法是这种加载器加服务器函数的方式。
00:13:31对于数据变更,Next.js 使用服务器操作,这些操作是用特殊的 useServer 指令装饰的。
00:13:39Next.js 有这些指令 useServer、useClient。
00:13:44有些人不喜欢它们,我也不是很喜欢,我得说。
00:13:48如果你有一个用 useServer 装饰的文件,那么其中的所有函数都会成为只在服务器上执行的服务器函数。
00:13:55不在客户端,但你仍然可以从客户端调用它们。
00:13:59例如,
00:13:59我这里有这个 saveNode 函数,
00:14:03它将节点存储在数据库中,
00:14:04仍然可以从客户端调用,
00:14:06比如使用 useActionState 钩子。
00:14:10在 Tan Stack Start 中,
00:14:13我们只需继续使用这个 createServer 函数方法,
00:14:17因为我提到过,
00:14:17这些函数保证在服务器上运行,
00:14:19你可以将它们用于数据获取或数据变更,
00:14:22因为代码只会在服务器上运行。
00:14:24在也会在客户端渲染的组件函数中,
00:14:26你可以使用 Tan Stack Start 提供的 useServer 函数钩子来包装你的服务器函数,
00:14:34这实质上使其可以从客户端调用,
00:14:36并为你提供额外的功能,
00:14:38如自动重定向处理等。
00:14:39这样我就可以从客户端组件中调用该服务器函数了。
00:14:43所以 Next.js 使用官方的 React 服务器函数,Tan Stack Start 最终使用它们自己的服务器函数。
00:14:51当然,总体思路是相同的。
00:14:54那么缓存呢?
00:14:56我提到过那是困难的部分。
00:14:58在 Next.js 中它相当激进且可能很复杂。
00:15:04这绝对是 Next.js 中较难的部分之一。
00:15:07如果你想全面学习 Next.js,我在我的 Next.js 课程中涵盖了这一点以及所有其他重要的 Next.js 概念。
00:15:16该课程是一个很好的资源,可以让你从绝对初学者成长为高级 Next.js 用户。
00:15:21但缓存绝对是 Next.js 中比较棘手的话题之一。
00:15:26当然,优势在于由于激进的默认设置,你可以为用户获得相当好的缓存效果。
00:15:35但你也很容易搬起石头砸自己的脚。
00:15:38对于 Tan Stack Start,我会总结为良好的默认设置。
00:15:43比 Next.js 激进程度低得多,而且最重要的是,至少根据我的经验,在开发和生产模式之间是一致的。
00:15:52它确实也为你提供缓存,例如当用户在路由之间导航时,数据会被缓存一段时间。
00:16:00这样在快速导航时,你不会向服务器发送大量请求。
00:16:04这当然对性能有很大帮助,但它不会在不同层缓存所有内容或试图缓存所有内容,这可以让你作为开发者的生活更轻松。
00:16:14当然,
00:16:15这也意味着如果你想为用户获得最佳性能并可能节省流量,
00:16:20你必须自己设置良好的缓存头,
00:16:23并比你在 Next.js 中可能需要做的更多地思考如何缓存你的应用程序。
00:16:30不过在这方面你还需要考虑其他问题。
00:16:32那么稳定性如何呢?
00:16:35这里我可能会给两者都打两个加号。
00:16:39它们都相当稳定。
00:16:40显然 Next.js 更加成熟,但根据我的经验,过去几年它确实有不少 bug,尤其是开发服务器经常出现崩溃等问题。
00:16:53但它已经改善了很多,总体而言是稳定的体验,而且当然有成百上千的应用程序在使用它,在生产环境中运行没有问题。
00:17:03这一点确实很重要。
00:17:06我们确实遇到过那些 React 安全漏洞,
00:17:09但首先,
00:17:09其中一些可能会在未来被发现,
00:17:11也会影响到 TanStack Start,
00:17:14尤其是当他们也开始支持 React 服务器组件时;其次,
00:17:18这当然主要不是 Next.js 的问题。
00:17:21TanStack Start 仍处于候选发布阶段,我确实遇到了不少问题。
00:17:28一些奇怪的崩溃、
00:17:29奇怪的错误信息、
00:17:31各种奇怪的行为,
00:17:32所以我也可以只给它一个加号,
00:17:34但考虑到它还在候选发布阶段,
00:17:37就这个阶段而言它已经相当稳定了,
00:17:39所以我会给两个加号。
00:17:41只是要注意,使用 TanStack Start 时你肯定可能会遇到一些问题。
00:17:47话虽如此,
00:17:47我确实有应用在生产环境中运行,
00:17:49比如 buildmygraphic.com,
00:17:53你可以用它借助 AI 制作精美的信息图表,
00:17:56这些应用都是由 TanStack Start 驱动的,
00:18:00运行没有问题,
00:18:01构建过程也很顺利。
00:18:02那么开箱即用的功能呢?
00:18:04获得优化的图片渲染、国际化或其他有趣功能有多容易?
00:18:12在这方面 Next.js 肯定做得更好。
00:18:15它有内置的图片组件,有内置的国际化支持,而 TanStack Start 没有这些。
00:18:24不确定是否有计划加入,
00:18:26也不确定这对你是否重要,
00:18:28这绝对不是必需的,
00:18:30有其他替代方案,
00:18:32你可以使用第三方包,
00:18:33也许你甚至不想要内置的东西,
00:18:36但如果这是你关心或担心的事情,
00:18:39那么 Next.js 可能是更好的选择。
00:18:43那么部署呢?
00:18:45这是个比较复杂的话题。
00:18:48Next.js 当然是由 Vercel 开发的,如果你在 Vercel 上部署,那是超级简单和流畅的。
00:18:56一切都为此做了优化。
00:18:58从历史上看,
00:18:59在自己的服务器上部署它有点困难,
00:19:02但公平地说,
00:19:04Next.js 团队确实做了很多工作来简化这个过程,
00:19:09编写了更好的文档,
00:19:11因此如今我会说你绝对可以在其他服务上部署它,
00:19:16也不会有太多问题。
00:19:17所以我会说是两个或三个加号,如果使用 Vercel 就是三个加号,如果使用其他提供商大概是两个加号。
00:19:28对于 TanStack Start,我现在会给两个加号,但也可以给三个。
00:19:36我给两个加号的主要原因是,在我录制这个视频的时候,托管文档还有点棘手。
00:19:45有官方支持的合作伙伴,
00:19:47比如 Cloudflare 和 Netlify,
00:19:51它们有相当完善的文档,
00:19:53部署可能会很顺利,
00:19:54不过我还没用过。
00:19:56如果你想在自己的 VPS 上用 BUN 运行它,
00:20:01这里有一些说明,
00:20:03但我发现有点难以理解,
00:20:05或者遇到了一些问题,
00:20:08虽然都能解决,
00:20:09但确实花了我不少时间。
00:20:12我认为一旦有了在 VPS 上使用 BUN 或 Node 部署 TanStack Start 的完整指南,
00:20:21部署肯定会变得更容易,
00:20:22特别是如果该指南包含一些你应该遵循的最佳实践建议,
00:20:27或者可能遇到的潜在陷阱。
00:20:29但如前所述,根据你的看法,这里也完全可以给三个加号。
00:20:34如前所述,这些都是主观的,只是我的经验和想法,显然我也很想听听你的想法。
00:20:42如果你已经切换了,
00:20:43或者你对 Next.js 和 T3 Stack 有什么看法,
00:20:47如果你正在考虑切换,
00:20:48或者你两者都不用,
00:20:50而是使用其他选择。