Уроки, отримані в результаті розгортання мого першого повнофункціонального веб-додатку

Нещодавно я досяг однієї зі своїх довгострокових цілей: розгортання мого першого повнотекстового веб-додатку.

У цій публікації я поділюсь уроками, які я засвоїв з точки зору початківця, а також деякими корисними підручниками, якими я керувався, ключовими перешкодами, які мені довелося подолати, та помилками, які я допустив на своєму шляху. Я хочу допомогти іншим розробникам зрозуміти, що пов’язано з розгортанням веб-програми.

Провівши більше шести тижнів, гуглюючи, намагаючись, не вдавшись і спробувавши ще раз, мені нарешті вдалося розгорнути свою веб-програму. Він складався з серверної бази Node.js разом з інтерфейсом React до віртуальної машини Amazon Web Services (AWS) EC2.

Це було досить складно, але це справді задовольняло, оскільки врешті-решт додаток було успішно розгорнуто і тепер доступне через загальнодоступне ім'я.

Найбільшою складністю для мене був пошук інформації. Я не розумів, що стосується розгортання. Тож я намагався знайти ефективні відповіді в Інтернеті. Мені не вдалося знайти єдиного посібника для всього процесу.

Сподіваємось, я можу спростити криву навчання розгортання для наступної людини, зібравши всю інформацію, яку я дізнався, в одне місце.

Отже, справа йде ...

Що означає розгортання програми?

Веб-програма розділена на дві частини.

  • Код на стороні клієнта: це ваш інтерфейсний код інтерфейсу. Це статичні файли, які не змінюються протягом життя вашої програми. Статичні файли повинні десь існувати, щоб ваші користувачі могли завантажувати та запускати їх у своєму браузері на стороні клієнта. Я піду детальніше про те, де це десь може бути пізніше.
  • Код на стороні сервера: це стосується всієї логіки вашого додатка. Його слід запускати на сервері (машині), зазвичай віртуальному, як екземпляр EC2, подібно до того, як ви запускаєте його при локальній розробці.

Для запуску локального коду сервер повинен мати його копію. Я щойно клонував репо Github на сервер із інтерфейсу командного рядка сервера.

Вам також потрібно налаштувати ваш сервер. Це включає:

  • налаштування машини для доступу до Інтернету та запуску вашого коду
  • виставлення правильних портів
  • прослуховування запитів HTTP (Інтернет-запити)
  • вказівка ​​власного доменного імені на сервер, на якому запущена ваша програма

Ви дізнаєтесь, що це працює, коли ви можете отримати доступ до своєї програми за допомогою власного доменного імені з будь-якої машини в Інтернеті, і вся функціональність вашої програми працює належним чином.

Отже, це огляд. Але як ми насправді це робимо?

Починаємо

Вам слід розділити свою програму та розібрати проблему. Ви розгортаєте дві різні речі: статичні файли на стороні клієнта та код на стороні сервера.

Моя перша помилка полягала в тому, що я розглядав свою заявку як єдине ціле, а не дві окремі програми, які спілкуються між собою.

Це додало складності та зробило пошуки відповідей марними. Це змусило мене почуватися пригніченим.

Я розбив проблему на ці кроки. Хоча кожну проблему завжди можна розбити далі.

  • Налаштування віртуальної машини та розгортання бекенда
  • Розгортання вашого Frontend
  • Підключення двох програм
  • Вказуючи своє доменне ім’я

На малюнку нижче я спробував зобразити повний процес на схемі.

Налаштування віртуальної машини та розгортання бекенда

У моєму випадку це був сервер 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 - це лише сукупність файлів, що зберігаються на веб-сервері, ми хочемо зробити ці файли якомога меншими та оптимізованими. Це гарантує, що клієнт може завантажувати та запускати їх якомога швидше.

Швидше сторінка завантажує рівних щасливих користувачів.

Усі ваші файли JavaScript Frontend можна об’єднати в один файл 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.