Att väcka liv i ett 3 år gammalt projekt i 6 enkla steg

2020-03-29

Bakgrund

År 2017 använda jag PHP-ramverket Laravel en del för att bygga sajter, tillsammans med Vue som frontend. En sajt jag byggde gick ut på att varje dag skrapa Aftonbladet på lite onödig information så att sajten kunde visa upp denna information i en schysst graf. Sajten skrapade hur många ✔ Aftonbladet använde varje dag och sparade ner antalet i en postgesdatabas som snurrade på Heroku.

Jag byggde sajten, satte upp ett cronjob i Heroku, implementerade en graf som visade antalet ”checkers” de senaste dagarna och gick sedan vidare till andra projekt.

Dagarna gick, månaderna gick, åren gick och plötsligt är det år 2020 och den här sajten har samlat in 3 års data. Det fanns ett litet problem dock. Sajten visade bara data för de senaste dagarna i en enda stackars graf. Med 3 års data borde man kunna få till lite mer roliga grafer och skära i datat på lite alla möjliga sätt för att presentera datat.

Vägen framåt

Jag stod inför ett val. Mycket har hänt sedan 2017 och jag sysslar för det mesta med fullstack JavaScript/TypeScript och inte så mycket PHP längre. Antingen dammar jag av mina PHP skills eller så tar jag tillfälle i akt att helt enkelt bygga om hela det här projektet.

Jag byggde såklart om hela projektet… Ingen sten lämnades orörd utan frontend och backend byttes ut och även databasen byttes ut.

Det här är alltså en liten historia om hur jag väckte liv i ett tre år gammalt projekt och bytte ut Vue, Laravel och Postgres mot React, Next.js och Google Firestore i 6 ”enkla” steg.

Steg 1: Hitta lämplig fullstack JavaScript-lösning

Då jag inte ville spendera alldeles för mycket tid med att sätta upp en utvecklingsmiljö utan istället förlita mig på en lösning som är lite mer åt ”Convention over configuration” hade jag en lista med önskemål att uppfylla för en fullstack JavaScript-lösning:

  1. Bra TypeScript support.
  2. Reactbaserad frontend.
  3. Snabb och enkel node-implementation då jag bara behöver göra ett fåtal API-anrop.
  4. Snabbt att komma igång utan överdrivet mycket tooling.

1.1 Rätt verktyg för jobbet

Utifrån denna lista tyckte jag att react-ramverket Next.js checkade av de mesta av mina önskemål då det är reactbaserat, har bra TypeScript stöd, Serverless functions för enkel backend och en rad andra schyssta features.

✓ Steg 1 check!

Steg 2: Exportera data och se över datamodellen

Det tidigare projektet sparade alltså data i en Postgres-databas som snurrade på Heroku. Det var alltså inte speciellt svårt att exportera den databasen:

  1. Logga in i Heroku-projektet med Heroku CLI
  2. Kopiera ned all data till csv-fil.

2.1 Exportera data

Jag använde följande kommando när jag väl var inloggad i Heroku-projektets postgres från terminalen:

$ \COPY checkers TO '~/aftonbladet-checkers.csv' WITH (FORMAT csv, DELIMITER ',',  HEADER true);

I och med att jag kör med JavaScript på backend-sidan så kändes det mest lämpligt att jobba med json och med tanke på att det nya projektet (steg 3 spoilers) sparar data i Google Firestore.

2.2 Se över datamodellen

Jag konverterade datan från csv-filen till json och såg över datamodellen något - döpte om något fält men i övrigt kändes det nya json-baserade datat redo för att importeras in i en ny källa.

✓ Steg 2 check!

Steg 3: Importera data till ny källa

Jag ville ha en enkel lösning när det gällde datakälla och helst något baserat på NoSQL. Jag ville i princip bara spara en platt lista med json-objekt som representerade varje skrapad dag med antal checkers. Jag har tidigare använt Googles Firestore lösning för en enklare backend och denna gång använde jag mig av Googles nyare lösning - Firestore.

3.1 Importera historisk data

Men nu hade jag alltså data för 3 år som behöver seedas in i Firestore. Det hade man kunnat lösa på en rad olika sätt men jag implementerade seedning av datat med hjälp av ett API-anrop (Next.js serverless function).

3.2 API för att slanga in data

En schysst grej med Next är att om man exporterar en modul i pages/api/example.ts så representerar modulen ett api anrop. Det är alltså filstrukturen som bestämmer hur api-anropen sätts upp.Jag skapade ett API-anrop på det här sättet och skyddade anropet bakom API nyckel och nu hade jag ett sätt att mata den nya källan med all historisk data.

✓ Steg 3 check!

Steg 4: Bygg ny backend

Som tidigare nämnt så bygger ju backend i Next på serverless functions. Min backend i det här fallet byggdes upp av olika API-anrop för att seeda, hämta data och även api-anrop för att skrapa dagens antal checkers. Att ha filstruktur-baserad API-anropsuppsättning (säg det snabbt tre gånger) var väldigt smidigt i ett sånt här projekt som ändå är så pass litet.

4.1 Enkel routing

Jag behövde aldrig sätta upp egna route-handles p.g.a det utan behövde bara skapa rätt filer på rätt ställe i filstrukturen. I och med att jag inte ville lägga flera helger på detta projekt så passade Next:s upplägg med serverless functions perfekt.

✓ Steg 4 check!

Steg 5: Bygg ny frontend

Historiskt sätt har jag ägnat mig mest åt Vue när det kommer till frontend - mycket för att jag tidigare använde en del Laravel som hade Vue som sitt default frontend. Men av olika skäl använder jag mest React nuförtiden, som dessutom är som handen i handsken när det kommer till TypeScript.

5.1 Konsumera och massera data

Att bygga frontend gick rätt fort. Endast ett API-anrop till backend implementerades och en rad utils-funktioner implementerades för att ”massera” datat på olika sätt för att kunna presentera det i olika grafer såsom exempelvis årsvis, kvartalsvis och enligt veckans dagar.

5.2 Fördelen med fullstack JavaScript

Fördelen med fullstack JavaScript innebär ju att alla utils-funktioner skulle kunna refaktoreras att användas i en serverless function istället - om man nu vill flytta mer logik från frontend till backend. Men med tanke på projektets storlek kändes det som att frontenden lika gärna kunde göra ett anrop och sen massera samma data på olika sätt för att fylla graferna.

✓ Steg 5 check!

Steg 6: Förbättra infrastrukturen och se över CI/CD

Förbättra och förbättra… Infrastrukturen tyckte jag egentligen inte att jag behövde göra speciellt mycket åt.

6.1 Sätt upp Travis CI

Heroku funkar bra och att applikationer byggs om när något händer på master branchen är ju väldigt schysst. Däremot hade det ju varit lite av en trygghet om något CI bygge skedde på varje push och varje merge request - för att försöka förhindra problem innan de uppstår. Jag kopplade Travis CI till repot och på varje push och merge request körs ett skript som lintar projektet och verifierar att projektet går att bygga.

6.2 Cronjob

Men hur blev det med cronjob för att skrapa Aftonbladet dagligen? Ja… tidigare användes ju Laravel som hade väldigt schyssta möjligheter att schemalägga jobb. Next är lite mer barebones. Ett litet fulhack implementerades där ett vanligt bash-script CURL:ar API:et - som i sin tur skrapar dagens antal checkers och sparar ned dom i Firestore. I Heroku kan man schemalägga aktiviteter och helt enkelt så triggas det skriptet dagligen - enkelt men effektivt.

✓ Steg 6 check!

Slutet gott allting gott

Det var alltså min lilla historia om hur jag i 6 steg väckte liv ett 3 år gammalt projekt. Eller tja.. väckte liv i och väkte liv i...Jag slängde ut allting förutom själva datan - men datan var ju ändå trots allt det viktigaste att spara och behålla i en återuppståndelse likt denna historia.

För den som är intresserad finns källkoden här och sajten går att besöka på https://aftonbladet-checker.Herokuapp.com/

Mer innehåll

Daniel Vernberg 2023