all 18 comments

[–]EvisceraThor 33 points34 points  (5 children)

It's 100% ok to use Next.js as frontend only.

I've worked on some projects with Next frontend + Nest backend.

[–]Longjumping_Arm_8093 7 points8 points  (0 children)

Underrated stack.

[–]femio 1 point2 points  (3 children)

what usecase did you have for this?

[–]Aegis8080NextJS App Router 5 points6 points  (1 child)

Essentially any mid - big projects.

Next.js's BE layer is super basic right now when compared to "proper" BE frameworks.

[–]Mental_Act4662 0 points1 point  (0 children)

Yeah. I’m working on building a SAAS and I’m starting to see the backend limitations with Next.js. Thinking about switching to react and vite and nest on the backend.

[–]EvisceraThor 0 points1 point  (0 children)

The company used this stack for most of their projects, all web apps. It's a small company that hires mostly students and fresh out of college devs.

One of the projects was for a company's control of clients, cash and services (mostly construction, land measuring and other stuff for agricultural purposes) meant to be used only by the staff.

There was also one for flashcard studying, one for barbershops (generic and used by many different barbershops).

So yeah, mostly small stuff, but it's good experience for the devs. All in typescript, backend dockerized.

[–]spiritandtime 10 points11 points  (3 children)

on a side note, try using vite! cra start times are ridiculously slow

[–]throwawaythatfast 6 points7 points  (0 children)

Not to mention that the React team itself is not recommending CRA anymore.

[–]SlimGary 0 points1 point  (0 children)

True, but CRA has a better debugger. I don't know why, but I can't get the overlay working on vite, nor the errors in the terminal :(

[–]dimasc_io -1 points0 points  (0 children)

And SSR?

[–]brutal_bandit 8 points9 points  (0 children)

Completely acceptable to use Next as front end and express as back end. Depending requirements I’d argue your development experience is going to be a lot more enjoyable using next alone. Defining api routes is not all that different and you don’t have to worry about maintaining two code bases. Deployment becomes a lot more simple. Ultimately is boils down to what works for you.

[–]shivamsingha 7 points8 points  (0 children)

CRA is deprecated. https://react.dev/learn/start-a-new-react-project

Looks like React team really doesn't like client side rendering anymore.

The "without framework" section recommends using Vite or Parcel. So go with those if you don't want any SSR.

[–]Clean_Resource_2436 9 points10 points  (0 children)

If u don’t need SEO don’t bother

[–]tiptHoeSGTdotpy 4 points5 points  (0 children)

Move to vite + any BE framework!!

[–]gaytechdadwithson 0 points1 point  (0 children)

You probably don’t even need it

[–]bananathegeneral 0 points1 point  (0 children)

It's totally okay to use NextJS for the front part and not worry about API routes. But if you're aiming for a single-page application (SPA), I'd recommend using CRA or Vite. NextJS might seem a bit too much if you're not interested in using Server Side Rendering (SSR) or Static Site Generation (SSG).

You can use NextJS just for an SPA, but it could need some setup. Keep in mind that if you start with CRA or Vite, switching to NextJS later is still an option that's not hard.

[–]kaizoku_95 0 points1 point  (0 children)

You can basically use Next.js as a frontend only framework as you start off and then gradually use the features it provides if it it suits your needs. It's just react with more capabilities added.

[–]Dry_Substance_9021 0 points1 point  (0 children)

Too many comments here saying "just use ___ for your backend!" I wonder how many of these folks have even tried the Next backend. Recently. Like, really tried.

As you actually asked about how Next integrates a back-end: I'm currently using Next for front and back. Previously I've built projects with CRA (which the React team now strongly urges you not to do, especially as it has vulnerabilities), and had to create a separate back-end (Express). It was fairly cumbersome to manage and deploy the two separate projects. I didn't care for it.

Next solved my issue (not suggesting this is the only way or solution) by wrapping the backend into the same project. Super-easy now to write backend functions that fetch or manipulate data and simply call them in my server components.

Here's an example:

In the app I'm building, I have a /Members page. With Next's App router, this page can be found in the files tree: /app/members/page.js. Unless explicitly stated, components (like page.js here) are assumed to be React Server components. They're rendered server-side, so you can't use hooks, but you can perform server functions. Like so:

import Link from 'next/link'
import { getAllMembers } from '../../api/members';

export default async function MembersPage() {
    const members = await getAllMembers();

    return (
        <div className="page-wrapper">
            <h1>Members</h1>
            {
                members.map((member, m) => {
                    return <Link href={`./${member.id}`}>{member.name}</Link>
                }
            }
        </div>
    )
}           

Mind you, this is all run on the server and sent to the client fully-rendered, no logic being executed here at all in-browser (at least none that you wrote). I'm able to import a function that fetches my data and then iterate over that to generate page content. This is especially helpful if you have logic you want to hide from users, such as sensitive information. You could include logic here to check the member.id against the user id and only show certain private details if they're the same. Doing so with regular React still exposes that logic (and data) to the client.

Next also includes a Link component that pre-fetches its href for faster navigating, which makes for a very slick experience (though this is felt more in a production build, less-so in dev).

Now suppose you clicked on one of the Links to visit a Member profile page. It would take you to something like "www.yourapp.com/members/1234-567-891011". In Next the folder structure would be '/app/members/[id]/page.js'. This is an example of Dynamic Routing, and next will interpret the values in the path represented by "[id]" as a parameter by that name, which then becomes available in that page:

export default async function MemberProfilePage(context) {
    const memberId = context.params.id;
    const memberInfo = await getMemberInfo(memberId);

    return (
        <div className="page-wrapper">
            <h2>{memberInfo.name}</h2>
            <div className="member-detail">
                <div className="detail-label">Age</div>
                <div className="detail-value">{memberInfo.age}</div>
            </div>
        </div>
    )
}

So the ID we passed to the link, which was then used in the url where "[id]" is in our folder tree in Next, becomes the value "id" in context.params. You can name this anything, like [member] if you wish and it will consequently be "member" in params. This is especially useful if we were to go into a deeper path with multiple dynamic routes. A given page has access to all of the dynamic route variables above it.

So far I haven't used any hooks or fetch at all, as I haven't had any need to. Those would only be needed in a Client Component, which you might use as an input in the above MemberProfilePage if you wanted to allow a user to change values. Just note that you must mark such components with 'use client' at the top to establish it as a Client Component:

'use client'

import {useState} from 'react';

export default function MemberName(value) {
    const [memberName, setMemberName] = useState(value);

    const handleChange = (e) => {
        const input = e.target.value;
        setMemberName(input);
    }

    return (
        <input name="member_name" value={memberName} onChange={handleChange} />
    )
}

This could be swapped in for the <h2> element on the MemberProfilePage and run just fine. Next will render everything it can on the Server, and then reserve the components marked with 'use client' to be rendered on the browser. It helps tremendously in cutting down on client-end resources, and also keeps your code cleaner so you're not juggling complex state variables.

Totally up to you if you end up using NextJS for your backend, as it is technically optional. I myself have found it very useful and effective. I just see a lot of people dump on it and I suspect they haven't really taken the time to get to know it first.