Practical Front-End Architecture
jaredgorski.org
jaredgorski.org
Every time I think of making an SPA for a side project I hit up create-react-app, look at the uncomfortably blank canvas, and go back to Rails with ERB. TBF for most purposes Rails + Turbo gets you really, really far - just look at GitHub.
Rails without a JS frontend is excellent in so many cases. The trap is when you start adding a little JS here and there to make things nicer, but soon you end up wishing you had just started with a fully JS frontend.
What I'm hoping for is a configurator/wizard where you can choose your options, and then you get a fully functioning foundational system to start from. Yes we can do it all by hand, but especially when it comes to auth and some other needs, the configuration can be a bit messy (because some details are always changing).
Not sure if Yeoman is still around but did they not attempt something similar?
And in the case of setup tools, they tend to all suffer from the problem of being very difficult to change once setup. The tool you use to build the customized foundation is often unable to make future modifications if you have changed any of the generated code.
But by now we know the 99% common options people want: a choice of a few databases, (probably but optional) user profiles and auth, etc. The database side is pretty much solved, but the user management is definitely not - and it's the source of so many data leaks.
In a way, it's been superseded by create-react-app and it's ilk, but I think those kind of tools are fine. If you're reaching for a tool like create-*-app, then you've already made a specific choice about a number of things, and it's just helping you to bootstrap the project.
It going to happen again soon with WASM. But I'm welcoming that. We'll probably all end up writing full stack Ruby, or something.
They provided a bit of rationale (kind of sprinkled across the article).
For me using Next over CRA as a default comes down to three things:
- Batteries included, high utility components and defaults for things you ought to stitch together otherwise. CRA is not a drop-in replacement for Next, even if you only render client side.
- Flexibility. Your project might just look mostly static (fully rendered at build time) , or server rendered, or client side rendered. It rarely is. If you default to Next you can easily extend and configure these capabilities (and more).
- Great DX. It's a framework that respects developers with good documentation, flexibility and a "just JS/React" kind of philosophy. There is magic that you cannot easily break through as with every framework, but so far it seems they keep the magic boundary at the right place.
It supports Angular, React, Next.js, Gatsby, Storybook, Cypress, and a lot more.
Maybe people don't hear about it, or they stop after reading the word "monorepo", while Nx is also great for stand-alone projects.
When I learned about OOP I was able to understand OOP code in a broad range of applications, languages and frameworks, but learning how react works gives me no insight into anything but react, and it's even abstracted enough from JavaScript that you could learn React without ever properly knowing how to write JavaScript (which is something I've encountered in a handful of new devs).
This is sort of an expected side effect of recreating nearly-identical JS frameworks every couple months, no?
Considering you have so few language options for frontend webapp development (excluding wasm and other such options), this really isn't a surprise to have a handful of options either. I can name more python server frameworks that are used in earnest than I can name frontend frameworks.
Part of the difference for frontend frameworks is that there's so much variety possible. Nearly every server framework has the same general design and API - some kind of routing, route handler definitions, and some additional niceties like with, db connection handling, sessions etc. I can't conceive of any other design that would work better or even be sensible.
While components have become the norm in front-end, there's still plenty of room for different architecture and actual API to use and define components, and manage state. That's where the fun of writing them comes in, and where there is still likely a better react or vue lurking in the shadows or yet to be created.
What I intended with my comment was to point out that the idea of new frameworks being created every week is a bit of an exaggeration and that it being the reason frontend development is fragmented is just totally incorrect.
React or Vue on their own with a sprinkling of helpful utility libraries will get most projects 99% of the way there though, and often times that _is_ simpler than trying to put together your own system for server side rendered pages and template composition.
Of course, if you're making a blog, you don't need any of this, but for _web applications_, I don't think I'd reach for SSR anymore.
The trends and gimmicks have caused this “walled garden” effect. It’s made both “practical frontend engineers” and “practical frontend architecture” a rarity. If I could write this post again, I’d talk more about how most use-cases simply don’t need a “modern tech stack”.
React is basically a glorified templating engine that attempts to enable reactive mechanisms on the client. Need “reactive”? Consider Svelte as well. Don’t need it? Consider moving the render to the build and use a lighter templating engine.
At the same time, I do know what you mean about the walled garden ecosystems. It seems unfortunate that every framework I pick up, I'm learning a new set of components everyone uses for things like virtualization. On the backend it feels less common to be using a library that's only relevant to your stack, and when there's a killer library in another language, you don't need to move mountains to use it.
This is news to me, are you sure about that? Wasn't react released earlier than elm?
[1] https://egghead.io/podcasts/dan-abramov-co-author-of-redux
GUI development has its own set of concepts and broad applications. React is somewhat novel but still fits squarely in here; the idea of a GUI component is pretty enduring.
Distributed systems development has its own set of concepts and broad applications. With modern tooling, web interactions look just like traditional RPCs.
I programmed "full-stack" through the GUI fat client era, the primitive web era, and now the modern web era. I'm much happier developing with the modern tools.
JSX?
> the days of using string templates to assemble HTML pages was a weird and specialized era.
I gotta say, I think React w/ JSX is far more of a weird and specialized era.
The real difference you're talking about is having the server render each user's UI versus offloading that to the user's machine. Regardless of whether it's via strings, 1s and 0s, https, rpc, etc. Browser's have become a more powerful "general purpose" renderer, so it makes more sense that they'll continue to take on more of the UI work themselves. It's still not as good as a purpose built client though, as sluggish electron apps have demonstrated. And sometimes it might still make sense to render the UI on the server (and cache it) for either / both simplicity and performance.
Occasionally you'll even do a bit of both with a client side app being rendered server side then hydrated... talk about a weird and specialized era.
I agree with you that "client side app being rendered server side then hydrated" is pretty weird. I also don't think this is the future of the web but rather a holdover from the previous HTML-based era. It may never go away; after all, lots of content is very well suited to simple HTML.
create-react-app has so many dependencies and takes a lot of time to scaffold a hello world. Adding some router or some popular library produces deprecation warnings and '2 moderate vulnerability' messages. Folder size will blow up over 1 GB to make trivial apps. That's insane.
Not the smoothest first impression for what's supposed to be the "on rails" introduction to react development.
For a simple production-ready React setup try the following libraries:
- react (obviously)
- redux, and react-redux (which ties react and redux together), and redux-thunk (enables asynchronous redux actions).
- react-router and react-router-dom (adapts react-router for web rather than react-native)
That's 6 libraries, but it's really only 3 as the auxiliary ones under redux and react-router are tiny. If you need to support older browsers then you might also need core-js to polyfill the newer apis, but that's it.
And if you use esbuild to build then you won't need need all the complexity that webpack brings.
We've updated the Redux core docs tutorials to teach RTK as the default [1] [2], and have examples of migrating existing Redux logic to use RTK [3].
As for the CRA aspect: I still don't really understand why some people refer to CRA as "bloated". It has all the standard pieces that have been used in the React ecosystem for years: Webpack for bundling, Babel for transpilation, Jest for testing, and ESLint for linting, and all with a very reasonable default configuration that has had thousands of hours of effort to deal with edge cases.
I'm not saying that CRA is _perfect_. The maintenance has been spotty lately, it's taken a very long time for the Webpack 5 branch to get close to release, and I'd love to see CRA adopt tools like SWC or CRA to speed up builds. But given the problems in the ecosystem before CRA, it's done exactly what it was supposed to: provided a single command to set up a new React app with good build defaults.
[0] https://redux-toolkit.js.org
[1] https://redux.js.org/tutorials/quick-start
[2] https://redux.js.org/tutorials/essentials/part-2-app-structu...
[3] https://redux.js.org/tutorials/fundamentals/part-8-modern-re...
Yes, that's the problem. It has ALL the pieces, whether you are using them, whether you understand them or not. For example, most projects will use either babel typescript. CRA? It has both and extra logic to switch between the two.
I feel like a better approach would be / have been an "open book" config where there is minimal starting point and it teaches you how to add the extra bits you want/need. That way it would be kept as simple as possible, and people using CRA would actually understand the tools they are using.
https://overreacted.io/npm-audit-broken-by-design/
The size of CRA is largely due to its primary dependencies (Webpack, Babel, Jest, and ESLint), which are normal parts of most modern web app build toolchains.
That said, there's plenty of other alternatives. For example, Vite uses a combination of ESBuild + Rollup for its build steps, and has only a relative handful of dependencies. As a result, it installs fast, and creates + starts projects even faster.
None of that is specific to React the UI library, though.
In contrast, when I tried sveltejs, the 'official' way using degit worked sewmlessly, standard dependencies were also much smaller than when I used react.
But I will give a try to Vite, thanks for recommendation!
The a majority of web apps being built today could be created at a fraction of the complexity by using these libraries, and they put full stack development back on the table.
Personally I prefer LiveView from the Phoenix(Elixir) framework. But my day job still uses Rails.
There are similar projects in Django and PHP (Laravel, I think)
Throwing errors to be caught higher up, the way they manage redirects, and the lack of discussion around managing state (which could on its own solve lots of these problems).
So much of this seems convoluted and unnecessary for a very simple goal of building a dashboard. Their use of Apollo seems to provide no advantage over a basic REST API.
There's frankly very little discussion about actual front end architecture. I'd expect a conversation on a React application architecture to focus on things like how is client side state managed? How is server state managed and kept up to date? Are the two mingled together or kept separate? How are they kept separate? How can you build reusable components? How can you avoid components bloating in size and scope etc
Front End development today - especially with React - is so easy to get running with and there are tons of better articles that actually discuss front end architecture including lots of courses on common patterns. Beyond articles, open source projects themselves often provide great architecture discussions.
Higher order components, react-query for server state, react-router for client side routing, building reusable behaviors with hooks are all good places to get started for actual architectural design
I’ve been wanting to write more about most everything you mentioned, but ended up writing about a few interesting patterns we implemented recently. I probably should’ve titled the post “A few interesting patterns we implemented recently”.
As for state management solving the problems of pageload validation (instead of our error boundary and redirect mechanisms), can you provide an example?
As for using state, when you use something like react-router, all those things, path parameters, query parameters etc are stored in state.
You can build hooks that use the hooks provided by react-router to retrieve those values in a useEffect in the relevant components. The hooks you build can be responsible for validating the path/query params, coordinating route changes etc.
The larger idea is to use your state as a means of coordinating messages that any component can hook into. So you could include in each of those detail pages a redirect route component that only fires when the hook you wrote detects that a page is invalid.
To take this to another level. You could build a Higher Order Component that automatically embeds this ability (a redirect component with a custom hook) into your item detail pages so that it's automatic.
By way of clarification, I see route validation and pageload validation as potentially separate. For example, a given route parameter may govern a whole scope of pages in the app, so it makes sense to centralize that route validation logic rather than duplicate it in each page’s validation hook. In a more traditional server (like Express), we can just handle requests which contain that route parameter with a particular middleware function that validates the route. However, if we’re just using Next.js’ filesystem router, we have to add validation in the component tree, in a wrapping component. You’re right that we could make a HOC, but then we would either need to apply it to each page file in that directory or just put it in the App render as a wrapping component, which is what we elected to do.
On the other hand, an individual page may need to run some specific logic to validate that particular load. That’s where the page validation hook comes in. We have a centralized permissions spec in the runtime which contains fallback rules for each page, so we can just update the “abort” callback with each route change so that the page can just bail out of the pageload and redirect the client appropriately.
I don't know how Next.js' filesystem router works, but it seems to perhaps be the cause for this roundabout solution.
You can do middleware in client side routing with react-router similar to how you would with express. That's exactly what hooks are for and you can build your own to enable that functionality at the scope that's needed.
https://blog.nrwl.io/managing-state-in-angular-applications-...
> <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.
> 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.
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.
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.
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.
Why not re-run the auto-generation script automatically?
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?
> 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.
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.
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.
What would you use to "simplify" things? Your own webpack config?
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'm more ambivalent on Apollo/GraphQL, but I know some people have been happy with the decision to use it
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.
Back in the days the apps were unresponsive, clumsy and user unfriendly.
You really can't compare web apps with old websites or even forum software like phpbb.
EDIT: The down vote of the PHP developer which still wants to write phpBB forum websites :)
Good luck with that. I'm waiting for the article that complains about frontend development ;)
It’s certainly nothing new, but the “buzz factor” impresses people who don’t know what it’s for and they implement it everywhere thinking it’s an improvement. The trend/gimmick culture in frontend is a real thing.
The fact that the same code can render the initial static page AND the dynamic client interactive UI is the point here.
Edit: looks like my comment is oddly similar to @d3nj4l's. Nice to see I'm not the only one!
A few other backend frameworks for other languages also have something like that.
The Nitrogen Framework for Erlang [0] is another in a similar vein (and pre-dates LiveViews).
Another is lamdera [1] which I came across on the Elm Radio podcast [2]. I've never used it, but the focus on minimising accidental complexity between front and back end was appealing, (along with the use of Elm).
So any universal solution will have to include strong client side prediction in addition to handling the server (something the game industry has understood and implemented for years, and I remain confused as to why it has gained near 0 traction on the web).
To my knowledge Meteor is still the only frameworks to explore down this path, but it has never really caught on. Does anyone know of any frameworks that acknowledge this issue and manage both server and client side accordingly?
Then there is caching, if your stack is well-integrated and aware of mutations you can respond with 304, or you can intercept requests with serviceWorkers, or edge/cloud workers/functions etc. AKA speed of light or practically instant responses.
When developing an app recently I added an artificial 1s delay to server responses (during development), but because of optimistic updates you would never notice it was there.
IMO, having the ability to separate presentation with backend is valuable.
That said, it's clunky in many ways and (very) slowly losing it's dominance. It's community clings on class based, mutable OO (while even languages like Java expand in other directions). And there are thousands of little gotchas, weirdness-es and limitations that make using the language un-fun and sometimes unproductive/limiting. For newcomers it is a nightmare to fall into all these traps for the first time.
A true PHP competitor however would need to be incredibly accessible and re-imagine a lot of things. I think it would need to fully embrace modern HTTP, HTML, CSS and browser APIs. Deno is seems to partially lean on that direction for example, but that is "just" the server side so it doesn't count. Isomorphic development is a big deal. There is Imba which is also an interesting attempt. Modern languages like Clojure and Kotlin provide the capabilities but not the development accessibility and defaults (personally a huge Clojure fan though).
Is it losing dominance?
https://arstechnica.com/gadgets/2021/09/php-maintains-an-eno...
Much of the effort in the latter part, innovation, products, tooling and marketing at the web frontier seems to more strongly focus on JS/TS/Node/V8/serverless/WASM. When I started with web dev, PHP was the de-facto standard language for small web-shops (Ruby was on the rise, Node on the horizon). I don't think that is true for the next generation of web developers.
Otherwise, what you are describing isn't going to be "Just Go" or "Just the language"... you'll have again a ton of libraries/frameworks on top of it... the complexity is going to be there... one way or another.
That gur feeling like you are missing something important is nothing more than psuedo FOMO. Its complicated and contrived for no good reason at all. SSG are good. Plain HTML is even better.
I would always advocate for plain HTML, or some basic templating engine. But such a statement highly depends on your needs. Plain HTML is great when you know exactly what you're building. As soon as you're going for something a bit more dynamic, or when certain elements require conditions, you quickly move to either SSG or some for of SSR.
Not saying you have to use whatever latest technology people are advocating, but use whatever makes sense to use. Plain HTML has its limitations, that could be solved with SSG or SSR.
I ask vanilla js and low level layout/styling questions in my interviews (not gotcha questions, but instead what I consider to be fundamental skills indicative of experience) and am consistently met with confusion.
Maybe I’m too old for this game and front end devs will never again need to know about addEventListener?
HTML was never gone :) I have and still working on big e-commerce websites.
For example, Ikea for product lists sends mini chunks of simple HTML. No JS involved.
What I see is the problem that people think that "Frontend development is easier than backend development".
For me, they have different challenges and different ways of thinking. Getting a good full stack developer is kind of getting a good doctor, which has at least to specialities.
I hate that statement so much. Even had some serious arguments with "back-end developers" who were constantly mocking HTML/CSS/JS. Turned out that when pushed to do it, they just couldn't do anything and had to ask for help.
Writing proper reusable HTML/JS isn't easy, it also requires thinking on how to structure and split up things. Especially when you throw some CSS into it.
I can assure you those developers mocking frontend devs can't even do backend if taken outside their big ass framework (django, rails, symfony,etc etc), because they believe everyhing is as easy as those frameworks put it to them. Somebody that had to work outside of that where you have to take many decisions and make tons of trade offs and find how to organize code and manage dependencies, etc will understand better how difficult frontend is. True we sometimes overcomplicate things more than needed (redux, rxjs, etc...) but even when we do not, this is still freakin difficult to get right.
Can you elaborate how? like some turbolinks thing?
What you can see in the Network tab is that you get chunks of html from the backend which have all the markup
Other e-commerce stores do that too.
Sometimes these chunks also have js in them.
This always amuses me when it comes from junior front-end devs who are scared to touch the backend because they've never done it before. I always tell them not to worry: the backend is much simpler.
I regret that my post is yet another React promotion. Not intended: architecture depends on use-case. I’m hoping to write more soon about selecting tools appropriately, which probably doesn’t mean React in many cases.
An FEEs job is 90% combine components from the design system with apis from the backend team to implement a UX from the design team (and obviously debugging, deploying, etc.). For this I only care that you know what an Event Listener is or what Flexbox is or what the Box model is I don’t really care whether you know some of the low level details off hand (unless you reference it in a story).
I mean I have a lot of experience with various front end component systems on desktop on the web, including Microsoft stuff and in the browser some Angular, React and Vue. But for my current project which is a little bit involved, I decided to skip React. It is actually working out fine. I assume React devs who see it will suggest that it's time to take me out behind the barn and put me out of my misery though.
SSR, progressive enhancement and all these tricks to speed up load time aren't really necessary if you just keep complexity down and your bundle size small.
Great question. In fact, that question has more to do with “architecture” than most of my post.
The primary reason we went with Apollo is that it’s flexibility-minded and well-documented, making it easier for new engineers to work with. If everything was ideal, we’d use Relay. Relay’s patterns are better (IMO) but it can be confusing for new folks to use it idiomatically. So, it’s primarily a dev-experience consideration for us.
This applies to so very much of web developement. We have spent so much collective time building web apps, and some have also put a lot of time into building libraries and frameworks, that with all the brainpower and effort, things should be easier now than they are.
I believe this is because we've had too much freedom. Not suggesting we should have stuck with C or Java, but it seems that many people who are motivated and intelligent have decided to build their own better mousetrap. So now we have 1,000 mousetraps. Or maybe 10,000. If we could somehow redirect that effort into 3-4 primary options, I think we'd be overall better off.
Take Wordpress for example. You can do just about anything with Wordpress and some custom plugins. It's a miserable experience mostly, but it's possible. Imagine if some of the smartest people behind some of the best frameworks and libs collectively worked on one new system (plugin-based). As long as there were a good plugin interface, the users (devs) could then use whatever language they prefer to provide business logic and customization.
A viable alternative would need to be just as simple, and currently that implies it should probably be implemented in PHP, which will exclude developers who want experience with "blog-friendly" languages.
A good foundation can be in any language, such as PHP. But it needs to have a modern, better architecture with a more consistent base library/API for the plugin writers to take advantage of. WP is like 1.0 of this. We've learned so much in the last 10-15 years; it would be nice to have a completely rethought foundation.
But for the plugins, I think there should be a standard interface layer (based on probably http, tcp, pipes, files, even memory stores for communication). Then plugins could be written in any language, hosted locally or remotely, and sandboxed.
I've never used Apollo in anger, but i've used Relay with Next.js for a few projects and it's been a dream. The biggest downside has been the size overhead of the Relay client itself (approx 40kb over the network), and the size of the serialized data (but that's the same price you'd be paying whether you were using GraphQL or not, just an unfortunate reality of the hydration model).
What has it looked like in practice for you?
For my older (getInitialProps) approach, you can see a rough example here: https://gist.github.com/AndrewIngram/e974f63160af9df292fc39e...
Look at the last file (PostDetail.jsx) to see what it's like using GraphQL as part of a page (PostLayout isn't defined here, but assume it's just a regular React component using Relay's useFragment hook).
We are using every new technology because why not, but we don't think about our use cases.
Things like "/items/12345/detail" let me believe that this is not a spa really? More like a good old MPA?
I'm not sure if the chosen technologies are the right ones for the jobs.
In general, I don't understand the trend to default to something like reactjs. We have and had alternatives.
What I see is that people complain about technologies which are not build for what they are using. To get good performance and bundle size out of SPA like apps, you really need to put in work. Maybe a simple Laravel/RubyOnRails website would have been the better stack for a lot of projects which are right now written in reactjs/nextjs.
I think the reason we have so many fe/js/options is that no one option has jump out as 'x10 better' than the rest.
Svelte for me at least gets close to 'it' - ymmv
Sidenote(sorry for highjack): The ninja hackers/coders out there please code this next:
Like you know how we have tree shaking for dead js/ts code ?(Really cool and impressive btw)
I want to get "html tree shaking" - Im putting it in quotes since what Im after is:
The least amount and/or optimized html that will generate the same 'view/end-result' of my current unoptimzed html.
Maybe a case for optimal-auto-encoder ?
Only real difference in my stack is I'm using redux toolkit query to connect with a Rest API instead of GraphQL (GQL would be nice, but can't have it all).
I'm a HUGE fan of antd! I've been working with it since like 2017 and it blows my mind what I can build in a few hours.
I haven't used tailwind, but wanting to look into it. Anyone have practical advise for using tailwind alongside a component library like antd?
As for “best practices”, I’d say there’s not many problems you’ll run into using something like Tailwind. Any configuration improvements you make probably won’t break anything, but you should still read the docs before you get started.
The difference is that backend is always going to be some variation of CRUD, so the architecture isn't changing too much. front end being the actual user-facing layer means it will always evolve with human-computer interface (UX?).
Mobile phones completely changed the way we thought about frontend, and it's just time until the next big change in form factor comes... and a bunch of new frameworks will pop up
I do get your point though that UI dev probably sees more variation since you need to adapt to the form factor of the user’s device, which changes significantly every few years.
1. The primary reason we chose NextJS (with SSR) was to be able to write a declarative React component that is run on the server and the client. For example a button to follow or unfollow a page (think: like/unlike in social media). In the previous generation of our application, we wrote the button in PHP that rendered HTML and toggled UI state on the front end using JS/jQuery. That meant writing the button logic (and HTML/CSS) in two places instead of one. Now, we have a single React component that renders itself based on state; it's the same component on the server and client.
2. I don't understand the extra work to avoid SSR. SSR is great and can be used behind authentication--there's no actual need to work around it. Additionally, in a NextJS application, SSR is only used on the first page load. When you click from page to page, it's all client-side transitions.
3. @yashap said "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." Agreed. Same here. It's wonderful. In particular Mobx. A lot of the comments seem to say "I expected the article to talk about how to maintain state in a React application"--that's how. Use Mobx. No matter what reactive JS framework you're using, use Mobx to maintain "global" state.
4. The discussion of "why move to NextJS when my Webpack config from 6 years ago works just fine" is a good one. Two big reasons we moved to NextJS (away from a Webpack config from 7 years ago) were: the handoff from server -> client is more seamless and the developer experience with hot module reload for server + client sides was worth it. Any JS application these days is going to be a tooling nightmare: Webpack, Babel, TypeScript, ESlint, React, polyfills, plugins, and then dependencies. That's awful no matter what JS framework you choose. Create React App doesn't fix that, it just hides it for the first step of creating a react application. You still have to maintain all that nonsense.
Doesn't NextJS do the same? The alternative to compare to would be a plain setup without any heavyweight boilerplate. These days you could you esbuild, but a webpack config can be ~50 lines and quite simple if you build it up from scratch.
Happy to expand on this more if you want.
{typeof window === 'undefined' ? null : children
On a related note, thanks for what you do for Next in the discord.Once the client-side JS has taken over, the `next/link` component [1] is used to render and listen to events when a user clicks on a link. That component tells `next/router` to render the page that was clicked on. All of this happens on the client by default. If JS is disabled on the client, then the HTML rendered by the `next/link` component on the server is a simple `<a/>` tag and a normal browser page load occurs.
[0]https://reactjs.org/blog/2020/12/21/data-fetching-with-react...
The React team is working with the Next.js team (amongst others) to make sure there's alignment.
Well not quite. With client side rendering you now have manage state in the browser as well as build API end points for each screen you want to create.
It's a more complicated architecture.
And instead of rendering html or static site generators...we just export everything as one or a few(for responsive) jpeg :) ?
Heaven forbid you’re on a shitty internet connection, these inane js-behemoths just die from a dropped tcp connection, since they’re built on the most optimistic assumptions about network connectivity.
I remember when accessibility was a part of web development, but I guess the ROI was to low.
But I did fail to address a more general decision-making process regarding choosing frontend architecture. If I did (and I probably will soon), I would talk a lot about the egregious initial load times on too many blogs that roll crazy dynamic tools for what should be a completely static site.