Changing development stack for Test Track - Why and What to Expect
27-11-2024 18:39
Test Track currently consists of two projects: a frontend project using the Vite ReactJS framework and a backend project using the Laravel PHP Framework.
I've recently started rewriting Test Track with a new technology stack for several reasons.
The rewrite uses the NextJS framework—a full-stack solution that combines frontend and backend code in a single project using one language. Since Test Track is a solo project, this simplifies development by eliminating the need to switch between JavaScript/TypeScript and PHP.
I should note that I'm using an older version of Laravel, so some of the issues I'll mention may have been addressed in newer versions. These observations reflect my current experience with Laravel.
While I appreciate Laravel, managing two separate projects creates extra work, particularly when updating both the Vite and Laravel frameworks. With NextJS, I'll only need to maintain one framework, streamlining the development process.
Another challenge with Laravel is its limited IDE intellisense support. Without additional tooling, IDEs can't recognize all Laravel functions natively, whereas NextJS provides comprehensive intellisense support out of the box.
Laravel's database management requires multiple steps: creating a migration file, writing PHP code for database structure changes, running the migration, and potentially using IDE Helper to rebuild the model.
In contrast, NextJS requires just updating a schema file and running a single command to update both the database and TypeScript files, maintaining complete intellisense support throughout.
A significant limitation in Laravel is that database relationships can't be typed, requiring developers to either memorize or look up relationship names. This becomes particularly challenging with multi-layered table relationships, as in Test Track where test runs connect to both a run-through task table and a test plan table.
In Laravel, this would be retrieved like below:
$testRuns = TestRun::whereProjectId($project_id)->with('run_through_task') ->with('test_plan') ->where('archived', false);
Within the testRun model we have the following:
public function run_through_task(): \Illuminate\Database\Eloquent\Relations\HasMany { return $this->hasMany(RunThroughTask::class, "run_through_id"); } public function test_plan() { return $this->belongsTo(TestPlan::class, "test_plan_id"); }
Note there are two methods, which are referenced in strings as the with parameter. Intellisense doesn't detect these, so I must either memorize or look up the exact names when I forget them. This becomes more complex when tables have multiple relationships—for example, you might need to use Table::whereId(1)→with('table1.table2.table3') to traverse through several linked tables.
In NextJS I don’t need to remember as Intellisense knows all of the tables and the references by doing something like below:
await prisma.testRun.findMany({ where: { id: 1 }, include: { test_plan: true, run_through_task: true } })
If a table links to a table which links to a table I could do something like below:
await prisma.table.findMany({ where: { id: 1 }, include: { table1: { include: { table2: true } } } });
Another key advantage of this rewrite is that it should not only streamline development but also improve site performance for our users.
Currently, with separate frontend and backend systems, the page must make API calls to fetch data after loading. While this process is fairly quick, users still experience a loading state while waiting for content to render.
The latest version of NextJS offers faster data retrieval through server-side rendering, meaning most—if not all—content is available as soon as the page loads. It also uses pre-fetching to cache data in the background, making it instantly available when needed rather than fetching it after navigation.
An example of this can be seen below. I created the projects page and ran a Google Chrome Lighthouse Analysis to compare the two version.
Below is the Laravel version
And the new version of the page on NextJS is below
Looking at a GIF of the login on the old version you can see the loading spinner briefly when the projects are loaded in
Below you will see a similar GIF where it shows logging in on the new version
As you can see, when the login happens, the page goes straight into a populated page of your projects, no view of the page, then a loading spinner, then the projects getting loaded in.
Rest assured, this isn't just a straight rewrite of the existing site. We'll be enhancing the UI, adding new features, and fixing bugs along the way. If you'd like to suggest specific improvements for the new version, please reach out to me at [email protected].