الدروس المستفادة من نشر أول تطبيق ويب متكامل

لقد حققت مؤخرًا أحد أهدافي طويلة المدى: نشر أول تطبيق ويب متكامل.

في هذا المنشور ، سأشارك الدروس التي تعلمتها من منظور المبتدئين ، جنبًا إلى جنب مع بعض البرامج التعليمية المفيدة التي اتبعتها ، والعقبات الرئيسية التي كان علي التغلب عليها ، والأخطاء التي ارتكبتها على طول الطريق. أرغب في مساعدة المطورين الآخرين على فهم ما ينطوي عليه نشر تطبيق ويب.

بعد قضاء أكثر من ستة أسابيع في البحث على googling والمحاولة والفشل والمحاولة مرة أخرى ، تمكنت أخيرًا من نشر تطبيق الويب الخاص بي. كان يتألف من خلفية Node.js جنبًا إلى جنب مع واجهة React الأمامية لجهاز Amazon Web Services (AWS) EC2 الظاهري.

لقد كان تحديًا كبيرًا ولكنه كان مرضيًا حقًا ، حيث تم نشر التطبيق بنجاح في النهاية ويمكن الوصول إليه الآن عبر اسم المجال العام.

كانت الصعوبة الأكبر بالنسبة لي هي العثور على المعلومات. لم أفهم ما الذي تضمنه النشر. لذلك عانيت من أجل العثور على إجابات فعالة على الويب. فشلت في العثور على دليل واحد للعملية برمتها.

آمل أن أتمكن من تبسيط منحنى تعلم النشر للشخص التالي من خلال جلب جميع المعلومات التي تعلمتها في مكان واحد.

إذن هنا يذهب ...

ماذا يعني نشر التطبيق؟

يتم تقسيم تطبيق الويب إلى جزأين.

  • رمز جانب العميل: هذا هو رمز واجهة المستخدم الأمامية. هذه ملفات ثابتة لا تتغير طوال عمر التطبيق. يجب أن تتواجد الملفات الثابتة في مكان ما حتى يتمكن المستخدمون من تنزيلها وتشغيلها في المستعرض الخاص بهم من جانب العميل. سوف أخوض في مزيد من التفاصيل حول المكان الذي قد يكون فيه ذلك في وقت لاحق.
  • رمز جانب الخادم: هذا يتعامل مع كل منطق تطبيقك. يجب تشغيله على خادم (جهاز) ، عادةً ما يكون افتراضيًا مثل مثيل EC2 ، يشبه إلى حد كبير تشغيله عند التطوير محليًا.

لتشغيل الكود المحلي الخاص بك ، يجب أن يكون لدى الخادم نسخة منه. لقد قمت للتو باستنساخ Github repo على الخادم من واجهة سطر الأوامر الخاصة بالخادم.

تحتاج أيضًا إلى إعداد الخادم الخاص بك. هذا يشمل:

  • إعداد الجهاز للتمكن من الوصول إلى الإنترنت وتشغيل الكود الخاص بك
  • كشف المنافذ الصحيحة
  • الاستماع لطلبات HTTP (طلبات الإنترنت)
  • توجيه اسم مجال مخصص إلى الخادم الذي يعمل التطبيق الخاص بك منه

ستعرف أنه يعمل عندما يمكنك الوصول إلى التطبيق الخاص بك باستخدام اسم المجال المخصص الخاص بك من أي جهاز على الإنترنت وتعمل جميع وظائف التطبيق الخاص بك كما هو متوقع.

إذن ، هذه نظرة عامة. لكن كيف نفعل ذلك بالفعل؟

ابدء

يجب عليك تقسيم التطبيق الخاص بك وتفصيل المشكلة. أنت تنشر شيئين مختلفين: الملفات الثابتة من جانب العميل والتعليمات البرمجية من جانب الخادم.

كان خطئي الأول هو التفكير في طلبي ككل ، بدلاً من تطبيقين منفصلين يتحدثان مع بعضهما البعض.

زاد هذا من التعقيد وجعل البحث عن إجابات على googling عديم الفائدة. لقد تركتني أشعر بالإرهاق.

لقد قسمت المشكلة إلى هذه الخطوات. على الرغم من أنه يمكن دائمًا تقسيم كل مشكلة بشكل أكبر.

  • إعداد الجهاز الظاهري الخاص بك ونشر الواجهة الخلفية الخاصة بك
  • نشر الواجهة الأمامية الخاصة بك
  • الحصول على التواصل بين التطبيقين
  • مشيرا إلى اسم المجال الخاص بك

في الشكل أدناه ، حاولت وضع العملية الكاملة في رسم تخطيطي.

إعداد الجهاز الظاهري الخاص بك ونشر الواجهة الخلفية الخاصة بك

في حالتي ، كان هذا خادم Express.js تم نشره على جهاز أمازون EC2 الظاهري. كنت سأشرح كيفية القيام بذلك ، لكن البرنامج التعليمي "إنشاء خادم Node.js وإدارته على AWS - الجزء 1" يقوم بعمل أفضل بكثير.

إنه أفضل برنامج تعليمي صادفته في هذا الفضاء ويغطي:

  • بدء تشغيل جهاز AWS الظاهري
  • الحصول على مجموعات الأمان الصحيحة للمنافذ
  • سحب الكود من GitHub إلى الجهاز الظاهري
  • تشغيل الخادم الخاص بك
  • باستخدام Nginx ، خادم HTTP ، لإعادة توجيه الطلبات من المنفذ 80
  • استخدام PM2 لمواصلة عملية تشغيل الخادم الخاص بك

لقد كانت منقذة للحياة ، وبدونها كنت سأظل عالقًا على الأرجح. لذا شكرا لك روبرت تود.

يمكنك بسهولة اختبار ما إذا كان خادمك يعمل باستخدام Postman لإرسال طلب إلى إحدى نقاط نهاية Backend الخاصة بك.

نشر الواجهة الأمامية الخاصة بك

والآن بعد أن أصبح لديك خادمًا يعمل على تشغيل الواجهة الخلفية (آمل) ، فأنت بحاجة إلى تشغيل الواجهة الأمامية. هذا أمر سهل حقًا عندما تفهم العملية.

لسوء الحظ ، لم أفعل ذلك لفترة طويلة. على سبيل المثال ، في البداية حاولت تشغيل الواجهة الأمامية باستخدام npm start.

ينشئ Npm start خادم تطوير محلي ، يخدم الملفات بحيث لا يمكن الوصول إليها إلا باستخدام localhostما لا نريده.

لنشر كود الواجهة الأمامية ، يجب عليك تخزين جميع الملفات على جهازك الظاهري في مكان يعرفه خادم الويب الخاص بك. يتيح خادم الويب للعميل تنزيل الكود وتشغيله في متصفحه.

Apache و Nginx أمثلة على خوادم الويب.

يستمع خادم الويب إلى منافذ معينة ، المنفذ 80 أو المنفذ 443 الأكثر شيوعًا (آمن) ، ويخدم إما ملفات ثابتة (رمز الواجهة الأمامية) أو يمرر الطلب إلى منفذ مختلف. على سبيل المثال ، رأينا طلبًا إلى الواجهة الخلفية في البرنامج التعليمي Node.js أعلاه.

نظرًا لأن رمز الواجهة الأمامية هو مجرد مجموعة من الملفات المخزنة على خادم ويب ، فنحن نريد أن نجعل هذه الملفات صغيرة ومُحسَّنة قدر الإمكان. هذا يضمن أن العميل يمكنه تنزيلها وتشغيلها في أسرع وقت ممكن.

تحميل صفحة أسرع يساوي المستخدمين السعداء.

يمكن تجميع جميع ملفات 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.