ren.codes

a tech blog

In a few weeks, I will start the excruciating quest on the search for the very overrated treasure that we all call The Master's Degree in Computer Science, and I feel like some reviewing is in order. Especially with COVID still orbiting for the foreseeable future, there hasn't been a better time to review some fundamentals for my benefit and everyone else's. However, I have seen enough programming tutorials and read a good amount of CS books to know what I find enjoyable. The fundamentals of computer science are commonly done on languages that I don't use on an everyday basis nor I have enough interest to dive into. With all of this in mind, I am now starting a new series of posts reviewing what we developers seem to feel are the base of every successful career on Computer Science but with the use of the Go Programming Language.

In any case, let's start with some basic knowledge. and work our way down.

Variables

In math, we use variables as placeholders of specific values. For example:

x + 2 = 3

On the equation above, x is a placeholder for the value 1. In programming, we also make use of variables as placeholders for data. For example:

var x = 1

The declaration above creates a new placeholder X, and we set the value 1 to it. Writing down a new variable on code is called a variable declaration. One can make a new variable in the following ways:

The most common way to declare a new variable on Go. Here the type is inferred from the value assigned to the variable:

var a = "one" 

Declaring two variables at once:

var b, c = "two"

Declaring two variables at once, with different values:

var d, e = 3, 4

Declaring a variable and its type:

var f int = 5

This the same as var g = 3:

g := 3 

I don't particularly enjoy moving. I enjoy the excitement of having a new home and a new neighborhood. I enjoy reorganizing a room and having a clean place to transition into. The boxing and carrying phase of the move is terrible. I can't stand having to measure, package, and carry all my items into a new place. Moving software is not less tiring.

My daytime job asked me to start on a redesign of our current product using NextJS. Our website has been up for over 10 years, and it is a local Goliath. The site redesign is well deserved, however, and I am excited to work with a new Frontend framework for the task. There was a POC built for this purpose, and the heads of the company were happy with the results, so my assignment was very much one-sided, and I had no complaints.

Until I wasted 2 weeks trying to fit in our site into NextJS.

NextJS offers a lot of features. One particular feature that comes to mind is the getInitialProps, which enables the initial data population. The first request on a NextJS application returns a populated page, and each subsequent call of getInitialProps happens on the client, allowing for CSR. This is fantastic for anyone who's site is trying to minimize requests loads.

Routing is another story. The NextJS routing functionality is opinionated and requires the user to organize their content within a ./pages directory. What does this mean? If you need a URI to look like the following:

/blog/2020/03/01/:id

Then the component that would be used to render said URI would be found under ./pages/blog/2020/03/01/. This, to me, is unnecessary. Looking further into the documentation, I find a section dedicated to dynamic routes that define catch-all functions. A catch-all route on NextJS is understood as a single point of entry for matching routes. Here is the example found on the docs:

pages/post/[...slug].js matches /post/a, but also /post/a/b, /post/a/b/c and so on.

The issue with this particular website is the directory structure doesn't reflect how the URLs are displayed. The developers created a CMS that did not divide the content by type onto each table. This resulted in every kind of content, that is, posts, unique pages, data, videos, etc., were saved under the same table and shared the same properties. Later, extension tables were created to remediate some of the issues and add some unique features to only certain types of assets, but URI paths stayed the same.

/this-is-a-headline-of-a-post/:id
/this-is-a-headline-of-a-video/:id
/even-a-data-type-content-has-a-headline/:id

This website redesign needs to use catch-all routes, but unfortunately, using catch-all routes kills the cool getInitialProps functionality. Using a catch-all route on the root directory seems to make each link click return a server request. There are discussions on GitHub trying to make sense of the CSR and SSR combination on NextJS.

Let me summarize all of the discussions: NextJS is not made for that. To further conclude my investigation, I looked into the ExportPathMap feature of NextJS. ExportPathMap allows the user to create a mapping that overrides the /pages directory and set up your own paths. The following mapping is shown as an example on the official documentation:

module.exports = {
  exportPathMap: async function (
    defaultPathMap,
    { dev, dir, outDir, distDir, buildId }
  ) {
    return {
      '/': { page: '/' },
      '/about': { page: '/about' },
      '/p/hello-nextjs': { page: '/post', query: { title: 'hello-nextjs' } },
      '/p/learn-nextjs': { page: '/post', query: { title: 'learn-nextjs' } },
      '/p/deploy-nextjs': { page: '/post', query: { title: 'deploy-nextjs' } },
    }
  },
}

This returned object is parsed and passed to a path_to_regex node module, which creates the necessary paths when a dynamic route is present on the config. This means that I should be able to use catch-all routes on the back-end and get all requests to go through the same path, but unfortunately, this is not accurate. Actually, adding catch-all routes has set the build process into an infinite loop, which I have to document in GitHub ASAP. At this point, I gave up trying to fit NextJS into our requirements.

Enter AfterJS, the right mix of NextJS server and client rendering and react-router. It has powerful getInitialProps functionality, brought from NextJS, which saves a ton of load time and server requests. A single point entry is now doable thanks to the flexibility of what the framework calls a “fallback route.” This route can be used as a single point of entry for the website.

// ./src/routes.js

import React from 'react';
import Main from './Main';
import { asyncComponent } from '@jaredpalmer/after';

export default [
  // fallback route
  {
    // there is no need to declare path variable
    // react router will pick this component as fallback
    component: Main,
  },
];

Once a single route is set up, all routes will go through the passed component. This means any request, including 404 calls, so one has to make a note and handle 404 requests within the passed component. But this fallback route gives me a compelling entry point for a redesign. I can keep the links as they are, and once they hit my main component, they can be parsed and redirected to the appropriate file. The rest is very similar to my initial NextJS setup. I don't need to rework the specialized components.

Since URI are very important for our SEO, we need a lot of routing flexibility. The site redesign can't dictate a change of URL slugs, and NextJS is very stubborn when it comes to routing. NextJS seems to be directing its framework towards statically built sites and new projects. This path might do for some, but it is not a catch-all, and for my purposes, that won't work.

I lost two weeks of development by sticking to the wrong stack. The two weeks were a good learning experience, but I don't think it is wise for every developer to learn by wasting time. Use this short post instead of 2 workweeks. Avoid repeating the mistakes that other developers do. That is why we write documentation, right?

Pick the right tools. Write a POC that tackles all the points on your primary requirements in a rudimentary way. The idea is to prove that your selected tech stack will fill those requirements before you fully commit to it. Doing so will save time in the long run.

As this year continues to shock me, I find myself with a lot of time to work on personal goals. Somehow I am lucky enough to stay safe by staying inside and working on personal growth. And I do not want to take that for granted. So as I remain safe and away from people with no empathy to wear a mask, my reading list gets more extensive, and my project board gets clumped with tasks.

I enjoy being busy. Understanding something that previously made no sense is cathartic. I am sure you remember the first time you solved for X. There was a sense of pride on your chest and an aw on your smile. So now I am in chase of that feeling.

But not all books will interest you. I enjoy programming and software architecture and racial relations and existentialism and synthesizers. I am sure one of those previously mentioned hobbies are not as enticing to you as they are to me. I started this blog to share my thoughts and to help others with my experience, and I believe that to reach that purpose, I need to separate my opinions from my teachings.

So I want to split both items into separate blogs. This blog will become a medium to share my thoughts with people who want to hear them while my tech blog will present tutorials and other information related to my main set of skills. I hope that simplifies things for everyone.

My thoughts blog URL is https://ren.rocks.