A few months ago, I finally found the time and put in the effort to revamp my blog site. Though I was reasonably happy with the application, its original intent was to showcase what I had learned over the past few years and with that mission came some major inefficiencies and complexity. The website itself was very slow to load. It was rendered entirely client-side, made a cross-origin network request on every page load to an external server, and had an unnecessary data abstraction. I mentioned many of these issues in a previous blog post which I will link below. As of today, all of these inefficiencies have been addressed and the site, though still retaining much of the same look and feel, is almost entirely new under the hood.
The first change I made was on the frontend. I knew running a Single Page Application using Client Side Rendering (CSR) was causing a large amount of latency and actually costing more to execute as network requests were made to my backend server, hosted on Google Cloud Platform, with every page refresh. I decided to migrate my React code to Next.js, originally for its Server Side Rendering (SSR) capabilities, but soon discovered that I could take it a step further. Next.js is one of very few frameworks that has Static Site Generation (SSG) as well as Incremental Static Regeneration (ISR). When you implement SSG with Next.js, your React code is used to create static web pages that ship less Javascript and load extremely fast for the end user. When you combine that with ISR, which is an amazing feature that allows you to regenerate individual or groups of static pages when changes are made to them without redeploying the entire application, you have a frontend system that is not only very performant, but also only requires access to the backend upon regeneration. Next.js made this functionality surprisingly easy to implement and once completed, I was able to shut my backend server down, only to turn it back on when I needed to make a change. I also used this migration as an opportunity to adopt Typescript, which introduced a higher level of safety and robustness to my frontend system. For testing, I added Cypress to perform high level, behavior driven tests. Testing in the frontend is still a bit of a weak spot for me, but I plan to add more tests in the next iteration.
The next pain point was the data abstraction layer in the backend. Not only was this portion slowing the system down, it also failed on occasion with little to no explanation. I completely removed this portion of the system and replaced it with JPAs within my content management system built in Kotlin with Spring Boot. Jakarta Persistence API (formerly known as Java Persistence API) is a set of concepts for retaining objects after their creation. In practice, it allows developers to connect to and interact with databases easily. Removing the data abstraction layer literally cut the call time in half. While doing this, I changed the url for the backend to a URL with the same origin as this site, removing the need to handle cross-origin communications. The last change I made to the backend was the addition of a PUT endpoint which now allows me to update existing blogs or create new ones with a specified blogId.
After making these changes, my applications performance improved substantially and I felt inspired to add new types of content to the site. I added a small about section on the home page that has an image of me to the left, as well as some icons in a custom font that represent a large portion of my skills as a developer. I implemented better animations for the blog cards and added functionality to the button in the left corner with my logo on it. It now brings you to the home page. I also added two new content types, “code” and “a”, where “code” provides monospaced text with syntax highlighting for code snippets and “a” adds hyperlinks.
Overall, I am happy with the changes I’ve made thus far, especially in regards to performance, but I’m definitely not finished yet. In some ways, I am dissatisfied with the UI and am considering doing a complete overhaul in favor of something far more simple. I also still do not have image capabilities, nor can I store text of a different content type within another type, i.e. bold text or a hyperlink within a paragraph. In the next iteration of the site, I plan to implement these features and more.
Blog post about the first implementation:
https://mcullenm.dev/blog/2