Pelajaran yang dipetik dari penerapan aplikasi web tumpukan penuh pertama saya

Saya baru-baru ini mencapai salah satu tujuan jangka panjang saya: menerapkan aplikasi web full-stack pertama saya.

Dalam posting ini, saya akan membagikan pelajaran yang saya pelajari dari perspektif pemula, bersama dengan beberapa tutorial bermanfaat yang saya ikuti, hambatan utama yang harus saya atasi, dan kesalahan yang saya buat selama ini. Saya ingin membantu pengembang lain memahami apa yang terlibat dalam penerapan aplikasi web.

Setelah menghabiskan lebih dari enam minggu googling, mencoba, gagal, dan mencoba lagi, saya akhirnya berhasil menerapkan aplikasi web saya. Itu terdiri dari backend Node.js bersama dengan frontend React ke mesin virtual Amazon Web Services (AWS) EC2.

Itu cukup menantang tetapi benar-benar memuaskan, karena pada akhirnya aplikasi tersebut berhasil di-deploy dan sekarang dapat diakses melalui nama domain publik.

Kesulitan terbesar bagi saya adalah mencari informasi. Saya tidak mengerti apa yang terlibat dalam penerapan. Jadi saya berjuang untuk menemukan jawaban yang efektif di web. Saya gagal menemukan satu panduan pun untuk keseluruhan proses.

Mudah-mudahan, saya dapat menyederhanakan kurva pembelajaran penerapan untuk orang berikutnya dengan membawa semua informasi yang saya pelajari ke satu tempat.

Jadi begini ...

Apa yang dimaksud dengan menerapkan aplikasi?

Aplikasi web dibagi menjadi dua bagian.

  • Kode sisi klien: Ini adalah kode UI antarmuka Anda. Ini adalah file statis yang tidak berubah sepanjang hidup aplikasi Anda. File statis harus ada di suatu tempat agar pengguna Anda dapat mendownload dan menjalankannya di browser mereka di sisi klien. Saya akan menjelaskan lebih detail tentang di mana tempat itu nanti.
  • Kode sisi server: Ini berkaitan dengan semua logika aplikasi Anda. Ini harus dijalankan di server (mesin), biasanya server virtual seperti instans EC2, sama seperti Anda menjalankannya saat mengembangkan secara lokal.

Untuk menjalankan kode lokal Anda, server harus memiliki salinannya. Saya baru saja mengkloning repo Github saya ke server dari antarmuka baris perintah server.

Anda juga perlu mengatur server Anda. Ini termasuk:

  • menyiapkan mesin agar dapat mengakses internet dan menjalankan kode Anda
  • mengekspos port yang benar
  • mendengarkan permintaan HTTP (permintaan Internet)
  • mengarahkan nama domain kustom ke server tempat aplikasi Anda dijalankan

Anda akan tahu ini berfungsi ketika Anda dapat mengakses aplikasi Anda menggunakan nama domain kustom Anda dari mesin mana pun di Internet dan semua fungsionalitas aplikasi Anda bekerja seperti yang diharapkan.

Jadi, itu gambarannya. Tapi, bagaimana sebenarnya kita melakukannya?

Mulai

Anda harus memisahkan aplikasi Anda dan memecahkan masalahnya. Anda menerapkan dua hal yang berbeda: file statis sisi klien dan kode sisi server.

Kesalahan pertama saya adalah memikirkan aplikasi saya secara keseluruhan, bukan dua aplikasi terpisah yang saling berhubungan.

Ini menambah kerumitan dan membuat pencarian jawaban tidak berguna. Itu membuat saya merasa kewalahan.

Saya memecah masalah menjadi langkah-langkah ini. Meskipun setiap masalah selalu bisa dipecah lebih jauh.

  • Menyiapkan VM Anda dan menerapkan Backend Anda
  • Menerapkan Frontend Anda
  • Mendapatkan Dua Aplikasi Berkomunikasi
  • Menunjuk Nama Domain Anda

Pada gambar di bawah ini, saya mencoba memasukkan proses lengkap ke dalam diagram.

Menyiapkan VM Anda dan menerapkan Backend Anda

Dalam kasus saya, ini adalah server Express.js yang digunakan pada mesin virtual EC2 amazon. Saya akan menjelaskan cara melakukannya, tetapi tutorial "Membuat dan Mengelola Server Node.js di AWS - Bagian 1" melakukan pekerjaan yang jauh lebih baik.

Ini adalah tutorial terbaik yang saya temukan di ruang dan sampul ini:

  • Memulai mesin virtual AWS
  • Mendapatkan grup keamanan yang benar untuk port
  • Menarik kode dari GitHub ke mesin virtual
  • Menjalankan server Anda
  • Menggunakan Nginx, server HTTP, untuk meneruskan permintaan dari port 80
  • Menggunakan PM2 untuk mempertahankan proses yang menjalankan server Anda

Itu adalah penyelamat hidup, dan tanpanya saya mungkin masih terjebak. Terima kasih, Robert Tod.

Anda dapat dengan mudah menguji bahwa server Anda berjalan menggunakan Postman untuk mengirim permintaan ke salah satu titik akhir Backend Anda.

Menerapkan Frontend Anda

Jadi sekarang Anda memiliki server dengan backend Anda berjalan (saya harap), Anda perlu membuat Frontend Anda berfungsi. Ini sangat mudah ketika Anda memahami prosesnya.

Sayangnya, saya tidak melakukannya untuk waktu yang lama. Misalnya, di awal saya mencoba menjalankan Frontend saya menggunakan npm start.

Npm start membuat server pengembangan lokal, melayani file sehingga hanya dapat diakses menggunakan localhostyang bukan yang kita inginkan.

Untuk menerapkan kode Frontend, Anda harus menyimpan semua file di mesin virtual Anda di lokasi yang diketahui server web Anda. Server web memungkinkan klien mengunduh kode dan menjalankannya di browser mereka.

Apache dan Nginx adalah contoh server web.

Server web mendengarkan port tertentu, port 80 atau lebih umum port 443 (aman), dan menyajikan file statis (kode Frontend Anda) atau meneruskan permintaan ke port yang berbeda. Misalnya, kami melihat permintaan ke Backend di tutorial Node.js di atas.

Karena kode Frontend hanyalah kumpulan file yang disimpan di server web, kami ingin membuat file ini sekecil dan seoptimal mungkin. Ini memastikan bahwa klien dapat mengunduh dan menjalankannya secepat mungkin.

Halaman yang lebih cepat memuat pengguna yang sama senangnya.

Semua file JavaScript Frontend Anda dapat digabungkan menjadi satu file JavaScript. Ini biasanya dilakukan dengan menjalankan npm run build, dengan asumsi Anda telah menetapkan skrip ini di package.json Anda.

Anda dapat membaca lebih lanjut tentang memaketkan kode di sini.

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.