After 20+ client projects on Next.js, I switched most of my work to Vite + React. The honest reason: most clients don't need SSR, and Next.js makes you pay for SSR even when you're not using it, in build time, in deployment complexity, in mental overhead, and in money. Vite gives me sub-second dev server starts, smaller bundles, deploy-anywhere flexibility, and a stack a junior can hand off in a week. I still reach for Next.js when SEO, edge rendering, or co-located backend code is genuinely the requirement. The rule I now use is: pick the simplest tool that solves the actual problem in front of you, not the most powerful tool in case the problem grows.
I've been a Next.js advocate for years. Server-side rendering, file-based routing, API routes, image optimization, the App Router: it's a powerful framework, and Vercel has done a remarkable job of pushing the web forward through it. For long-form content sites, marketing pages, and large multi-tenant SaaS, it's an excellent default.
But after shipping more than twenty client projects across portfolios, dashboards, admin panels, internal tools, and small SaaS products, I noticed an uncomfortable pattern: almost none of my clients actually needed SSR. They needed a fast app, a clean handoff, cheap hosting, and a stack their next developer could understand without a course.
What they were getting was an SSR-shaped framework that added complexity I had to keep explaining away. The first time I shipped a Vite + React + Supabase project end to end and watched the dev server boot in 200ms and the production build deploy to a static host for free, I stopped pretending. For SPAs, Next.js is overkill, and the overkill has a cost.
Next.js is built around the assumption that some pages will be server-rendered. Even if you push everything to the client, you're still inside that assumption. You pay for it in:
None of this is fatal. A lot of it is acceptable for the right project. But for an SPA that's going to live behind auth and ship to a handful of users, every one of those costs is being paid for a benefit that's never collected.
Build speed. Vite's dev server starts in under 300 milliseconds on my machine. Cold start. Next.js takes between 3 and 8 seconds on the same hardware. When you're iterating fast, making a small change, checking the browser, making another small change, that gap compounds into real wall-clock hours over a week of work.
Simplicity. There is no getServerSideProps, no getStaticProps, no generateStaticParams, no decision about which rendering strategy a page should use. Every component is a regular React component. Every route is a regular React Router route. The mental load is dramatically lower, and that frees energy for actual product work.
Flexibility. A Vite build produces a folder of static files. I can deploy it to Lovable, Netlify, Vercel, Cloudflare Pages, Render, an S3 bucket with CloudFront, or even a cheap shared host. There is no Node.js server to keep alive, no cold start penalty, no "edge runtime" gotchas. For client projects, this matters because the client owns the hosting after handoff and I want their bill to be ten dollars a month, not two hundred.
Bundle size. A typical Vite + React app I ship is between 100 and 180 KB of JavaScript, gzipped, including the framework. A similar Next.js App Router app starts at around 200 KB before you've written a line of business code. On a mobile connection in Damascus or Khartoum, that gap is the difference between an app that feels instant and one that feels sluggish for the first three seconds.
Honest dev experience. Hot Module Reload in Vite is essentially perfect, state preserves, edits show up in under 100 milliseconds, and I almost never need to restart the dev server. Next.js has improved a lot here, but it's still noticeably slower and occasionally requires a full restart when something gets confused.
I don't think Next.js is wrong. I think it's a great tool that's being used for the wrong job most of the time. The cases where I still reach for it:
If any of those apply, Next.js is the better answer. If none of them apply, Vite is almost certainly the better answer.
This stack covers about 90% of my client work. It is fast to develop in, fast to build, fast to deploy, and (most importantly) easy to hand off to whoever picks up the project next. I've handed off three Vite projects to junior developers and all three were productive within a week.
Here's what a typical "fetch and render" looks like in both stacks. In Next.js App Router:
// app/projects/page.tsx
import { db } from '@/lib/db';
export default async function ProjectsPage() {
const projects = await db.project.findMany();
return <ProjectsList projects={projects} />;
}
This is elegant on the surface, but you've now committed to running a Node process, you've coupled your component tree to a server runtime, and you've added a layer where "this is a server component" vs "this is a client component" becomes a thing you have to think about constantly.
In Vite + React + TanStack Query:
// src/pages/Projects.tsx
import { useQuery } from '@tanstack/react-query';
import { supabase } from '@/integrations/supabase/client';
export default function ProjectsPage() {
const { data: projects } = useQuery({
queryKey: ['projects'],
queryFn: async () => {
const { data } = await supabase.from('projects').select('*');
return data;
},
});
return <ProjectsList projects={projects ?? []} />;
}
Slightly more verbose, but everything happens in the browser, every component is the same kind of component, deploys are static files, and the caching/refetching behavior is explicit instead of magical.
I'm not going to pretend this is free. Switching to Vite costs you:
next/image. I usually pre-process images at build time with a script, or use Cloudinary for client uploads.React.lazy and Suspense yourself instead of getting it for free. It's about thirty extra lines of code, total.For 90% of the projects I work on, these trade-offs are net positive. For the other 10%, I just use Next.js.
Ask one question: does my first paint need to be HTML with content?
If yes: Next.js (or Remix, or Astro). The SSR cost is paying for a real benefit.
If no: Vite + React. You get a faster dev loop, smaller bundles, cheaper hosting, and a simpler mental model.
That's the whole decision. Everything else (file routing, image optimization, middleware) is a feature you can add to either stack if you actually need it.
The temptation in our industry is to pick the most powerful tool because someday you might need its full power. The reality is most projects never reach "someday." They reach a launch date, they reach a handoff, they reach a sunset.
The best tool is the simplest one that solves the problem in front of you. For most SPAs, that's Vite + React, and I'm not going back.
بعد أكثر من 20 مشروع عميل على Next.js، نقلت معظم عملي إلى Vite + React. السبب الصادق: معظم العملاء لا يحتاجون SSR، وNext.js يجبرك على دفع كلفته حتى حين لا تستخدمه، في زمن البناء، وفي تعقيد النشر، وفي العبء الذهني، وفي المال. Vite يعطيني خادم تطوير يبدأ في أقل من ثانية، وحُزماً أصغر، ومرونة في النشر على أي مزوّد، وستاكاً يستطيع المطوّر الجديد تسلّمه خلال أسبوع. أبقى ألجأ إلى Next.js حين يكون SEO أو العرض على الحافّة أو الكود الخلفي المُلصَق بالواجهة متطلَّباً حقيقياً. القاعدة التي صرت أعمل بها: اختر أبسط أداة تحلّ المشكلة التي أمامك، لا أقوى أداة تحسّباً لمشكلة قد تأتي.
كنت من أنصار Next.js لسنوات. العرض من جانب الخادم، التوجيه المبني على الملفات، مسارات API، تحسين الصور، App Router: إطار قوي بحقّ، وVercel فعلت عملاً ممتازاً في دفع الويب إلى الأمام عبره. لمواقع المحتوى الطويلة وصفحات التسويق وSaaS الكبيرة متعددة المستأجرين هو الاختيار الافتراضي المنطقي.
لكن بعد إطلاق أكثر من عشرين مشروع عميل بين بورتفوليو، لوحات تحكّم، أدوات داخلية، وSaaS صغيرة، لاحظت نمطاً مزعجاً: تقريباً لا أحد من عملائي احتاج SSR فعلاً. كانوا يحتاجون تطبيقاً سريعاً، وتسليماً نظيفاً، واستضافة رخيصة، وستاكاً يفهمه المطوّر التالي بلا دورة تدريبية.
الذي كانوا يحصلون عليه هو إطار مصمَّم حول العرض من جانب الخادم بكلفة تعقيد كنت أمضي وقتي في تبريرها. أوّل مرة شحنت فيها مشروع Vite + React + Supabase من البداية إلى النهاية، ورأيت خادم التطوير يبدأ في 200 مللي ثانية والبناء الإنتاجي ينشَر على استضافة ثابتة مجانية، توقّفت عن التظاهر. لتطبيقات الصفحة الواحدة، Next.js مبالغة، والمبالغة لها ثمن.
Next.js مبني على افتراض أن بعض الصفحات ستُعرض من الخادم. حتى لو دفعت كل شيء إلى العميل، تبقى داخل ذلك الافتراض. تدفع الثمن في:
لا شيء من هذا قاتل. كثير منه مقبول في المشروع المناسب. لكن لتطبيق صفحة واحدة سيعيش خلف مصادقة ويُقدَّم لعدد محدود من المستخدمين، كل واحدة من هذه التكاليف تُدفع مقابل فائدة لن تُجنى.
سرعة البناء. خادم Vite يبدأ في أقل من 300 مللي ثانية على جهازي. بداية باردة. Next.js يستغرق بين 3 و8 ثوانٍ على نفس العتاد. حين تكرّر بسرعة, تغيير صغير، فحص في المتصفّح، تغيير صغير آخر, هذا الفارق يتراكم إلى ساعات حقيقية في أسبوع عمل.
البساطة. لا getServerSideProps ولا getStaticProps ولا generateStaticParams، ولا قرار حول استراتيجية العرض لكل صفحة. كل مكوّن هو مكوّن React عادي. كل مسار هو مسار React Router عادي. العبء الذهني أخف بكثير، وهذا يحرّر طاقة للعمل الفعلي على المنتج.
المرونة. بناء Vite يُنتج مجلّد ملفات ثابتة. أستطيع نشره على Lovable أو Netlify أو Vercel أو Cloudflare Pages أو Render أو دلو S3 خلف CloudFront أو حتى استضافة مشتركة رخيصة. لا خادم Node.js يحتاج بقاءً حيّاً، لا غرامة بداية باردة، لا فخاخ "edge runtime". لمشاريع العملاء هذا يهمّ، لأن العميل يملك الاستضافة بعد التسليم وأريد فاتورته عشرة دولارات شهرياً لا مئتين.
حجم الحُزمة. تطبيق Vite + React نموذجي عندي بين 100 و180 كيلوبايت من JavaScript مضغوطاً، شاملاً الإطار. تطبيق Next.js App Router مشابه يبدأ حول 200 كيلوبايت قبل أن تكتب سطر منطق عمل. على اتصال موبايل في دمشق أو الخرطوم، هذا الفارق هو الفرق بين تطبيق يبدو فورياً وتطبيق يبدو ثقيلاً في الثواني الأولى.
تجربة تطوير صادقة. Hot Module Reload في Vite فعلياً مثالي, الحالة تُحفظ، التعديلات تظهر في أقل من 100 مللي ثانية، ونادراً ما أحتاج إعادة تشغيل الخادم. Next.js تحسّن كثيراً هنا، لكنه ما زال أبطأ ملحوظاً ويحتاج أحياناً إعادة تشغيل كاملة حين يرتبك شيء ما.
لا أظنّ أن Next.js خطأ. أظنّه أداة ممتازة تُستخدم في الوظيفة الخطأ في معظم الأحيان. الحالات التي ما زلت ألجأ فيها إليه:
لو انطبقت أيّ منها، Next.js أفضل. لو لم تنطبق أيّ منها، Vite يكاد يكون الأفضل دائماً.
هذا الستاك يغطّي حوالي 90% من عمل عملائي. سريع في التطوير، سريع في البناء، سريع في النشر، والأهم: سهل التسليم لمن يلتقط المشروع بعدي. سلّمت ثلاثة مشاريع Vite لمطوّرين مبتدئين وكان الثلاثة منتجين خلال أسبوع.
هذا ما تبدو عليه عمليّة "اجلب وارسم" في كلا الستاكين. في Next.js App Router:
// app/projects/page.tsx
import { db } from '@/lib/db';
export default async function ProjectsPage() {
const projects = await db.project.findMany();
return <ProjectsList projects={projects} />;
}
أنيقة في الظاهر، لكنك التزمت بتشغيل عملية Node، وقرنت شجرة المكوّنات بزمن تشغيل خادم، وأضفت طبقة تجبرك على التفكير دائماً في "هذا مكوّن خادم" أو "مكوّن عميل".
في Vite + React + TanStack Query:
// src/pages/Projects.tsx
import { useQuery } from '@tanstack/react-query';
import { supabase } from '@/integrations/supabase/client';
export default function ProjectsPage() {
const { data: projects } = useQuery({
queryKey: ['projects'],
queryFn: async () => {
const { data } = await supabase.from('projects').select('*');
return data;
},
});
return <ProjectsList projects={projects ?? []} />;
}
أكثر إطنابة قليلاً، لكن كل شيء يحدث في المتصفّح، كل مكوّن من نفس النوع، النشر ملفات ثابتة، وسلوك الكاشينغ وإعادة الجلب صريح بدل أن يكون سحرياً.
لن أتظاهر بأن هذا مجاني. الانتقال إلى Vite يكلّفك:
next/image. عادة أعالج الصور مسبقاً في زمن البناء بسكربت، أو أستخدم Cloudinary لرفع العملاء.React.lazy وSuspense بنفسك بدل أن تأتي مجاناً. كلها حوالي ثلاثين سطراً إضافياً، لا أكثر.لـ 90% من مشاريعي هذه المقايضات إيجابية الصافي. للـ 10% الباقية، أستخدم Next.js وأمضي.
اسأل سؤالاً واحداً: هل تحتاج أوّل لقطة لي أن تكون HTML بمحتوى؟
لو نعم: Next.js (أو Remix أو Astro). كلفة SSR تشتري فائدة حقيقية.
لو لا: Vite + React. تحصل على حلقة تطوير أسرع وحُزم أصغر واستضافة أرخص ونموذج ذهني أبسط.
هذا هو القرار كلّه. كل ما عداه (توجيه ملفات، تحسين صور، Middleware) مزايا تستطيع إضافتها لأيّ ستاك حين تحتاجها فعلاً.
الإغراء في صناعتنا أن تختار الأقوى لأنك قد تحتاج كامل قوّته يوماً. الواقع أن معظم المشاريع لا تصل إلى ذلك اليوم. تصل إلى تاريخ إطلاق، تصل إلى تسليم، تصل إلى تقاعد.
أفضل أداة هي الأبسط التي تحلّ المشكلة التي أمامك. لمعظم تطبيقات الصفحة الواحدة، هذه الأداة هي Vite + React، ولن أعود.
هل Vite مناسب لمواقع متعدّدة المستأجرين؟ جزئياً. لو كل مستأجر له نطاق فرعي يحتاج SSR، Next.js أنسب. لو المنطق متعدّد المستأجرين يحدث بعد المصادقة في تطبيق صفحة واحدة، Vite كافٍ.
ماذا عن SEO؟ Vite بحدّ ذاته لا يقدّم SSR. لو تحتاج SEO، أضف Prerendering في زمن البناء (vite-plugin-prerender أو React Snap) أو انقل إلى Astro أو Next.js.
كيف أتعامل مع متغيّرات البيئة في Vite؟ Vite يكشف فقط ما يبدأ بـ VITE_ للعميل، وهذا حدّ أمنيّ صحيّ. الأسرار الخلفيّة تبقى في الـ Edge Function أو في خدمة الباك إند.
هل أستخدم React Router أم TanStack Router؟ React Router للمشاريع الجديدة لاستقرار النظام البيئيّ. TanStack Router لمشاريع تحتاج توجيهاً مكتوب الأنواع بدقّة من اليوم الأوّل.
ما حدّ الحجم الذي يصبح فيه Vite غير كافٍ؟ لم أصل إليه. تطبيقات بمليون سطر تعمل عليه. الحدّ غالباً تنظيميّ لا تقنيّ, حين يكون فريقك ضخماً وتحتاج SSR لكلّ صفحة بسبب SEO.
هل ما زلت أحتاج Webpack؟ لا، إلا لو ورثت مشروعاً قديماً. Vite يغطّي كلّ ما كان Webpack يفعله بسرعة أعلى وإعداد أقلّ.
الانتقال بين الإطارات أمر عاطفيّ بقدر ما هو تقنيّ. أمضيت سنوات في Next.js وأقدّر ما تعلّمته منه. لكن أداة العمل اليوميّ يجب أن تطابق نمط المشاريع التي تعمل عليها لا التي تتمنّى أن تعمل عليها. لو معظم عملك تطبيقات صفحة واحدة، الستاك الأبسط يفوز. لو يومك مواقع SSR وSEO، Next.js ما زال الجواب. لا تختر بناءً على ما يبدو حديثاً، بل بناءً على ما تشحن به فعلاً.