Ask HN: Vite or NextJS?
I am building a new project from scratch. I have a backend already written in Python/FastAPI. I have React/Typescript experience with CRA and Vite (and I prefer the latter). I haven't used NextJS before, but I'm interested in learning more about it. I'm thinking of using it and figuring it out as I go along, but I'm wondering how much time I should expect this to set me back? If I'm already familiar with React, will NextJS take me a few hours to pickup? A few days? Weeks? I understand that this is a broad question and everyone has different capacity to learn, but I'm trying to get a rough sense since I don't want to push off deadlines too much.
17 comments
If we were still on Next.JS 13, I would advise against it, that version saw the introduction of the "App router" which replaced the "Pages router", and as all new shiny things, it had a lot of warts and migration was painful.
Next.JS 14, which introduced server actions, is really worth it though.
But, IMHO, the main advantage of Next.JS is Vercel. You get a free platform to deploy your app just by "pointing it to your git repository". I've used it with Prisma and MongoDB (with a MongoDB Atlas free instance), so I have deployed my app completely, free of charge. Which for proof of concepts is a great thing.
Next.JS 14, which introduced server actions, is really worth it though.
But, IMHO, the main advantage of Next.JS is Vercel. You get a free platform to deploy your app just by "pointing it to your git repository". I've used it with Prisma and MongoDB (with a MongoDB Atlas free instance), so I have deployed my app completely, free of charge. Which for proof of concepts is a great thing.
I, a high school student, had almost never used Next.js before I built [Zyma](https://github.com/EvanZhouDev/zyma) with my friend in a 12-hour hackathon. I learned how to use Next.js properly within and beyond that hackathon (in around 3-6 hours of actual learning and experimenting in total), just from reading the documentation.
I almost never used Next.js before because I had contributed to another project before that uses Next.js, but never really touched the parts that are Next.js-specific.
The main thing about Next.js (or I guess any modern React meta-framework in this day) that was a new concept to me would be React Server Components.
My experience with Vite consists of SvelteKit (which is built on Vite) and I would just say that the DX of Vite is a bit nicer than Next.js as Next.js tries to get in everything: it’s fairly opinionated on how to do things while Vite typically doesn’t get in your way.
I almost never used Next.js before because I had contributed to another project before that uses Next.js, but never really touched the parts that are Next.js-specific.
The main thing about Next.js (or I guess any modern React meta-framework in this day) that was a new concept to me would be React Server Components.
My experience with Vite consists of SvelteKit (which is built on Vite) and I would just say that the DX of Vite is a bit nicer than Next.js as Next.js tries to get in everything: it’s fairly opinionated on how to do things while Vite typically doesn’t get in your way.
This is very helpful. Given your experience, would you use NextJS on your next project or are you indifferent?
I had a background in Vue.js and hadn't worked with React or Next.js before, but I took the plunge and started my project using Next.js (https://github.com/sudheerkumarme/curo-care-pwa). I found the learning curve surprisingly smooth, thanks to Next.js' excellent documentation. If you're considering it, I'd encourage you to dive in and learn as you go.
Next.js builds on React, so if you're comfortable there, picking it up might take a few days to a week. The documentation is extensive, making the initial learning process quite manageable. I suggest starting with the official Next.js documentation (https://nextjs.org/docs) as it provides a comprehensive guide.
One thing to keep in mind is the concept of data fetching, which can be a bit tricky initially. The documentation provides useful patterns for data fetching (https://nextjs.org/docs/app/building-your-application/data-f...), helping you navigate this aspect of Next.js development.
Next.js is more opinionated than React, which can be an advantage for newcomers. However, coming from a React background, it might take some time to adjust to the project structure and conventions. Once you get accustomed, these opinions can actually make development more streamlined.
If you decide to go with Next.js and run into any challenges, feel free to reach out to me at [email protected]. I'd be happy to lend a hand or share insights from my experience.
Overall, my experience with Next.js was pleasant. In this age of AI assistants like Bard and ChatGPT, you're likely to find valuable support regardless of the technology you choose. Happy coding!
Next.js builds on React, so if you're comfortable there, picking it up might take a few days to a week. The documentation is extensive, making the initial learning process quite manageable. I suggest starting with the official Next.js documentation (https://nextjs.org/docs) as it provides a comprehensive guide.
One thing to keep in mind is the concept of data fetching, which can be a bit tricky initially. The documentation provides useful patterns for data fetching (https://nextjs.org/docs/app/building-your-application/data-f...), helping you navigate this aspect of Next.js development.
Next.js is more opinionated than React, which can be an advantage for newcomers. However, coming from a React background, it might take some time to adjust to the project structure and conventions. Once you get accustomed, these opinions can actually make development more streamlined.
If you decide to go with Next.js and run into any challenges, feel free to reach out to me at [email protected]. I'd be happy to lend a hand or share insights from my experience.
Overall, my experience with Next.js was pleasant. In this age of AI assistants like Bard and ChatGPT, you're likely to find valuable support regardless of the technology you choose. Happy coding!
Isn't Vite and Nextjs operating on different levels?
I’d say you should consider Remix. It seems to be the most straight forward yet power packed one.
NextJS always break for some weird reason and the upgrades are painful sort of
NextJS always break for some weird reason and the upgrades are painful sort of
I think Vite makes more sense as its framework around react to build a frontend only. Nextjs is more like fullstack framework with ability to use server components and ORM
I wouldn’t call my self an expert in React or frontend for that matter.
Earlier this year, I was helping someone create an MVC for a startup idea and I stumble upon NextJS (v13 at the time).
Within 2 or 3 weeks I was able get it up and running, hosted it in Vercel for demos and hand it to the team that was going to build it.
I found it very approachable and well documented. Everything I needed was on their website
Earlier this year, I was helping someone create an MVC for a startup idea and I stumble upon NextJS (v13 at the time).
Within 2 or 3 weeks I was able get it up and running, hosted it in Vercel for demos and hand it to the team that was going to build it.
I found it very approachable and well documented. Everything I needed was on their website
You can learn NextJS easily, if you have good understanding of React. Also, while using Nextjs for the apis, you need to learn some basic syntax like we have in Express.js or node. Rest, consider it as same as React in a broader way and you can easily follow along with the documentation of Next.JS
NextJS is fairly easy to pickup if you're familiar with React. The basics and a quick prototype will probably take less than a day.
NextJS was (and maybe still is) a popular choice for server-side rendering. If you don't need that, not sure if its worthwhile.
NextJS was (and maybe still is) a popular choice for server-side rendering. If you don't need that, not sure if its worthwhile.
Nextjs does also support static site generation. Vite does have similar with Vike, but after using it's client side routing, next still comes out on top.
Vike's client side routing just replaces the whole page, so if you have something like a notification pop up and then the user navigates, the notification disappears.
Vike's client side routing just replaces the whole page, so if you have something like a notification pop up and then the user navigates, the notification disappears.
NextJS is a batteries-included full-stack framework, Vite is a lot more minimal.
If you're just looking to stand up a SPA frontend for your BE, I'd recommend going with Vite, or using NextJS but going full SPA-mode.
Doing things in a properly "NextJS"y way requires buy-in to the SSR/React Server Components paradigm, which takes some time to learn, if you're used to doing things in the SPA way. You have to architect differently -- specifically the way you handle data fetching/caching. I think it's worth digging into if you have the time, just depends on your goals.
Also worth mentioning, since NextJS is full-stack, deployment will be more involved. You might not notice any pains if you use Vercel, but definitely doesn't match the simplicity of sending along a single JS bundle with Vite.
If you're just looking to stand up a SPA frontend for your BE, I'd recommend going with Vite, or using NextJS but going full SPA-mode.
Doing things in a properly "NextJS"y way requires buy-in to the SSR/React Server Components paradigm, which takes some time to learn, if you're used to doing things in the SPA way. You have to architect differently -- specifically the way you handle data fetching/caching. I think it's worth digging into if you have the time, just depends on your goals.
Also worth mentioning, since NextJS is full-stack, deployment will be more involved. You might not notice any pains if you use Vercel, but definitely doesn't match the simplicity of sending along a single JS bundle with Vite.
Go with Vite/React. It's minimal and customizable. Next.js is too much new stuff to learn.
Why do you want to use Next.js if you already have a FastAPI backend?
One of the goals of making an API is to be able to implement multiple frontends on top of it.
In Next.JS server side, whether you query a database or a remote API with `fetch`, there are not much differences. And you'd still want Server Side Rendering to avoid having slow "first display" time.
In Next.JS server side, whether you query a database or a remote API with `fetch`, there are not much differences. And you'd still want Server Side Rendering to avoid having slow "first display" time.
IMO as a frontend dev: It's a question of app architecture, optional hosting and middleware features, and whether your app needs any of that.
TLDR: Vite is good for client-side only single-page apps. Next can do that too (with more complexity), but its real strength lies in being able to handle some of the stuff a more dedicated backend traditionally would, offloading some of the frontend rendering and fetching to the backend server (or serverless funcs).
Next also has the additional benefit (big, IMO) of being the most popular way to do React (and arguably web frontends in general)... it has a thriving ecosystem of third-party packages, examples, and users. IMO that is a bigger benefit than any strict feature parity comparison. I don't think it's an exaggeration to say that Next is now the "standard" way to do React -- and when React last overhauled their docs, Next replaced the default CRA for a while, until they added some other frameworks in a subsequent update. It makes a big difference in day to day work, especially with other teams/companies, when you can share the same framework and mental model.
Longer version:
CRA, Vite, and Next.js all do what's typically expected of a framework these days: improve on the barebones React DX. They all handle bundling (via webpack or esbuild or Rollup or similar), tests (usually jest), hot module refresh (live previews as you edit), built-in support for SASS and TypeScript, etc. And they also give you a single framework to upgrade together, integrated and tested by a company, instead of a dozen individual packages across the React ecosystem -- drastically reducing the chance of incompatibilities. Now, these are all nice for the developer, but they don't really help the end-user UX.
Next goes a step beyond those basics: If your data lives in a backend and visitors see a frontend, Next also takes up the space in between the two, in a place where reverse proxies, Varnish caches, and other optimizations of that sort used to live. It lets you optimize the heck out of your pages (and components now, with the App Router 13+) so the server can do a lot of the work and send the client pre-built HTML blobs, reducing the fetching and rendering done on the client.
In a traditional clientside SPA (like create-react-app or default Vite), the user's browser downloads a bunch of JS, runs it, fetches any data it needs, and then combines that data and your code into a bunch of HTML. That all happens in real-time on the client, and it can sometimes be a bottleneck for users with slower devices or networks.
The power of Next.js is in letting you, the developer, more carefully manage that lifecycle. The downside is that it often forces you to manage that lifecycle when you don't want to -- like in a traditional SPA.
For example, let's say you run a website with a blog and an ecommerce section.
The blog is the easier example: The content lives somewhere (doesn't really matter where, say a headless CMS or a bunch of Markdown files). Next can do a serverside fetch/readfile, combine the content with your React components, and then render HTML + hydratable JS all on the server, efficiently packing it down and code-splitting it for delivery via CDN. When a user sees that page, what they first download is the HTML, so the blog content is immediately readable. Half a second later the JS is downloaded in chunks and rehydrated in the background. When the user clicks the "Next post" link, Next fetches ONLY THE JSON CONTENT from its middleware -- as distinct from your original backend -- and uses that small blob (probably just a few kB) and uses that to re-render the next post's blog body, while keeping the rest of the page (headers, menus, scripts, etc.) unchanged. This makes inter-page navigation lightning fast, because it's not refetching/reloading EITHER all the JS or the HTML, just the JSON of the content that changed. And for clients without JS, or who didn't get to load it in time before navigating, clicking "Next post" will simply fall back to the serverside rendered version of that page. It takes a second or two longer in that case because it has to download the entire HTML all over again, but it's a graceful degradation. At the same time, every time a user visits that blog post, Next will do a background staleness check. If the post's been updated, it will re-fetch and re-build just that one page, so subsequent visitors see the updated version (incremental static regeneration, ISR). This is all kinda magic, but well-documented in their docs.
The advantage of all this is faster end-user browsing. The disadvantage is increased complexity for the developer: you have to think through the mental model of this, separating your SPA into chunks of "what can I offload to the server" and "what must happen on the client" and then "how do I deal with invalidations".
A more complex example is ecommerce: Each product can be a component that's mostly rendered serverside, with the names, descriptions, etc. all coming from the DB. The images get fetched from S3 or Imgix or wherever, then next/image adds progressive rendering, blur thumbnails, and responsiveness to them. The pricing data component changes maybe once a day, and is statically built and invalidated not on a timer but a specific invalidation tag. The inventory level, however, is completely client-side (shows a React suspense while loading, nothing if JS is disabled)... that goes through a serverless func that pulls it from the latest DB tables/KV store/whatever.
All of that is out-of-the-box functionality for Next.js, and it can all live in one single codebase -- frontend and middleware and API routes and serverside and clientside stuff, just in different folders with file-based routing.
It can be really powerful, but it's also a lot of overhead and mental complexity if you just need a barebones clientside SPA (which Vite is great for). With great power comes great... need for debugging?
Now, a lot of these principles can be offloaded to a real backend too. You want to make serverside components and send them over the wire as HTML, cached on a CDN? You can do all that with standard backend software and keep the frontend light. I don't know what you've implemented in Python/FastAPI, but if it sounds like it's duplicating some of the features of Next, it probably is.
Next makes a lot of sense in an all-JS team, cuz it lets them handle the entire frontend, all the middleware, and some of the backend (minus the actual content) all in the same TypeScript codebase, no Python or Java or .NET or PHP required. (And Vercel is also moving into DBs as a service: https://vercel.com/guides/using-databases-with-vercel). If you have a separate backend written in some other language & framework, it may or may not overlap with Next features. That's why it's an architectural decision, not just a strict frontend comparison.
--------------------------------------------
Now, whereas the above was me trying to objectively analyze the differences... this is my opinion as a user: The App Router is annoying. I loved Next before 13, with the old pages router doing serverside stuff and useEffect() plus dynamic() loading in clientside stuff. It was a pretty intuitive mental model.
The App Router makes things a lot more complicated. Still, I had to learn it, alongside React Server Components and Suspense etc., just to keep up with the latest versions -- especially since I work in a support role now (for a headless CMS vendor) and deal with other companies using Next in various permutations, often with the App Router nowadays.
I understand the benefits it offers, but I question whether the incrementally better UX is worth the much higher complexity and worse DX. The old page router is still available, but it seems to me they're trying to phase it out in favor of the new shiny, which is a shame because it's so much more complex. Maybe I'm just getting old :)
My old argument for Next.js is that it abstracts away a lot of the chaos of the old React ecosystem (where nothing was provided out of the box, not even routing) into a single sleek package. To a large extent that is still true, but it's also true for Vite, Astro, Remix, etc. these days -- they all offer many similar benefits over vanilla React, without the mental complexity of Next + App Router.
But... I would still 100% choose Next for new projects. Like it or not, it is the industry standard (at least for now) and it has the best chance of both still being used and maintained in 5 years, and also allowing your project to grow into its features as needed.
The basic setup with Next, even with the App Router, only takes a day or two to learn and implement. If you use `create-next-app` it'll only take like five minutes to get a example website up and running, then a few hours to get it hooked up to a real backend using prototype frontend components.
But for many months after that, you'll hit subtle differences in, say, `use client` vs `use server` and how to embed one in the other, how to get around its built-in monkeypatching of `fetch()` to cache its results, how to properly implement ISR with sensible invalidations, etc. It's a long-tailed learning curve.
If it were me, that learning curve is worth it. Mostly because I know I can trust Next and Vercel to do their jobs once I learn them, and I'm not going to run into their limitations before I hit my own. And having a large ecosystem + userbase is huuuuuuuuuge for not having to reinvent the wheel, being able to find StackOverflow or ChatGPT solutions, etc.
But YMMV. Build your prototypes in a few frameworks and see which ones are the easiest to work with for your use case, and then imagine your app in 5 years with a bunch of new features, and try to imagine that it's like using that framework to build those.
Good luck!
edit: Heck, screw "5 years". Just imagine 2 years, lol. Nothing in Javascript lasts longer than that.
TLDR: Vite is good for client-side only single-page apps. Next can do that too (with more complexity), but its real strength lies in being able to handle some of the stuff a more dedicated backend traditionally would, offloading some of the frontend rendering and fetching to the backend server (or serverless funcs).
Next also has the additional benefit (big, IMO) of being the most popular way to do React (and arguably web frontends in general)... it has a thriving ecosystem of third-party packages, examples, and users. IMO that is a bigger benefit than any strict feature parity comparison. I don't think it's an exaggeration to say that Next is now the "standard" way to do React -- and when React last overhauled their docs, Next replaced the default CRA for a while, until they added some other frameworks in a subsequent update. It makes a big difference in day to day work, especially with other teams/companies, when you can share the same framework and mental model.
Longer version:
CRA, Vite, and Next.js all do what's typically expected of a framework these days: improve on the barebones React DX. They all handle bundling (via webpack or esbuild or Rollup or similar), tests (usually jest), hot module refresh (live previews as you edit), built-in support for SASS and TypeScript, etc. And they also give you a single framework to upgrade together, integrated and tested by a company, instead of a dozen individual packages across the React ecosystem -- drastically reducing the chance of incompatibilities. Now, these are all nice for the developer, but they don't really help the end-user UX.
Next goes a step beyond those basics: If your data lives in a backend and visitors see a frontend, Next also takes up the space in between the two, in a place where reverse proxies, Varnish caches, and other optimizations of that sort used to live. It lets you optimize the heck out of your pages (and components now, with the App Router 13+) so the server can do a lot of the work and send the client pre-built HTML blobs, reducing the fetching and rendering done on the client.
In a traditional clientside SPA (like create-react-app or default Vite), the user's browser downloads a bunch of JS, runs it, fetches any data it needs, and then combines that data and your code into a bunch of HTML. That all happens in real-time on the client, and it can sometimes be a bottleneck for users with slower devices or networks.
The power of Next.js is in letting you, the developer, more carefully manage that lifecycle. The downside is that it often forces you to manage that lifecycle when you don't want to -- like in a traditional SPA.
For example, let's say you run a website with a blog and an ecommerce section.
The blog is the easier example: The content lives somewhere (doesn't really matter where, say a headless CMS or a bunch of Markdown files). Next can do a serverside fetch/readfile, combine the content with your React components, and then render HTML + hydratable JS all on the server, efficiently packing it down and code-splitting it for delivery via CDN. When a user sees that page, what they first download is the HTML, so the blog content is immediately readable. Half a second later the JS is downloaded in chunks and rehydrated in the background. When the user clicks the "Next post" link, Next fetches ONLY THE JSON CONTENT from its middleware -- as distinct from your original backend -- and uses that small blob (probably just a few kB) and uses that to re-render the next post's blog body, while keeping the rest of the page (headers, menus, scripts, etc.) unchanged. This makes inter-page navigation lightning fast, because it's not refetching/reloading EITHER all the JS or the HTML, just the JSON of the content that changed. And for clients without JS, or who didn't get to load it in time before navigating, clicking "Next post" will simply fall back to the serverside rendered version of that page. It takes a second or two longer in that case because it has to download the entire HTML all over again, but it's a graceful degradation. At the same time, every time a user visits that blog post, Next will do a background staleness check. If the post's been updated, it will re-fetch and re-build just that one page, so subsequent visitors see the updated version (incremental static regeneration, ISR). This is all kinda magic, but well-documented in their docs.
The advantage of all this is faster end-user browsing. The disadvantage is increased complexity for the developer: you have to think through the mental model of this, separating your SPA into chunks of "what can I offload to the server" and "what must happen on the client" and then "how do I deal with invalidations".
A more complex example is ecommerce: Each product can be a component that's mostly rendered serverside, with the names, descriptions, etc. all coming from the DB. The images get fetched from S3 or Imgix or wherever, then next/image adds progressive rendering, blur thumbnails, and responsiveness to them. The pricing data component changes maybe once a day, and is statically built and invalidated not on a timer but a specific invalidation tag. The inventory level, however, is completely client-side (shows a React suspense while loading, nothing if JS is disabled)... that goes through a serverless func that pulls it from the latest DB tables/KV store/whatever.
All of that is out-of-the-box functionality for Next.js, and it can all live in one single codebase -- frontend and middleware and API routes and serverside and clientside stuff, just in different folders with file-based routing.
It can be really powerful, but it's also a lot of overhead and mental complexity if you just need a barebones clientside SPA (which Vite is great for). With great power comes great... need for debugging?
Now, a lot of these principles can be offloaded to a real backend too. You want to make serverside components and send them over the wire as HTML, cached on a CDN? You can do all that with standard backend software and keep the frontend light. I don't know what you've implemented in Python/FastAPI, but if it sounds like it's duplicating some of the features of Next, it probably is.
Next makes a lot of sense in an all-JS team, cuz it lets them handle the entire frontend, all the middleware, and some of the backend (minus the actual content) all in the same TypeScript codebase, no Python or Java or .NET or PHP required. (And Vercel is also moving into DBs as a service: https://vercel.com/guides/using-databases-with-vercel). If you have a separate backend written in some other language & framework, it may or may not overlap with Next features. That's why it's an architectural decision, not just a strict frontend comparison.
--------------------------------------------
Now, whereas the above was me trying to objectively analyze the differences... this is my opinion as a user: The App Router is annoying. I loved Next before 13, with the old pages router doing serverside stuff and useEffect() plus dynamic() loading in clientside stuff. It was a pretty intuitive mental model.
The App Router makes things a lot more complicated. Still, I had to learn it, alongside React Server Components and Suspense etc., just to keep up with the latest versions -- especially since I work in a support role now (for a headless CMS vendor) and deal with other companies using Next in various permutations, often with the App Router nowadays.
I understand the benefits it offers, but I question whether the incrementally better UX is worth the much higher complexity and worse DX. The old page router is still available, but it seems to me they're trying to phase it out in favor of the new shiny, which is a shame because it's so much more complex. Maybe I'm just getting old :)
My old argument for Next.js is that it abstracts away a lot of the chaos of the old React ecosystem (where nothing was provided out of the box, not even routing) into a single sleek package. To a large extent that is still true, but it's also true for Vite, Astro, Remix, etc. these days -- they all offer many similar benefits over vanilla React, without the mental complexity of Next + App Router.
But... I would still 100% choose Next for new projects. Like it or not, it is the industry standard (at least for now) and it has the best chance of both still being used and maintained in 5 years, and also allowing your project to grow into its features as needed.
The basic setup with Next, even with the App Router, only takes a day or two to learn and implement. If you use `create-next-app` it'll only take like five minutes to get a example website up and running, then a few hours to get it hooked up to a real backend using prototype frontend components.
But for many months after that, you'll hit subtle differences in, say, `use client` vs `use server` and how to embed one in the other, how to get around its built-in monkeypatching of `fetch()` to cache its results, how to properly implement ISR with sensible invalidations, etc. It's a long-tailed learning curve.
If it were me, that learning curve is worth it. Mostly because I know I can trust Next and Vercel to do their jobs once I learn them, and I'm not going to run into their limitations before I hit my own. And having a large ecosystem + userbase is huuuuuuuuuge for not having to reinvent the wheel, being able to find StackOverflow or ChatGPT solutions, etc.
But YMMV. Build your prototypes in a few frameworks and see which ones are the easiest to work with for your use case, and then imagine your app in 5 years with a bunch of new features, and try to imagine that it's like using that framework to build those.
Good luck!
edit: Heck, screw "5 years". Just imagine 2 years, lol. Nothing in Javascript lasts longer than that.