
The UI Framework Wars – Picking the Winning Side for Exalt.gg! – Part One
Setting the Stage
Web developers these days have become accustomed to building amazing applications on the web, and doing it largely on the client-side. With modern technological advances (things like serverless functions, cloud computing, microservices, etc), application complexity is becoming more and more common on the client-side. And technology library developers have not left a need unfulfilled! Recent years have seen the introduction of a plethora of client-side (and sometimes both client-side and server-side) frameworks. But, the real question, you may say, is “which one should I use?”
Unfortunately, this isn’t an easy question to answer, even though we get asked – often. It often depends on the problem you’re trying to solve, but when deciding what I wanted to write about in this post, I realized that while I can’t generically answer that question for everyone, I can describe the pros and cons of some of the bigger ones, and what we’ve experienced through using them. Hopefully, this will help you to answer that question for yourself. Now, there are quite a few similar posts out there. But, many of them are biased in one direction or another. At Richter Solutions and Campfire Studios, we truly try to choose the right framework for the product we’re building, so I’m hoping that my attempt at objectivity will provide some insight which might be lacking from other similar articles.
Oh, one more thing. While I’ll share some code in specific scenarios as we go through the explanations of each, I’m really going to try to keep this high-level, looking at the features and specific benefits and detriments that we’ve experienced in our usage of each framework.
That was a ton of prose. Let’s get to the important stuff.
But, my developers already know <x>…
Hogwash. If you hired these developers and they’re not willing to use the appropriate tool for your product, then I assure you, you don’t want them working on your product. You wouldn’t want a general contractor to break the edges of your polished granite countertops with a hammer to fit into position, right? No, you’d want them to use… I don’t know, a file or a sander, or a precision cutting machine or something. Listen, I’m no handyman, but if I saw a contractor standing over my granite slab with a hammer, I’d have a slow-motion “Nooooo…!” moment, and probably fire him after a short check to verify the integrity of the granite. Unfortunately, most product owners don’t feel the same way about their products, for some reason.
Along these same lines, I should point something else out when it comes to developers. While you can definitely take it too far, a developer is building an essential piece of your business. Therefore, before you hire them, please ask the difficult questions. I’m a firm believer that talent and passion is far more important than experience. While it’s true that a developer can look most things up on Google, what you want is the person who is going to look at more than just the first answer that shows up on Stack Overflow. You want the guy/girl/other that is going to make sure they understand why that solution works. You want the one who is going to make sure that it’s the right solution for the thing they’re solving, not just a solution that “works”. Where does that come from? Passion. I should really right an article about team composition and culture next. It’s probably the second most important thing to the success of a product, following reasonably behind marketing.
TLDR; Most decent developers can learn a new modern framework and become effective with it in a couple weeks. Don’t use this excuse for your developers. Good ones wouldn’t use it for themselves.
Framework Decision Checklist
“You’re starting with a list?! No, Kyle, not you too.”
Yes, we’re starting with a list. Why? Because it’s actually an important part of the process in deciding which framework is the best one to use!
When choosing a framework for a project, typically we ask a couple questions about the framework in relation to the product we’re building. Some of the questions here may seem silly, but we’ve learned that when you make sure to ask them, there’s no chance that you miss something because you didn’t ask. Misinterpretation happens much more than people like to admit, and by simply asking as many of the questions at the start, you can eliminate a lot of misinterpretation. If there’s a question you don’t have a clear and easy answer to, you should stop, find the answer to your question, and then begin the process again. While this list is not exhaustive, it should give some idea to what you should also be asking. Though, to be fair, it’ll probably need additional things to be applicable to you and your product.
Alright, alright! Where’s the list?
- What is the overall footprint of our application?
- Will we have nested routes?
- How important is lazy-loading of modules in our application?
- What browsers are we targeting to support?
- How would we like to manage state in the application?
- Is the application going to need to use a state management library?
- Will the same data appear in multiple places throughout the app?
- How frequently will data update in our application?
- How would we like to manage access to restricted views in the application?
- Will we be building a library of business-specific componentry which we’ll use throughout the application, or will there be many one-off components?
- Will this be a single-page application (seems silly to ask these days, but it should still be asked)?
- Will we want to support the Web Monetization Initiative?
Okay, we have our very simple list. Now, how would we use this to decide which client-side programming framework we should use for our product? Shoot, we should have a product to compare against our list. Going through our checklist can be one of the hardest parts of deciding which client-side framework to use, but when we’re done we’ll be able to walk down the list of frameworks and mark them off one by one until we find the perfect match. If only dating was so easy. I know what we’ll do. We’ll use a product that we’re currently developing at Campfire. Let’s use “Exalt” as our topic:
- What is the overall footprint of our application?
- On the whole, Exalt is a very large application. However, it will actually be split into two smaller applications: the Player Dashboard, and the Organizer System. So, let’s look at each individually.
- The Player Dashboard is a portal where players can track their history with games. Matches they’ve played, people they’re following, events (tournaments) they’ve participated in or may want to participate in, and conversations they’ve had. They will have a profile. They will be able to search for players, events, and game products in a very comprehensive way. They will be able to register for events, get notifications for pairings, and view their standings for each event they’re participating in. They will also be able to see how their matches have affected their ratings for each game, and their aggregate rating for all games. Because it’s a gaming platform, it should make use of modern advancements with relation to animations and other UI glitter. Summary? The player dashboard is huge.
- The Event Organizer System is a platform where organizers can create and manage their events for any game they run events for in one place. Organizers will have the ability to set prize information, choose a pairing pattern, set rules for who is allowed to enter their event (e.g. only players with a Magic rating of greater than 1800), set event timing information (start time, end time, round times, etc), create peripheral side-events, and will be able to export the results in a properly formatted result to be submitted to the rating agency for the related product (Magic, the Pokemon Company, Riot games, etc). Matches from these events will also automatically apply to the players’ Exalt rating history. They will also be able to link their PayPal account to the platform, so that players can register online, and they can be paid automatically. Finally, organizers will have a dashboard with widgets showing relevant business information related to their events (how many unique players have joined their events, average number of participants per event, etc). Summary: The actual UI allows organizers to do quite a bit, and there will be some fairly complicated componentry, but most of the complexity will be on the server-side. The client-side for this is actually pretty simple. Simple forms, and a couple views to view their events (past, present, and future).
Whew, that was a lot. But, that’s a difficult question to answer, and while this list is not in order of importance, I would argue that it’s the most important question here. Why are we building this? What is our application going to do? Are the two most important questions we can ask as business or product owners. Okay, lets move on in the list. Things should be downhill from here. Question one? Exalt has a large footprint.
- Will we have nested routes?
- When organizers are creating events, each step in creating an event will have smaller steps to take. We’ll want to break this up to make the overall step consumable in small, bite-sized chunks. In addition, player profiles will be split into a couple nested views for a couple reasons. First, we want to only display information the user wants to look at. Second, we only want to have to load the minimal amount of data possible. Trying to load everything about a user from the onset would result in longer initial load times, which would result in user frustration and bounce. No thanks.
- How important is lazy-loading of modules to this application?
- Because the user can only digest so much information at once, anyway, we want to break up the viewable spaces in a data-relevant way. We don’t want a huge dashboard showing them their match history and their profile and the events they’re currently participating in, all at once. Hello, old newspaper websites. Because we have so much data in the platform, and it’s all individually contextual in nature, we’ll definitely want to lazy-load our modules/components. We don’t want to send the entire application, when they player is only interested in their current events.
- What browsers are we targeting?
- The answer to this question will often come down to whether your product is a consumer application or an internal business application. If you’re building a consumer application, it’s much easier for you to dictate what platforms you will run on (though, it’s generally best to support the largest range possible, as to not alienate your users). If you’re building an enterprise application for a big corporation, then often you will be told which browsers you must support. For your sake, I hope it’s not IE. *Shudders at the thought* For Exalt (a consumer application), we are supporting all major browsers, most of which are built on web-kit. We will not be actively supporting IE (any version), but will support Edge.
- How would we like to manage state in the application?
- Notice that the question was not “How will we manage state in the application?” It was “How would we LIKE to manage state in the application?” Most applications these days default to using Redux or some Redux variant for managing the client-side application state, without much thought to why or whether its really needed. Let’s determine how we’d LIKE to manage state for Exalt.
- We will have page-level data, and would like to break out nested components by responsibility, with components only caring about the data which is directly related to them. Our application state model will be quite complex, as not only will we have a ton of data about players and events, we will also want to manage the UI state for users of the applications. We will want to maintain which sub-view a user was on in the event-creation work-flow, for instance. This will require extensive application state management, and said data will likely be shown in multiple places (albeit in different ways) in the same view. Therefore, it’s probably a good idea to use Redux or a Redux variant in this application.
- Is the application going to need to use a state management library?
- Through the process of determining how we would like to manage state, we determined that it was probably a good use case for Redux. So, yes. We will use Redux (or some variant).
- Will the same data appear in multiple areas throughout the app?
- Yet another indicator that we should use Redux. A no to either this question, or a different answer to (5) would have changed the answer to (6) and made it a much more relevant question.
- How frequently will data update in our application?
- What an interesting question! Many apps take the load once on request approach (which requires a refresh of the application or an “update data” function in the app), which is fine in most cases. Some still, use a caching approach, invalidating information in the store after a certain number of visits to a view, or a certain amount of time. Sometimes, this is okay as well. Though, admittedly, cache invalidation strategies can be complicated and lead to code smell. In our case, though, we have the need for real-time data in many places of the application. We want to update players in real-time whenever they’ve received a notification. This could be because of a new pairing in an event they’re participating in, an announcement for that same event, or due to things such as someone commenting on a thread or following them. So, we need to make a decision. For Exalt, we’re going to say that for non-realtime elements we’ll use the load-on-request strategy, and for real-time elements we’ll use a combination of Server-Sent Events and Websockets to retrieve data. Also, since our data is related to actively running events at the root, we can say that data will update frequently in Exalt.
- How would we like to manage access to restricted views in the application?
- Managing access to views in a client-side application is very difficult, as technically the user has access to all of the code currently loaded on the client. If we answered yes to the question of lazy-loading then the path forward becomes a little easier, and some frameworks provide implementations for a “Route Guard”-type element, so if that’s needed, it could push us toward one framework over others, due to simpler implementation. Ideally, we’d put a route guard in front of the resolution of a route, and not even let the application get to the point of resolving the code for a lazy-loaded module, but we can dive into this a bit later, when we start looking at what different frameworks provide. We could also send a request to the authorization server in a pre-route hook, or we could build a custom pre-routing solution that looked at our authorization model to determine if the user has access to the view before actually performing the request for the app to go to the route. In this case, we would also want to put preventative logic in restricted views in case a user manually skirted our precautions and went directly to the view. A number of options are available, here. Client-side authorization strategies could really be an article all on its own. Maybe I’ll get to that, as well. It’s a very interesting topic.
- Will we be building a library of business-specific componentry which we’ll use throughout the application, or will there be many one-off components?
- Because Exalt is part of the much larger effort behind many of our games, and we’ll likely want a consistent look and feel across different exposed applications, the answer in our case is a resounding yes, we will have a component library for the Ignition platform.
- Will this be a single-page application (seems silly to ask these days, but it should still be asked)?
- It will be a large container single-page application, housing two smaller single-page applications embedded into it.
- Will we want to support the Web Monetization Initiative?
- This is an important question to ask, because the direction of the industry and emerging technologies indicates that this will be the way of the future. For Exalt, which will be following a free model with the ability to acquire a subscription for access to certain features (and for organizers), it really isn’t the approach we want to take. That’s not to say that it doesn’t end up being the right solution in the future, but for now, I don’t think Exalt is a good candidate.
Holy moly. That was a lot, right? It was, but now we know exactly what it is we’re building, and even made some decisions on things without even thinking that we were doing it. This process can be intense, but by doing it, choosing the right tools to use will be a breeze. We have essentially detailed the goals of our product, the needs and desires of the technology team building it, all based on the requested features from product ownership. This is similar to some of what we would do on initial creation of a storyboard for an agile team on a new product. We’ve defined the big blocks that are needed
In Part 2 of this article, we will begin to look at how the things we outlined relates to what is available in modern client-side frameworks, and how we might go about deciding what is the best tool, even when they may seem very similar. I assure you, they are very different in what they do, and we’re going to take a deep dive into what those differences are.
Until next time, “Stay classy, interwebz.”
Kyle Richter
President & C.E.O., Richter Solutions & Campfire Studios
Comment