Hacker News new | ask | show | jobs
by BigJono 1728 days ago
> Therefore, we've elected to render our application completely on the client. On Next.js this means that we wrap our React app in a "client-side only" component that looks like this:

> <pointless confusing newb-unfriendly code that invokes one of the most esoteric parts of the React API>

> This component only allows our React code to render inside the browser environment, minimizing Next.js' server-side render runtime.

Yep, sounds like a practical way to do what is literally the default.

So does the 4 paragraphs of clusterfuck about integration between Next and Apollo. How many brain cells did your team kill figuring that one out just to decide on client side rendering?

I've been using React and webpack for 6 years now, and interfacing with Rest APIs dependency-free using the standard library for at least as long as fetch has been around. All the commenters here are musing about how back end is so solved and front-end is a mess then lauding OP for posting about his "practical" stack at the same time?

This stuff is literally the entire reason front end sucks. Front end has been solved for ages with a couple of simple dependencies and all anyone wants to do is write blogs about over overengineered and/or VC funded fadtech because they're terrified of having to write a few lines of simple code.

It's not normal to just randomly spend a year "upgrading" to stuff that's barely been popular longer than that. I've been on projects that do just that, then on the next project we'll build a much bigger app from scratch in 3 months with 1/3rd of the team size.

5 comments

Agreed. Having worked extensively with GraphQL, I’ve come to see it as a MASSIVE source of unnecessary complexity in almost all cases. Haven’t worked with Next.js, but using an SSR framework, then not using SSR, seems like a tonne of unnecessary complexity too. They even say:

> At Liferay Cloud, our project lives behind authentication and our clients are enterprise-level, with relatively modern browsers and powerful networks. So, SEO and client-side limitations are not concerns for us. Therefore, we've elected to render our application completely on the client.

So, why are you using an SSR framework then?

The FE stack at my current co. is React, MobX and TypeScript, powered by REST APIs that are well documented via OAS. It’s a very nice, easy to learn and maintain stack.

GraphQL's biggest problem is that it dispenses with the concept of Interface Segregation (from SOLID). Instead of having more, special-purpose, API interfaces (which RESTful APIs give us) we bring all the problems that SQL introduced for interfacing with RDBMSs in the 1970s (that have been plaguing us for 50 years now) into the realm of front-end application development.

GraphQL is popular because it helps rapidly develop backend services. BE devs don't have to spend as much time wiring up end-points and serializers. But it just shifts the problem from the BE, where it belongs, to the FE where it doesn't. Like you said, it makes FE development needlessly more complicated. Now, instead of focusing on view-related concerns, which is the point of your front-end, devs need to understand more details about the BE's domain model (unnecessarily) and need to use a text-based query language to communicate with the services. It is pure stupidity.

> So, why are you using an SSR framework then?

Great question; I should’ve mentioned this more concretely in the post.

I would’ve nuked Next completely, but we like the filesystem-based server and the ability to add imperative server-side logic cohesive with each page (getServerSideProps). In the past, this logic ends up on a separate server file and it’s less cohesive. Next keeps things a bit more organized for us.

I like your stack. What’s your use-case?

I haven’t used Next, can you explain this more?

> the ability to add imperative server-side logic cohesive with each page (getServerSideProps)

Our use case is an administrative web-app for managing a transportation network. i.e. you’ve got a bunch of cars and buses driving people around, you can use the admin web-app to see a live map of all the vehicles, see their itineraries, book driver shifts, configure rules about fares, where people can get picked up and dropped off, etc. It’s a mix of highly live/interactive content, and more static content.

Totally. With Next, your page component can export a getServerSideProps function which is used by the Next server to fetch any props necessary for the page component server-side on-demand. There’s a variation of this function for static builds called getStaticProps, which runs at build time to fetch data for props. So, even if we don’t render anything server-side, we can still run logic/fetches/etc. on the server side when a particular page is requested. This could be useful for dealing with sensitive data, for example.

Sounds like a cool app. I definitely see plenty of opportunities for static content there, like you said, but proper state management is vital for the real-time stuff.

Even if not using the SSR part of next, it is still a great build tool, with sane defaults and possibilities of static generation.

What would you use to "simplify" things? Your own webpack config?

How do you keep your openapi spec up to date?
Not the user you were asking, but the way we do it is that the OpenAPI/Swagger spec is auto-generated from server-side code (a C# .NET app with the ABP framework) during the CI build, and that is then used to auto-generate an API client (via swagger-typescript-api) which is what the frontend app uses.

When the backend team makes some changes, they notify the front-end team which then runs the auto-generation script, fixes the typescript errors (if there were breaking changes), and that's it. Pretty nice setup, IMO.

Nice!

Why not re-run the auto-generation script automatically?

We use these types all over the app, manual intervention is very often needed.
We edit the OAS with Stoplight Studio, and enforce it with server-side middleware, which validates that requests and responses conform to the OAS (400s if requests don’t conform, 500s if responses don’t conform).

At a previous workplace I’ve used OpenAPI Generator to generate clients and server stubs from the OAS, which is a nice approach to ensuring you’re confirming to the spec, too.

Did you have the requirements for users that you do not know want to define their own API upon your data?
No, it’s never come up. This is touted as a selling point of GraphQL, but IMO is mostly solving a problem that few people have. Having worked a lot both consuming and producing external APIs, people seem happiest with idiomatic, well documented RESTful APIs, they don’t want to learn some complex RPC system like GraphQL just to use your API.

I think these GQL benefits are somewhat legit:

1. Fetch in one round trip what would take multiple with REST

2. Fetch only the response fields you need

But honestly, 1 generally saves 0-1 round trips, and for 2, while response payloads are smaller, GQL requests payloads tend to be huge, so it’s largely a wash. At least in my GQL usage, they’ve been minor wins, not worth the complexity that GQL adds.

I probably should’ve clarified that this stack is geared toward our enterprise-facing cloud dashboard. There’s a lot of data flying around and it needs to be displayed real-time. But most websites really don’t need this stuff. Front end needs to learn what backend has figured out: the stack has to fit the use-case.

I probably should’ve titled this post better, since I’ve been wanting to write more about how to make appropriate front end tooling decisions in general... not just our extremely dynamic use-case. The entire web seems to be running bloated React apps despite most sites’ needs being solved by the old stuff or new things like 11ty.

Just to clarify as well (since I didn’t in the post), we’re still using Next despite nuking the SSR because the filesystem-based server is useful to us and we like the patterns they provide for running server-side code.

I was excited about this post, saw the stack, and noped out of there. I was hoping for a really simple approach but this ain’t it.
I’m hoping to write a more general post soon about selecting tooling per-use-case, which certainly should not result in this overpowered and complex stack in most cases.
Do you know any good repos I could look at to see how actually practical front-end applications look like? Of course, keeping in mind it does all you'd expect a typical web app to do like CRUD, etc. I feel like I'm deep in the rabbit hole of Next.js + Apollo GraphQL but am interested to simplify whenever possible.
I've been doing web dev for almost 10 years and I've been extremely impressed with Next recently; I think it's the most "practical" framework out there right now assuming you're not wanting to go 100% client-side or 100% static-rendered (you can do each of those on their own very easily without it). The way it lets you mix both, as well as server-rendered where needed, is a game-changer.

I'm more ambivalent on Apollo/GraphQL, but I know some people have been happy with the decision to use it

We use Apollo at my new company and I have mixed feelings on GQL so far, but I asked HN about it and lots of people had positive anecdotes: https://news.ycombinator.com/item?id=28488259
Do you have any examples of JWT refresh token auth for Apollo? I'm having an absolute nightmare figuring it out
Specifically, are you referring to JWT with Apollo client on the server-side?

On the client-side, you can just use a link and get the cookie into an auth header that way. On the server-side, you need some way of getting that auth token from the cookie and passing it into the server-side runtime so that you can insert it into the auth header via a link in each server-side Apollo client instance.

Sorry, that stuff was already set up when I got here