Поуки от внедряването на първото ми уеб приложение с пълен стек

Наскоро постигнах една от дългосрочните си цели: внедряване на първото ми уеб приложение с пълен стек.

В тази публикация ще споделя уроците, които научих от гледна точка на начинаещи, заедно с някои полезни уроци, които последвах, ключови пречки, които трябваше да преодолея, и грешки, които направих по пътя си. Искам да помогна на други разработчици да разберат какво е свързано с внедряването на уеб приложение.

След като прекарах повече от шест седмици в гугъл, опит, неуспех и опит отново, най-накрая успях да разгърна уеб приложението си. Той се състоеше от беккенд на Node.js заедно с React интерфейс към виртуална машина на Amazon Web Services (AWS) EC2.

Това беше доста предизвикателство, но беше наистина задоволително, тъй като в крайна сметка приложението беше успешно внедрено и вече е достъпно чрез име на публичен домейн.

Най-голямата трудност за мен беше да намеря информацията. Не разбрах какво е свързано с разполагането. Затова се мъчих да намеря ефективни отговори в мрежата. Не успях да намеря нито едно ръководство за целия процес.

Надяваме се, че мога да опростя кривата на обучение за внедряване за следващия човек, като събера цялата информация, която научих на едно място.

Така че това става ...

Какво означава разгръщане на приложение?

Уеб приложението е разделено на две части.

  • Клиентски код: Това е вашият интерфейсен потребителски код. Това са статични файлове, които не се променят през целия живот на приложението ви. Статичните файлове трябва да съществуват някъде , за да могат вашите потребители да ги изтеглят и стартират в своя браузър от страна на клиента. Ще вляза в по-подробни подробности за това къде това може да бъде някъде по-късно.
  • Код от страна на сървъра: Това се занимава с цялата логика на вашето приложение. Той трябва да се изпълнява на сървър (машина), обикновено виртуален като екземпляр EC2, подобно на това, че го стартирате, когато се развива локално.

За да стартирате вашия локален код, сървърът трябва да има копие от него. Току-що клонирах моето репо Github на сървъра от интерфейса на командния ред на сървъра.

Също така трябва да настроите сървъра си. Това включва:

  • настройка на машината за достъп до интернет и стартиране на вашия код
  • излагане на правилните портове
  • слушане на HTTP заявки (интернет заявки)
  • насочване на потребителско име на домейн към сървъра, от който се изпълнява приложението ви

Ще разберете, че работи, когато можете да осъществите достъп до вашето приложение, като използвате вашето персонализирано име на домейн от която и да е машина в Интернет и цялата функционалност на вашето приложение работи според очакванията.

Това е преглед. Но как всъщност го правим?

Приготвяме се да започнем

Трябва да разделите приложението си и да отстраните проблема. Разполагате две различни неща: статични файлове от страна на клиента и код от страна на сървъра.

Първата ми грешка беше да мисля за моето приложение като цяло, а не за две отделни приложения, които си говорят помежду си.

Това добави към сложността и направи търсенето на отговори безполезно. Остави ме да се чувствам съкрушен.

Разделих проблема на тези стъпки. Въпреки че всеки проблем винаги може да бъде разбит допълнително.

  • Настройване на вашата виртуална машина и внедряване на вашия Backend
  • Внедряване на вашия Frontend
  • Първи комуникации между двете приложения
  • Посочване на вашето име на домейн

На фигурата по-долу се опитах да поставя целия процес в диаграма.

Настройване на вашата виртуална машина и внедряване на вашия Backend

В моя случай това беше сървър Express.js, разположен на виртуална машина на Amazon EC2. Бих обяснил как да го направя, но урокът „Създаване и управление на сървър Node.js на AWS - част 1“ върши далеч по-добра работа.

Това е най-добрият урок, който съм срещал в това пространство и обхваща:

  • Стартиране на виртуална машина AWS
  • Създаване на правилни групи за сигурност за портове
  • Издърпване на код от GitHub във виртуалната машина
  • Стартиране на вашия сървър
  • Използване на Nginx, HTTP сървър, за препращане на заявки от порт 80
  • Използване на PM2 за продължаване на процеса, изпълняващ вашия сървър

Това беше спасител на живота и без него сигурно все още щях да остана. Така че благодаря, Робърт Тод.

Можете лесно да проверите дали вашият сървър работи с Postman, за да изпратите заявка до една от крайните точки на Backend.

Внедряване на вашия Frontend

Така че сега, когато имате сървър с работещ бекенд (надявам се), трябва да накарате вашия Frontend да работи. Това е много лесно, когато разбирате процеса.

За съжаление не го направих дълго време. Например, в началото се опитах да стартирам моя Frontend, използвайки npm start.

Npm start създава локален сървър за разработка, обслужващ файловете, така че да са достъпни само с помощта, localhostкоето не е това, което искаме.

За да разположите кода на Frontend, трябва да съхраните всички файлове на вашата виртуална машина на място, за което вашият уеб сървър знае. Уеб сървърът позволява на клиента да изтегли кода и да го стартира в своя браузър.

Apache и Nginx са примери за уеб сървъри.

Уеб сървърът слуша определени портове, порт 80 или по-често порт 443 (защитен) и обслужва статични файлове (вашият Frontend код), или предава заявката на друг порт. Например видяхме заявка към Backend в урока по Node.js по-горе.

Тъй като кодът на Frontend е само колекция от файлове, съхранявани на уеб сървър, ние искаме да направим тези файлове възможно най-малки и оптимизирани. Това гарантира, че клиентът може да ги изтегли и стартира възможно най-бързо.

По-бързата страница зарежда еднакво щастливи потребители.

Всички ваши Frontend JavaScript файлове могат да бъдат обединени в един JavaScript файл. Това обикновено се прави чрез стартиране на npm run build, ако приемем, че този скрипт е дефиниран във вашия package.json.

Можете да прочетете повече за пакетиране на код тук.

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.