You have an idea for an application and you want to build it fast and effectively.
If that happens to be the case, let me tell you that this article might just help you get started with it or at least get you motivated enough to give it the ol’ college try.
The idea behind this nitty-gritty application was to create a dashboard for an auction where one can enable a fantasy bidding session for a FIFA tournament — I mean the one where you slog-out in front of a gaming console — so as to build your own respective team and build a sense of ownership. The requirement was straight forward. The difficult part followed soon after. Turning that idea or vague imagining into a working application. And I jumped straight into it.
Let’s talk about the essential stages of development concerning the application and certain phases once it was done. All set? Let’s go then.
I was aware that I had three days maximum to code out the central structure and at the same time I was in the mind-frame to brush up on a few of the concepts I had worked on earlier. Thereby, the tech-stack part was rather pretty easy to decide. And given the fact that this was supposed to be a pure front-end application and sported more as a Proof of Concept (POC) than anything else, I knew which tools I would pick up to hammer away at this. Here is a list of all the frameworks and libraries I decided to make use of.
Redux: A state management library which enables faster and easier maintenance of states throughout the application. It gels in well with React.
React-Loadable: One of the best solutions to code-splitting available to React. Easy to implement and has a simple-to-understand documentation.
React-Flexbox-Grid: This library imitates a flex-box format for building responsive layouts fast. It has an easy-to-comprehend syntax and can be easily incorporated into any react boilerplate template.
That basically covers all the tools I needed. I decided to style the application manually using CSS modules. Although there are multiple styling frameworks available if one doesn’t wish to expend so much effort. Let’s talk about the structure and the general flow of the application.
The visualization is probably one of the essential steps. But more than that, it is paramount to make sure that you are able to draw a map that leads you, as an end-user, from the start of the application to the end of it. Here is a rough sketch of the user journey visualization.
Having created this rough image, we start breaking down the application into pages and sub-components. One thing during this entire process which was clear to me was that I needed to make the application super-easy to use. Given the fact that I sincerely lack User Experience intuitiveness, I decided to refine this aspect as much as I could.
After the initial break down, I decided upon the four primary tasks that the application needs to take care of.
- It should allow one to select their respective clubs before the bidding process kicks off.
- It should be able to sell/pass off the players and at the same time monitor the selected clubs’ budgets and squad size.
- It should be able to display the squads formed at any given instance.
- It should display the list of all the players along with their current status.
Having outlined the primary tasks, I started to decide upon the components to be utilized and the manner in which the local state is supposed to be persisted throughout the application. Not using Redux in such a case was a clear no-brainer as it immensely helped to maintain the general state of the application and came super handy especially when it came to persisting data, using the local storage of the browser.
Note: The players’ and clubs’ data had been extracted earlier using Node.js and a few web scraping libraries along with certain reference data, which was obtained from Kaggle. All this data was clubbed together in the form of a couple of JSON files and was used as the primary data source for this application.
Let’s take a look at the main pages, components, and their respective functionalities.
As discussed earlier, the team selection page has three main functionalities that needed to be coded out. These were basically:
- Search through the clubs’ data
- Select/deselect the clubs available
- Map the selected/deselected clubs
Reducers and actions coupled with React events were mainly utilized for this particular page. This page denotes the landing page to the application (if you have not happened to use this application of late).
The trophy page of the application is the place where all the action happens. This page is supposed to be the center-place where the bidding will be conducted, keeping in mind the three tasks that this page is designed to accomplish. Namely:
- Price setting and select a bidding club for the current player on bid
- Monitor the budgets and squads of the participating clubs
- Sell/pass off the player on bid
- A glance at the next 5 players in line for the auction
This component has a lot of state changes occurring in a single event and has to be handled simultaneously.
All the formed squads are visible at any given time to be viewed. This component is a simple view-based component to enable a user to monitor the players one has purchased during any given time of the bid. It enlists the players along with their essential statistics.
This component mainly requires mapping functions to be called upon regularly.
Another straight forward view-based component. However, this was relatively much more challenging to get right as compared to the previous one. The biggest challenge in this particular component was that we had to not only render but also be able to filter across 18,000+ data points at any given time.
The initial page load was taking around 9 seconds and it was a massive overheard being incurred as far as the application’s performance was concerned. That was a matter which had to be addressed once this component was in place.
Skimming across the structure helped in providing me with much more clarity concerning the look and feel and the way in which the application was supposed to function.
In a simple user journey map as discussed throughout this section. Anyone can go to the application — taking up the auctioneer role — and select the clubs he wants to feature in the auction. Having done that he can accept a bid for a player and sell it to a participating club. Or simply pass off the player in the case of no-bid having come forth. The application helps ensure that the auctioneer need not worry about the calculative costs and data maintenance. Thereby, enabling the auction to go smoothly and without any hiccups of the sort.
However, let me point it out. The application was far from optimized by the time a single flow was complete. Let us have a look at that.
I understand that the application was built in a hurry with dirty, effective code snippets. Having said that, one cannot just let the existing issues/bugs/shoddy practices affect the general functioning of the application. I agree that there were/are bugs in the application but it is still more than stable enough to be utilized.
There were mainly three areas that required optimization. Here are the areas of concern spotted and the measures taken to take these concerns off completely.
Players’ List Rendering
Rendering more than 18,000+ data objects using a mapping function and filtering through the list had tremendously reduced the efficiency of the application and the delay was huge. Approximately 9 seconds, to be precise. In order to tackle this issue, I had to resort to a recursive strategy of rendering one element at a time followed by a setTimeout() function until the entire list was rendered. You can find the recursive code snippet below.
This strategy tremendously improved the code performance and reduced rendering time massively. Going from 9 seconds to a mere second or under to start rendering the players. A load off our heads, there and then.
Chunk Creation for Faster Page Operations
Another major concern was related to the manner in which the final bundle was handled and its consequent performance. Given the fact that we have the entire data source (which is around 4 MB of file) in the front-end, it is required that it does not reduce the page-load performance of the application. Normally without using any code splitting mechanisms, the bundle created was not only rather large but also had to be loaded on the very first load and every time the application changed routes.
This is where React Loadable came to the rescue. I used it in the core route module to minimize the respective chunks loaded. This enabled me to easily call and load the respective pages. You can see the various chunks created and the minimal sizes of each chunk bundle. Code-splitting just became headache free.
Persisting Data Locally
One of the challenges of keeping the application in a stable, working state is to be able to persist the data on the front-end completely. Thus, every time an end user refreshes a section of the application, it switches back to the initial data point rather than persisting with the current traversed state. Not a great experience after all.
The fastest, dirty and effective — although least secure — way to deal with this situation is to make use of a browser’s local storage especially since we need to get this application up and running. And voila I decided to go with this approach and as a result, I was able to persist the selected clubs’ as well the modified players’ list data.
Dirty but effective none the less.
That wraps up the optimizations’ section. Let me point it out that this project is still subject to further enhancements. So most probably, the dirty code might just start to smell less, look clean and more effective as time goes by.
It was fun visualizing, designing and coding out this simple, small application. I got to re-explore certain concepts like code-splitting and local storage data persistence. The point of developing anything is to have fun in the process. And that is exactly what I happened to experience. I hope you feel the same as you run through this article and get that bout of motivation — no matter how small it might be — to get your idea from a mental thought to a visible application or prototype.
You can find the entire code for the application here.
And you can play around with the application on this link.
Time to code that idea. If you have any comments or questions, feel free to reach out to me or you can post it here in the comments section. I promise I do respond pretty fast.
Keep Coding, Peeps!