Erfaringer fra implementering af min første full-stack webapplikation

Jeg har for nylig opnået et af mine langsigtede mål: implementering af min første full-stack webapplikation.

I dette indlæg vil jeg dele de lektioner, jeg har lært fra et begynderperspektiv, sammen med nogle nyttige tutorials, jeg fulgte, vigtige vejspærringer, som jeg var nødt til at overvinde, og fejl, jeg lavede undervejs. Jeg vil hjælpe andre udviklere med at forstå, hvad der er involveret i implementering af en webapplikation.

Efter at have brugt over seks uger på at google, prøve, fejle og prøve igen, lykkedes det mig endelig at implementere min webapplikation. Det bestod af en Node.js-backend sammen med en React-frontend til en Amazon Web Services (AWS) EC2 virtuel maskine.

Det var en ganske udfordring, men det var virkelig tilfredsstillende, da applikationen til sidst blev implementeret med succes og nu tilgængelig via et offentligt domænenavn.

Det største problem for mig var at finde oplysningerne. Jeg forstod ikke, hvad der var involveret i implementeringen. Så jeg kæmpede for at finde effektive svar på nettet. Jeg kunne ikke finde en enkelt guide til hele processen.

Forhåbentlig kan jeg forenkle implementeringsindlæringskurven for den næste person ved at bringe alle de oplysninger, jeg lærte, ét sted.

Så her går det ...

Hvad betyder det at implementere en applikation?

En webapplikation er opdelt i to dele.

  • Kundsides kode: Dette er din frontend UI-kode. Dette er statiske filer, der ikke ændres i hele din applikations levetid. Statiske filer skal eksistere et eller andet sted, så dine brugere kan downloade og køre dem i deres browser på klientsiden. Jeg vil gå nærmere ind på, hvor det et sted kan være senere.
  • Serversidekode: Dette behandler al logik i din applikation. Det skal køres på en server (maskine), ofte en virtuel som en EC2-forekomst, ligesom du kører den, når du udvikler lokalt.

For at køre din lokale kode skal serveren have en kopi af den. Jeg klonede lige min Github repo på serveren fra kommandolinjegrænsefladen på serveren.

Du skal også konfigurere din server. Dette inkluderer:

  • opsætning af maskinen til at kunne få adgang til internettet og køre din kode
  • udsætte de korrekte porte
  • lytte efter HTTP-anmodninger (internetanmodninger)
  • pege et brugerdefineret domænenavn til den server, din applikation kører fra

Du ved, at det fungerer, når du kan få adgang til din applikation ved hjælp af dit brugerdefinerede domænenavn fra enhver maskine på internettet, og al funktionalitet i din applikation fungerer som forventet.

Så det er en oversigt. Men hvordan gør vi det faktisk?

Kom godt i gang

Du skal opdele din ansøgning og nedbryde problemet. Du implementerer to forskellige ting: statiske filer på klientsiden og server-side-kode.

Min første fejl var at tænke på min ansøgning som en helhed snarere end to separate applikationer, der taler med hinanden.

Dette øgede kompleksiteten og gjorde googling efter svar ubrugelig. Det efterlod mig overvældet.

Jeg opdelte problemet i disse trin. Selvom hvert problem altid kan opdeles yderligere.

  • Opsætning af din VM og implementering af din Backend
  • Implementering af din frontend
  • Få kommunikation mellem de to applikationer
  • Peger på dit domænenavn

I figuren nedenfor har jeg forsøgt at sætte den komplette proces i et diagram.

Opsætning af din VM og implementering af din Backend

I mit tilfælde var dette en Express.js-server indsat på en amazon EC2 virtuel maskine. Jeg ville have forklaret, hvordan man gør det, men vejledningen "Oprettelse og styring af en Node.js-server på AWS - del 1" gør et langt bedre job.

Det er den bedste vejledning, jeg er stødt på i dette rum og dækker:

  • Start af en AWS virtuel maskine
  • At oprette korrekte sikkerhedsgrupper til havne
  • Træk kode fra GitHub til den virtuelle maskine
  • Kører din server
  • Brug af Nginx, en HTTP-server, til at videresende anmodninger fra port 80
  • Brug af PM2 til at fortsætte processen, der kører din server

Det var en livredder, og uden den ville jeg sandsynligvis stadig sidde fast. Så tak, Robert Tod.

Du kan nemt teste, at din server kører ved hjælp af Postman til at sende en anmodning til et af dine Backend-slutpunkter.

Implementering af din frontend

Så nu hvor du har en server med din backend kørende (håber jeg), skal du få din Frontend til at fungere. Dette er virkelig let, når du forstår processen.

Desværre gjorde jeg det ikke længe. For eksempel forsøgte jeg i starten at køre min Frontend ved hjælp af npm start.

Npm start opretter en lokal udviklingsserver, der betjener filerne, så de kun er tilgængelige ved hjælp af, localhosthvilket ikke er det, vi ønsker.

For at implementere Frontend-koden skal du gemme alle filerne på din virtuelle maskine et sted, som din webserver kender til. Webserveren lader en klient downloade koden og køre den i deres browser.

Apache og Nginx er eksempler på webservere.

En webserver lytter til bestemte porte, port 80 eller mere almindeligt port 443 (sikker) og serverer enten statiske filer (din Frontend-kode) eller sender anmodningen til en anden port. For eksempel så vi en anmodning til Backend i Node.js-tutorial ovenfor.

Da Frontend-kode kun er en samling af filer, der er gemt på en webserver, vil vi gøre disse filer så små og optimerede som muligt. Dette sikrer, at klienten kan downloade og køre dem så hurtigt som muligt.

Hurtigere side indlæser lige glade brugere.

Alle dine JavaScript-filer fra Frontend kan bundtes i en enkelt JavaScript-fil. Dette gøres normalt ved at køre npm run build, forudsat at du har defineret dette script i din package.json.

Du kan læse mere om bundlingskode her.

Basically, bundling your application removes anything that isn’t essential. This includes shortening names and placing all JavaScript code in one file. It will also compile your code into the correct JavaScript version. This is so all web browsers can understand and run it (for example, converting TypeScript to JavaScript).

When your code is bundled, you just have to copy the files into your web server. Then configure your web server to serve files stored at that location.

Here is a good article on deploying static files to an Nginx web server.

Hopefully, if all is going well (which it never does), your Frontend code is now working.

Visit the public DNS for the virtual machine to verify that the static information from the site loads.

Getting the Two Applications Communicating

So I had both my applications running individually, but something wasn’t right. I couldn’t get rid of a network request error.

This was the most frustrating point for me. I was so close, but I ran into some setbacks that ended up taking weeks to solve.

Cross-Origin Resource Sharing (CORS) is a mechanism that allows communication between different IP addresses or ports. You want your Backend to be allowed to send data back to your Frontend.

To enable this, your Frontend must include the correct headers when requesting resources. This can be done in two ways:

  • The headers can be added in Nginx although it takes some figuring out. You can start here.
  • You can use the cors npm module to include the headers.

A great way to test this if it is working is by looking within the network tab of your browser’s developer tools. This shows all the requests your application is making. If you select a request you can see where the request went to and what headers it included.

Once you have the right request headers being sent with your request, you have to make sure the requests are going to the correct place. This should be the address and port of your EC2 Backend server and not the address and port of your local Backend server like mine was.

Your Frontend communicates with your Backend using HTTP requests. Somewhere in your Frontend, code you will tell it where your Backend is located.

const networkInterface = createNetworkInterface({ uri: ‘//0.0.0.0:5000/graphql', });

Mine looked like this, which clearly was not going to be correct for my production server.

Annoyingly this made my application seem like it worked when I first navigated to it on my local machine, as my local server was running and able to return the required information.

To fix this, you can simply change the URI defined, but that means having to change it back every time you do further development, which is not the best approach (I know because I did it).

A more sophisticated solution is to include both URIs and use environment variables to select the appropriate one.

const networkInterface = createNetworkInterface({ uri: process.env.NODE_ENV === 'production' ? '//thecommunitymind.com/graphql' : '//0.0.0.0:5000/graphql', });

Simple but effective. Just make sure you set your NODE_ENV to production when using it for your production server.

We’re almost there. In fact, your deployment might work now.

But I had one last problem to overcome.

Even though my CORS setup was correct, the required headers were not being included consistently and were only getting added sometimes. For some POST requests, the CORS headers were not always present. Very odd!

This error lead me on a frustrating goose chase trying to fix my CORS setup in Nginx, when actually it had nothing to do with CORS.

Actually, I didn’t even need to do anything with CORS in Nginx, because I was using the CORS npm module.

The error was due to two other issues:

  • My database was included as an sqlite file in the Backend and
  • My process manager, PM2, was watching for file changes

So writing to the database file on a POST request caused PM2 to restart the server. This was leading to the correct headers not getting picked up which resulted in misleading errors.

A great tip and one I wish I had known earlier is to check your server logs on your EC2 instance. Whether you’re using PM2 or something else there will always be a way to check your logs. Just Google it!

These logs provided the key to solve my issue.

I simply had to turn off the watch ability of PM2. Bingo. And finally, it worked.

Pointing your Domain Name

This is the icing on the cake. You want a nice clean URL for your newly deployed application.

I bought my domain name through Amazon and used Route 53 to point it to the correct EC2 instance. This was a surprisingly painless experience.

Amazon’s tutorial was quite sufficient.

Summary

I hope this post has helped you understand the web application deployment process and ultimately get your amazing project online — whatever that may be.

At least you should have a better idea of what to Google for!

Good Luck.