How Things Have Changed: Part 1, The Setup
A documentation of starting the same project from scratch, half a year apart.
In December of 2016, I decided to make a portfolio site utilizing everything I had learned in the first month of my schooling. In July of 2017, I decided to rewrite the site from scratch.
The result of the rewrite is https://brianjlee.net; the previous version is now hosted in http://v1.brianjlee.net, for the sake of preservation.
In this post, I decided to document the decisions which necessitated a total rewrite, the thought process behind these decisions and the consequences of these decisions.
By no means, this isn’t rewriting Skype from scratch. The scope of this project is, in fact, quite narrow. I have no plans to preach a certain process as if it is groundbreaking; rather, the point is for me to gather my thoughts, write down what I learned and think of ways I could have done things better.
If you happen to be reading this, this should provide a glimpse of how web technologies have shifted in recent years, as experienced by someone who entered the field relatively recently. In a way it is a journey of personal development in navigating a fast-changing environment. It’s also bound to be less reader-friendly than my previous posts unless you particularly like reading unbroken walls of text. Apologies in advance.
Content Changes
The part which necessitated some form of a site update was the changes in content that I needed to display in the site. The major parts are two-fold:
- Find a way to easily update projects:
Because the old site was a static web page with information written directly into HTML, each time I need to display new information I had to edit HTML and post again to the content server. This proved to be time-consuming enough that the site went months without any updates. - Incorporate the blog on Medium:
I started writing content a few months ago and it made sense to link my writing back to my webpage.
Can a static page running client-side JavaScript handle these two requirements?
Certainly 1. is plausible; the plan was to retrieve the project listing from a static-yet-easily-updatable source and retrieve data on the projects from the GitHub API. Using GitHub gists made sense for the data source since data can be retrieved and uploading changes is a simple process. That said, because the source data is not managed by a database but rather user input, it made more sense to store it as a plain text document which is far easier than writing valid JSON by hand.
So whichever solution I plan on implementing must have a reasonable way of looking at the data shown above, interpret it into a data structure that made sense and retrieve the appropriate data from an external API to be displayed.
There were two immediate downsides to leaning on client-side code for this functionality.
- The requests to various endpoints will have to be made from the client device which adds the number of HTTP requests needed to display the whole page. While this may allow incremental loading, overall usability may suffer as a result. I would rather delegate this process to server-side by making the individual requests and sending the client a single JSON response, thus minimizing the request/response cycles from the client.
- Handling requests from client side means the API key necessary for making requests to the GitHub API needs to be sent to the client, either by hard-coding it into the source code or making yet another request to a resource someplace else.
Further, incorporating this blog you are currently reading was basically impossible just using client side code. This is entirely because by design Medium does not have an API endpoint that sends information. Presumably this is to provide accurate data on readership by preventing automated scripts such as scrapers to meddle with the counting. Without a way to access data, the thought was to incorporate an <iframe> that would display my profile page directly onto the page.
Not so fast: naturally, given how protective the Medium platform is, there are several protections that disallowed my above plans. Namely the X-Frame-Options header, which prevents requests made by other domains to display the content that was sent in response. To bypass this, I was going to need to reroute the html from a server that will not include this header. Hence, I was going to need my own backend at this point.
At this point, the overall design changed from ‘a simple static page’ to ‘a simple static page with a separate API’, a direct result that followed the change of content. The decision to keep the two pieces separate had to do with the fact that I was using surge.sh to host the static page in the previous version and I wanted to keep this in place, mostly to not have to reconfigure SSL.
Client Page
At this stage other decisions regarding the nature of the actual web client was also made. Notably I decided away from using a frontend framework and stick to jQuery. For a static page with almost no direct interaction with data and limited range of user actions, adding React or Angular would only add complexity, enlarge the project scope and drag down user satisfaction (i.e. loading times).
Another decision was moving away from Materialize, which was in part a decision to deviate from following Material Design but also a direct result of the fact that maintenance cycle for Materialize is relatively slow. It is entirely plausible that while Materialize continues using jQuery version 2.x, I may not return to it.
The decision to use Bootstrap version 4, which is still in alpha stage, had most to do with its wide use of flexbox.
Initially these were the only parts I wanted to use; the intent was to make this re-write as simple as possible.
The Tools
The previous version had less than fifty lines of JavaScript; this was understandable since there was no dynamically generated content in that version. Most of the code in those fifty lines controlled small behaviors such as changing icons on clicks or tapped into built-in functionalities that were provided by Materialize.
This time around, I needed to generate content based on API responses which was bound to increase the amount of client-side code. Previously when I had to do this, I would write one JavaScript file with code that easily exceeded several hundred lines. In hindsight, even I’m not sure how I managed to keep straight files that look like this.
After months of writing client-side code with frameworks such as React and Angular, there are habits that stuck. Noticeably, I can no longer write without breaking code into modules, which is a great step for better organized code but is impossible to implement without incorporating tools.
Since writing in modules, it also made sense to organize the code by breaking the modules down into conceptual components, which made it easier to keep track of the different responsibilities of each code.
Since I was planning on using build tools for the site anyways, there really was no reason not to throw in TypeScript. TypeScript is addicting.
For tooling, I landed on Browserify; Webpack was set aside for the exact same reason I’ve set aside React. It’s trendy but just not the right tool for the moment. Plus, with plugins such as Tsify (for TypeScript transpilation) and Uglify, it accomplishes exactly what I need without a lot of preconfiguration.
At this point, the previous intent to keep this project simple pretty much flew out the window. That said, it is a necessary set up to allow more complexity into the code without less confusion throughout development.
