استضافة خادم Node.js https مع تحديث طبقة المقابس الآمنة تلقائيًا في السحابة وكيف أقوم بإعداد دورة التطوير (+ بوابة ، رد فعل)

مقدمة


بادئ ذي بدء ، يوم واحد أردت إنشاء تطبيق. نشأت هذه الرغبة لأنني أحب القراءة ، ولكن ببساطة لا يوجد مُجمِّع كتب عادي في شبكة الإنترنت الروسية الشاسعة. في الواقع ، بدافع البحث عن شيء للقراءة ومحاولة تذكر اسم الكتاب الذي قرأته مؤخرًا والفصل الذي توقفت عنده ، ولدت الرغبة في إنشاء تطبيق ويب يكون كل هذا ممكنًا وملائمًا. تجدر الإشارة إلى أنه لا توجد خبرة في التطوير والبرمجة وما إلى ذلك. لم يكن لدي ، عملي غير مرتبط بهذا على الإطلاق. ومع ذلك ، تغلبت الرغبة على الكسل وتطورت إلى أفعال ملموسة ، نوع من الهواية.

لن أخبرني كيف درست javascript أو node.js أو الرد أو html أو css ، وما إلى ذلك ، وسوف ننتقل إلى ما جئت إليه في الوقت الحالي ، وما أود مشاركته معك ، وبالطبع الاستماع إلى النقد البناء للمتخصصين.

مثل الكثيرين ، لقد تدربت على جهاز الكمبيوتر الخاص بي على المضيف المحلي: 3000 ، إنشاء الواجهة الأمامية / الخلفية ، وأنواعها ، وعملت مع api ، وما إلى ذلك ، لكن كنت دائمًا قلقًا من فكرة نقل كل هذا إلى الاستضافة لاحقًا؟ هل ستنجح؟ هل سيكون من الضروري إعادة كتابة الكود بسبب هذا؟ والأهم من ذلك ، هل من الممكن تكوين كل شيء حتى أتمكن من العمل على التطبيق من أي جهاز كمبيوتر ونقل كل شيء بسهولة إلى استضافة على الإنتاج؟ سأتحدث عن هذا.

اختيار استضافة


بالنسبة لهوايتي ، كنت على استعداد لإنفاق 10 دولارات شهريًا ، لذلك اخترت الاستضافة التي كنت أخطط للبقاء معها في المستقبل. كما قلت ، قبل ذلك كان لدي 0 تجربة ، بما في ذلك مع استضافة الموقع. حاولت ورفضت ما يلي:

Jelastic : واجهة جميلة وسهلة الاستخدام ، ويبدو أن كل شيء بديهية وقابلة للتطوير ومفهومة. ومع ذلك ، واجهت صعوبات في الإعداد (لم يرغب nginx لسبب ما في العمل من vps ، فقط مع الوحدة النمطية المنفصلة الخاصة بهم) وتوصيل SSL (والتحديث التلقائي) إلى المجال الناطق باللغة الروسية عن طريق الوسائل القياسية (وعدوا بإصلاح الخلل ، لكنني لا أريد الانتظار)

الاستضافة السحابية REG.RU : لدي أيضًا مجال هناك ، لذلك يبدو الحل منطقيًا ، لكنهم لم يقوموا بتكوين PostgreSQL بشكل منفصل ، وبما أنني لا أريد الاتصال بإدارة قاعدة البيانات ، فقد بدأت أتطلع إلى مزيد من البحث.

السحب AWS و Google : جربت ذلك ، يبدو أن كل شيء على ما يرام ، لكنني تذكرت قوانيننا "الرائعة" وشرط وضع بيانات المستخدم على الخوادم في الاتحاد الروسي. لسوء الحظ ، لم يكن لدى هؤلاء الرجال خوادم في الاتحاد الروسي. ليس محاميا ، ولكن من الخطيئة قررت البحث عن الغيوم مع خوادم في الاتحاد الروسي. إذا كان من غير المحتمل أن يواجه تطبيقك مشكلات مع القانون ، فهذا اختيار جيد.

على الرغم من وجود غيوم مع خوادم في الاتحاد الروسي ، ما زلت أريد شيئًا من شأنه أن ينقذني من الاضطرار إلى الغوص في إدارة PostgreSQL. صادف الدافع قليلاً منذ وقت ليس ببعيد Yandex.Clouds التي أصبحت متوفرة ، حاولت ، يبدو أن كل شيء بسيط ومريح ، لذلك توقفت عندهم الآن. تجدر الإشارة إلى أن استضافة PostgreSQL تأتي فورًا مع ذاكرة 1core و 4 جيجابايت ، والتي تكلف حوالي 2 روبل شهريًا ، لذلك في وقت التطوير والتحميل المنخفض ، أخطط لتشغيل PostgreSQL على VPS مقابل ~ 300r ، ونقل قاعدة البيانات مع زيادة في التحميل والسماح تعمل ياندكس في الإدارة والتحديث.

إعداد Yandex.Cloud


سحابة خاصة افتراضية


1) قم بإنشاء دليل لموقعك:

الصورة

2) إنشاء سحابة خاصة افتراضية:

الشيء الرئيسي الذي يعطيه لي في المرحلة الحالية هو IP للوصول إلى المورد الذي تم إنشاؤه من الخارج. تعرفت على الشبكات الفرعية والمناطق والعزلة والتسامح مع الأخطاء بشكل سطحي ، إذا لزم الأمر ، فسوف ألحق بالركب.

3) قم بإنشاء شبكة فرعية وتعيين IP داخلي لها (كما أفهمها ، إنها مثل الشبكة المحلية)

الصورة

4) انتقل إلى علامة التبويب IP وحجز لنفسك IP ثابت.

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

الصورة

حساب السحابة


هنا سيكون لدينا حسابات :) أي أننا سننشئ جهازًا افتراضيًا مع Linux (اخترت ubuntu 18.04) ، وقم بتثبيت تطبيقات node.js و postgreSQL.

الصورة

نقر لإنشاء VM ، ونفكك جميع الإعدادات إلى الحد الأدنى ، حيث لن يكون هناك أي تحميل أثناء التطوير (عندما يتم إصدار تطبيقنا ، ثم نلتف أكثر قليلاً ، سنراقب بواسطة الرسوم البيانية).

سه


نقطة المشكلة التي واجهتها في هذه المرحلة هي SSH:

الصورة

ما كان ولماذا لم يكن لدي أي فكرة ، لذلك ذهبت للدراسة. اتضح - هذه مجرد طريقة وصول ، ولكن ليس بكلمة مرور ، ولكن بواسطة مفتاح SSH الذي تم إنشاؤه. لإنشاء ذلك بالفعل ، قم بتنزيل المعجون وتثبيته وفقًا لما نصحت به.

تشغيل C: \ Program Files \ PuTTY \ puttygen.exe

الصورة

نضغط على الزر "إنشاء" وحرك الماوس لإعطاء العشوائية للمفتاح الذي تم إنشاؤه (كما أفهمها). بعد ذلك ، انسخ السطر الذي يظهر بدءًا من ssh-rsa في مكان ما في الملف النصي وانقر فوق حفظ المفتاح الخاص ، حفظ المفتاح العمومي. يتم إدراج المفتاح الذي تم نسخه إلى الملف النصي في حقل SSH بمفتاح صفحة Yandex Yandex. نحدد الجذر كعلامة تسجيل دخول ، وإلا فلن يكون بإمكانك الوصول عند العمل مع نظام الملفات الرسومية للتطبيق الذي سيتم من خلاله الاتصال بالسحابة من المنزل / العمل (ربما هناك طريقة ، لكنني لم أفهم).
كما لاحظ Andreymal ، من الأفضل عدم استخدام الجذر بحيث لا تنتقل الروبوتات الصينية كلمة المرور لسحابة الخاص بك ، ولكن لأنه في Yandex.cloud الوصول فقط عبر SSH ، يمكنك العيش على هذا النحو.

يجب تشغيل تطبيق على استضافة حصريًا من قبل مستخدم غير جذر ، حتى لا تسمح للمهاجمين بتنفيذ تعليمات برمجية ضارة من خلال الثغرات المحتملة في تطبيقك.


نحن نتصل بالسحابة من جهاز كمبيوتر ونختار عميل SSH مجاني


يسمح لك المعجون القياسي بالعمل على سطر الأوامر فقط ، وبما أنني لست معتادًا على مستخدم windows ، فقد بدأت في البحث عن عميل بمستكشف زائف. في البداية جربت Mobaxterm ، لكن بعد فترة من عدم النشاط ، توقف المستكشف عن العمل تمامًا ، لذا فأنا الآن أعمل مع bitvise ssh وحتى الآن لا أرى مشاكل مثل Mobaxterm.

تكوين bitvise سه


الصورة

هنا في الخادم> حقل تشير إلى سحابة IP الخارجي لدينا. المنفذ 22. انقر فوق مدير مفتاح العميل> استيراد وحدد المفتاح الخاص الذي تم إنشاؤه مسبقًا فيه. قد لا تزال بحاجة إلى عبارة رئيسية ، اختر شيئًا لن تنساه. أغلق هذه النافذة وحدد اسم المستخدم في حقل المصادقة: الجذر ، مفتاح publick ، ​​مفتاح العميل - حدد المستورد مسبقًا. انقر فوق تسجيل الدخول وإذا فعلنا كل شيء بشكل صحيح ، فقم بالاتصال بالسحابة:

الصورة

تثبيت Node.js


أوصي هنا باستخدام تعليمات digitalocean.com ، فهي مفصلة للغاية والكثير منها باللغة الروسية. عادةً ما أستخدم google "digitalocean ubuntu 18.04 node.js" أو ما تريد تثبيته أو تهيئته هناك.

كيفية تثبيت Node.js يمكن قراءتها هنا .

باختصار ، نذهب إلى nodesource (هنا يمكن تثبيت أحدث إصدارات node.js) ، أو تصفح الورقة هنا:

الصورة

قم بنسخ الأوامر وتشغيلها:

curl -sL https://deb.nodesource.com/setup_11.x | sudo -E bash - sudo apt-get install -y nodejs 

نتحقق من كيفية تأسيسها من قبل الفريق

 nodejs -v 

سوف نرى نسخة من node.js

 npm -v 

سيتم عرض إصدار مدير الحزم لـ node.js.

بعد ذلك ، انتقل إلى المجلد / opt / mysuperapp (my_super_app_name - يجب عليك إنشاء هذا المجلد). تم اختيار دليل opt كموقع للتطبيق بعد googling الطويل "حيث يكون من المناسب وضع ملفات node.js للتطبيق في أوبونتو".

أخيرًا ، قم بإنشاء ملف server.js ، والذي سيكون نقطة إدخال التطبيق ، والصق رمز الخادم البسيط على node.js هناك:

 const http = require('http'); const hostname = 'localhost'; const port = 80; const server = http.createServer((req, res) => { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.end('Hello World!\n'); }); server.listen(port, hostname, () => { console.log(`Server running at http://${hostname}:${port}/`); }); 

المنفذ 80 مخصص لطلبات http ، و 443 مخصص لـ https. بينما لدينا خادم على HTTP.

نحن نحفظ كل شيء وتشغيل الأمر:

 node server.js 

يجب أن تعرض وحدة التحكم السطر "Server قيد التشغيل في المضيف المحلي : 80 /"

يمكنك الآن فتح متصفح ، وإدخال عنوان IP خارجي (واحد في سحابة ياندكس من أوبونتو VM الخاص بك) وسنرى "Hello World!"

نحن نفعل كل شيء بشكل مريح أو دورة التنمية مع بوابة


يبدو أن كل شيء يعمل ، لكننا لن نعمل طوال الوقت بالاتصال بالسحابة. علاوة على ذلك ، فجأة ، لن نعمل بمفردنا في المستقبل.

جيثب


جيثب هو المكان الذي يوجد فيه كود طلبنا. باختصار ، مبدأ العمل لشخص واحد هو كما يلي:

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

كل شيء سريع وبسيط ومريح.

سجل في الواقع على جيثب وقم بإنشاء مستودع خاص لطلبنا (سيكون متاحًا لنا فقط):

الصورة

انسخ السطر github.com/ReTWi/mysuperapp.git لتنزيل التطبيق.

الصورة

  1. نعود إلى سطر الأوامر bitvise ، وأوقف التطبيق عن طريق الضغط على ctrl + c (إذا كان لا يزال يعمل).
  2. انتقل إلى دليل / opt وحذف المجلد مع التطبيق الذي أنشأناه

Git هو ما سنستخدمه لتحميل تطبيقنا على github ، ومن هناك إلى جهاز كمبيوتر مضيف أو جهاز كمبيوتر آخر. Git هو موضوع منفصل للمناقشة ، لذلك دعونا نتناول هذا الآن.
قم بتثبيت git على الاستضافة باستخدام الأوامر التالية:

 sudo apt update sudo apt install git 

تحقق مما إذا كان كل شيء راسخًا:

 git --version 

يجب أن تظهر نسخة بوابة.

نحن نملأ بيانات git (لم أفهم السبب ، ولكن من الواضح أنه قد يكون هناك بعض التحذيرات المملة).

 git config --global user.name "Your Name" git config --global user.email "youremail@domain.com" 

أخيرًا ، نقوم بتحميل تطبيقنا على الاستضافة باستخدام الأمر:
(يجب أن يكون هناك رابط لتطبيقك)

 git clone https://github.com/ReTWi/mysuperapp.git 

سيظهر mysuperapp جديد في دليل / opt ، حيث سيتم تحديد ملفات التطبيق التي تم تنزيلها من github.

الآن حان الوقت لتكرار نفس الشيء بالنسبة لأجهزة الكمبيوتر وإغلاق سلسلة أجهزة الكمبيوتر (مختلفة) -> Github -> الاستضافة

تثبيت node.js على جهاز الكمبيوتر .

رمز الاستوديو البصري


للبدء ، حدد محرر شفرة المصدر الذي سنعمل فيه. اخترت Visual Studio code ، لذلك فهو بسيط ومريح ، ويحتوي على الكثير من المكونات الإضافية ويمكنك تكوين تزامن الإعدادات إذا كنت تعمل مع أجهزة متعددة. في الواقع ، نقوم بتنزيل مجلد التطبيق المشترك أو تثبيته أو تشغيله أو تحديده ، نظرًا لأن git clone سينشئ ملفه الخاص بنا.

الإضافات التي أستخدمها هي كما يلي:

الصورة

تثبيت بوابة للكمبيوتر .
افتح وحدة تحكم في VScode باستخدام ctrl + shift + `أو terminal> محطة جديدة

تراجع:

في وحدة التحكم في Windows ، تكون سيئة مع الأحرف الروسية ، بحيث لا توجد شقوق تحتاج إلى فتح ملف> تفضيلات> إعدادات ، أدخل terminal.integrated.shellArgs.windows في الحقل ، انقر فوق

الصورة

وأضف السطر "terminal.integrated.shellArgs.windows": ["-NoExit" ، "/ c" ، "chcp 65001"] ،

الصورة


كرر الأمر لتنزيل الملفات من github:

 git clone https://github.com/ReTWi/mysuperapp.git 

في VScode ، انقر فوق ملف> فتح مجلد وفتح مجلد تطبيقنا.

قم بإنشاء ملف server.js بنفس رمز الخادم البسيط:

 const http = require('http'); const hostname = 'localhost'; const port = 80; const server = http.createServer((req, res) => { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.end('Hello World!\n'); }); server.listen(port, hostname, () => { console.log(`Server running at http://${hostname}:${port}/`); }); 

قم بتثبيت nodemon لإعادة تشغيل الخادم تلقائيًا عند إجراء تغييرات على الكود:

 npm i nodemon -g 

أنا - اختصار للتثبيت
ز - التثبيت العالمي (لتكون متوفرة في وحدة التحكم) ، وليس فقط لتطبيقنا.

قم بتشغيل الأمر:

 nodemon server.js 

افتح مضيف محلي : 80 / في المتصفح أو مضيف مضيف محلي فقط: 80 وشاهد Hello World.

حان الوقت للتحقق من سلسلة أجهزة الكمبيوتر> Github> Hosting.

قم بتنزيل سطح مكتب Github لمزيد من الراحة ، وقم بتوصيل حساب github الخاص بك ، ثم انقر فوق إضافة ملف مستودع التخزين المحلي وحدد دليل تطبيقنا.

في التطبيق ، نرى التغييرات التي أجريناها مقارنة بالإصدار الذي تم تنزيله من Github (أضفنا server.js):

الصورة

انقر فوق "الالتزام بالسيد"> "أصل الدفع" ، وبالتالي قم بتنزيل الملفات من الكمبيوتر إلى Github.

الصورة

نذهب إلى حساب github في المتصفح ونرى ملف server.js الذي تم تنزيله:

الصورة

دعونا نمارس أكثر من ذلك بقليل ، في VScode نستبدل السطر "res.end ('Hello World! \ N')؛" إلى "res.end ('OmNomNom') ؛". سنرى أن الخادم نفسه أعيد تشغيله:

الصورة

سنراجع المتصفح ونرى التغييرات التي أجريناها "OmNomNom" هناك.

سيُظهر لنا github على سطح المكتب أننا غيرنا الخط:

الصورة

مرة أخرى ، انقر فوق الالتزام بإتقان> أصل الدفع لإرسال الملفات إلى جيثب.

التبديل إلى سطر الأوامر استضافة.

نوقف تطبيقنا إذا كان لا يزال قيد التشغيل (ctrl + c).

قم بتنزيل تطبيقنا المحدث بالأوامر التالية:

 git config credential.helper store git pull 

الأول سيحفظ بياناتنا حتى لا تضطر إلى إدخال اسم المستخدم وكلمة المرور باستمرار. في المستقبل ، ستكون عملية السحب كافية بالنسبة لنا.

تثبيت pm2 - شيء مشابه للعقيدة ، فقط للاستضافة:

 npm i pm2 -g 

دعنا نبدأ التطبيق باستخدام pm2 ، والتي ستعيد تشغيل الخادم الخاص بنا عن طريق السحب التالي على الاستضافة:

 pm2 start server.js --watch 

افتح المتصفح على سحابة IP الخارجية الخاصة بنا وشاهد "OmNomNom".

وبالتالي ، قمنا بإغلاق سلسلة العمل مع التطبيق ونشره السريع على الاستضافة.

نقوم بإنشاء شهادات SSL مؤقتة لـ HTTPS على المضيف المحلي والاستضافة


نذهب إلى موقع zerossl.com

الصورة

في المجالات ، مجال ip ... ، أدخل أولاً المضيف المحلي ، وانقر فوق إنشاء وتنزيل ملفين حسب الزر:

الصورة

نقوم بحفظها في مشروعنا في مجلد ssl / localhost.

كرر الإجراء الخاص بـ IP Cloud Cloud وحفظه في ssl / myapp.

إطلاق خادم https node.js أكثر تعقيدًا


هيكل التطبيق:

الصورة

  • العميل - هنا سوف تكمن أمامنا. لقد رد فعل.
  • سجلات - سجلات على استضافة سوف تسقط هنا
  • node_modules - وحدات node.js
  • خاص - ملفاتك الخاصة ، أقوم بتخزين وصول SSH إلى السحابة هناك
  • الخادم هو الخلفية الخاصة بك
  • SSL - شهادات SSL للعمل https على المضيف المحلي والاستضافة
  • .babelrc - تطبيق webpack'om يتفاعل مع إعدادات البناء (يسمح لك باستخدام JS أكثر حداثة عند تطوير الواجهة الأمامية)
  • .gitignore - الملفات التي لن يتم نقلها إلى github (git لا يبدو أنها تراها)
  • client.js - نقطة الدخول لتوليد رد فعل التجميع
  • package.json - node_modeles الذي تستخدمه ومقتطفات الأوامر المختلفة.
  • package-lock.json - التغييرات في الوحدات (كما أفهمها ، سيتحقق الملف من تثبيت نفس الوحدات النمطية على الاستضافة وعلى الكمبيوتر الشخصي).
  • pm2-watch.json - إعدادات بدء تشغيل pm2 للاستضافة
  • README.md - غطاء لجيثب
  • server.js - نقطة البداية لخادم Node.js الخلفي
  • webpack.config.js - رد فعل بناء التكوين

.جيتينور


نحن هنا نشير إلى تلك الملفات / المجلدات التي لا نريد تحميلها على github. ستكون موجودة فقط على هذا الجهاز ولن تقوم git بتعقب / إظهار تغييراتها. فتح وإدراج:

 /node_modules/ /logs/* # exception to the rule !logs/.gitkeep /public/react_bundle.js /public/isProd.js 

نظرًا لأن github لا يفرغ المجلدات الفارغة ، فيمكنك وضع شيء ما بداخله ، على سبيل المثال ، ملف gitkeep فارغ. احفظ الملف وأغلقه.

package.json


افتح والصق ما يلي (بعد / / التعليقات المضافة)

 { "name": "myapp", //    "version": "1.0.0", "description": "OmNomNom", "main": "server.js", "scripts": { "server": "pm2 start pm2-watch.json", //  npm run server     "client": "webpack -w --mode development", //  npm client    .        ,   . "client-prod": "webpack --mode production", //     production "client-analyze": "webpack --mode production --analyze true" //     production       .    }, "repository": { "type": "git", "url": "git+https://github.com/myapp/knigam.git" //     github }, "author": "rtw", "license": "UNLICENSED", //     ( ) "bugs": { "url": https://github.com/myapp/knigam.git" }, "homepage": "https://github.com/myapp/knigam.git#readme", "dependencies": { "@babel/core": "^7.2.2", //  js  frontend "@babel/plugin-transform-runtime": "^7.2.0", //  js  frontend "@babel/preset-env": "^7.3.1", //  js  frontend "@babel/preset-react": "^7.0.0", //  js  frontend "ajv": "^6.8.1", //    "babel-loader": "^8.0.5", //  js  frontend "babel-plugin-styled-components": "^1.10.0", //   styled-components "css-loader": "^2.1.0", //   webpack'om css "fastify": "^2.0.0-rc.6", //  express,      "fastify-cookie": "^2.1.6", //    "fastify-static": "^2.2.0", //     "moment": "^2.24.0", //    "pg": "^7.8.0", //    "pino": "^5.11.1", //   postgreSQL  node.js "pino-pretty": "^2.5.0", //     "react": "^16.8.1", // Frontend .      Vue.js,    .      ,     "react-dom": "^16.8.1", // React     "style-loader": "^0.23.1", //   webpack'om ,    "styled-components": "^4.1.3", // CSS in JS,           "webpack": "^4.29.3", //    "webpack-bundle-analyzer": "^3.0.3", //       "webpack-cli": "^3.2.3" //    ,     } } 

سأركز على إطارين / مكتبات رئيسية تم اختيارها للتطبيق:
لقد تم اختيار Fastify كبديل لـ Express.js ، نظرًا لأن أول واحد لديه بالفعل دعم تجريبي لـ htpp2 ، فإنه يتطور بنشاط ويبدو لي أن لديه مستقبلًا أكثر من express.js ، الذي أصبح بطيئًا جدًا ويتطور بطريقة أو بأخرى. من ناحية أخرى ، تعمل Express.js لفترة طويلة وسيكون من الأسهل العثور على معلومات عنها.

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

نقوم بحفظ ملف package.json وتثبيت جميع الوحدات المحددة في التبعيات باستخدام الأمر:

 npm i 

سيكون لدينا مجلد node_modules ، حيث سيكون هناك كل الوحدات النمطية لتطبيقنا.

العميل - في حين أن المجلد فارغ
السجلات - داخل ملف .gitkeep ، بحيث يهاجر المجلد إلى الاستضافة وتندرج السجلات بنجاح هناك. أثناء التطوير ، سنقوم بإخراج كل شيء إلى وحدة التحكم.

العامة


هنا ستظهر الملفات الثابتة لموقعنا ، والصور هناك ، والتفضيلات ، وما إلى ذلك.
دعونا نتحدث عن ملفين:
index.html:

 <!DOCTYPE html> <html> <head> <base href="/" /> <meta charset="UTF-8" /> <title>MyApp</title> </head> <body> <div id="cookies">    react_bundle   </div> <noscript >:       Javscript</noscript > <script src="react_bundle.js"></script> </body> </html> 

- هنا لدينا رد فعل الواجهة الأمامية تحميلها وجعلها في علامة من قبل معرفها.

يحتوي isProd.js على سطر واحد "module.exports = false"
نظرًا لأنه في استثناءات gitignore ، فهو غير محمول. وفقا لذلك ، وضعناها على خطأ على الكمبيوتر ، وصحيح على الاستضافة. ثم نستخدم هذا الملف لفهم البيئة التي نعيش فيها حاليًا (التطوير / الإنتاج). يبدو لي الأكثر ملاءمة ، بالإضافة إلى ذلك ، يمكنك تغيير الكود جزئيًا أثناء التطوير والتحقق من تشغيل الوحدات النمطية في الإنتاج.

SSL - هناك شهادات سبق حفظها في مجلدات المضيف المحلي و myapp

.babelrc


 { "presets": [ [ "@babel/preset-env", { "targets": { "browsers": [">0.25%", "not ie 11", "not op_mini all"] } } ], "@babel/preset-react" ], "plugins": [ "babel-plugin-styled-components", "@babel/plugin-transform-runtime" ] } 

إعدادات إنشاء react_bundle الخاصة بنا مع دعم المتصفح الذي يستخدمه أكثر من 0.25٪ من المستخدمين.

client.js


 import React from 'react' import { render } from 'react-dom' render(<div>!!</div>, document.getElementById('cookies')) 


يجعل الواجهة الأمامية لدينا في div مع علامة ملف تعريف الارتباط.

pm2-watch.json - يسمح لك بتشغيل الخادم باستخدام أمر "خادم تشغيل npm" على الاستضافة مع تتبع التغييرات في الكود وإعادة التشغيل تلقائيًا.

webpack.config.js


باني تطبيق المفاعل:

 const webpack = require('webpack'), path = require('path'), BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin module.exports = (env, argv) => { let prod = argv.mode == 'production' let config = { entry: './client.js', output: { path: path.resolve('./public'), filename: 'react_bundle.js' }, module: { rules: [ { test: /\.(js|jsx)$/, exclude: /node_modules/, loader: 'babel-loader' }, { test: /\.css$/, use: ['style-loader', 'css-loader'] } ] }, resolve: { alias: { client: path.resolve('./client/shared'), public: path.resolve('./public') } }, plugins: [ argv.analyze ? new BundleAnalyzerPlugin() : false, prod ? new webpack.optimize.AggressiveMergingPlugin() : false, new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /ru/) ].filter(Boolean), optimization: { minimize: prod ? true : false }, performance: { hints: false } } return config } 

باختصار ، يقوم بفتح ملف client.js وكل ما بداخله ، حيث يقوم بجمع react_bundle ووضعه في المجلد العمومي ، حيث سيتم تحميله من خلال index.html المفتوح.

server.js


 const isProd = require('./public/isProd'), fs = require('fs'), log = require('./server/logger'), path = require('path') //   node.js,      process.on('unhandledRejection', (reason, promise) => { log.error({ reason, promise }, '  unhandledRejection') }) process.on('uncaughtException', err => { log.error({ err }, '  uncaughtException') }) // Redirect server from http port 80 to https 443 const fastifyHttp = require('fastify')({ logger: log, ignoreTrailingSlash: true }) fastifyHttp.listen(80, '::', (err, address) => { if (err) { log.error({ err, address }, '   HTTP ') } else { log.warn('Http c ') } }) // Let's Encrypt challenge fastifyHttp.get('/.well-known/acme-challenge/:file', (req, res) => { let stream = fs.createReadStream( path.join(__dirname + '/ssl/.well-known/acme-challenge/' + req.params.file) ) res.type('text/html').send(stream) }) fastifyHttp.get('/*', (req, res) => { res.redirect(301, 'https://' + req.headers.host + req.raw.url) }) fastifyHttp.get('/', (req, res) => { res.redirect(301, 'https://' + req.headers.host + req.raw.url) }) //  let fastifyOptions = { logger: log, ignoreTrailingSlash: true, http2: true } fastifyOptions.https = isProd ? { allowHTTP1: true, key: fs.readFileSync('./ssl/myapp/key.txt'), cert: fs.readFileSync('./ssl/myapp/crt.txt') } : { allowHTTP1: true, key: fs.readFileSync('./ssl/localhost/cert.key'), cert: fs.readFileSync('./ssl/localhost/cert.pem') } const fastify = require('fastify')(fastifyOptions) fastify.listen(443, '::', (err, address) => { if (err) { log.error({ err, address }, '   ') } else { log.warn( `   ${ isProd ? '' : ' ' }` ) } }) //  fastify.setSchemaCompiler(schema => { return ajv.compile(schema) }) //  fastify fastify.setErrorHandler((err, req, res) => { log.error({ err, req }, 'fastify errorHandler') //     if (err.validation) { return res.send({ error: '   ' }) } else { return res.send({ error: ' errorHandler' }) } }) //   fastify.register(require('fastify-static'), { root: path.join(__dirname, './public') }) //  fastify.register(require('fastify-cookie'), err => { if (err) log.error({ err }, 'fastify-cookie') }) //       /   //       index.html,     //        api,   GET /api/userdata fastify.setNotFoundHandler((req, res) => { res.sendFile('index.html') }) // Routes fastify.register( async openRoutes => { //    openRoutes.register(require('./server/api/open')) openRoutes.register(async withSession => { //         //    , : ///withSession.addHook('preHandler', async (req, res) => { // if (!(await sessionManagerIsOk(req, res))) return // }) withSession.register(require('./server/api/with_session')) }) }, { prefix: '/api' } //    ) 

مجلد الخادم


هنا تكمن الخلفية وجميع الطرق.
logger.js - اعتمادًا على البيئة ، يسجل isProd إما إلى وحدة التحكم أو الأخطاء

 'use strict' const pino = require('pino'), isProd = require('../public/isProd') let logOptions = isProd ? { level: 'warn', //   timestamp: () => { return ',"time":"' + new Date() + '"' } } : { level: 'warn', prettifier: require('pino-pretty'), prettyPrint: { levelFirst: true, translateTime: true } } let dest = isProd ? pino.destination('./logs/errors.log') : pino.destination(1) let log = pino(logOptions, dest) module.exports = log 

الخادم / api /
open.js - أضف مساراتنا هنا.

 'use strict' module.exports = function(fastify, options, next) { fastify.route({ method: 'GET', url: '/', handler: async (req, res) => { res.send('api / route') } }) fastify.route({ method: 'GET', url: '/hi', handler: async (req, res) => { res.send('api / route hi') } }) next() } 

بعد إعداد كل شيء على Localhost والتحقق منه ، نحمّل كل شيء على github ، ومن هناك ندعو إلى الاستضافة. كل ما يجب القيام به على الاستضافة هو تثبيت الوحدات النمطية node.js باستخدام الأمر "npm i" وإنشاء ملف isProd.js

تحديث SSL تلقائيًا


عندما تشتري مجالًا وتربطه بسحابة IP ، كمثال على تعليمات REG.RU ، يمكنك تثبيت SSL مجاني محدّث تلقائيًا على الخادم ليتمكن الموقع من العمل عبر https.

خادمنا يعمل دون nginx. قد نحتاج إليها في المستقبل كموازن تحميل أو خادم HTTP أسرع لتوزيع الملفات الثابتة ، لكنني لا أرى حتى الآن الحاجة إليها. لا نحتاج إلى موازنة التحميل حتى الآن ، لكنني لم أجد مقارنات بشأن سرعة توزيع الإحصائيات.

قبل التثبيت في مجلد ssl ، قم بإنشاء المجلد المعروف جيدًا ، وفيه التحدي الصاعد. اتضح /opt/myapp/ssl/.well-known/acme-challenge

لتثبيت SSL المحدّث تلقائيًا على خادم مع node.js بدون nginx ، انقر فوق الارتباط . بدوره ، قم بتنفيذ الأوامر في وحدة التحكم بالاستضافة:

 sudo apt-get update sudo apt-get install software-properties-common sudo add-apt-repository universe sudo add-apt-repository ppa:certbot/certbot sudo apt-get update sudo apt-get install certbot sudo certbot certonly 

نختار طريقة التحقق الثانية ، والتي ستضع ملفًا محددًا في مجلد /opt/myapp/ssl/.well-known/acme-challenge ، وبعد تأكيد مالك الخادم سيتم حذفه.

نشير إلى مجالنا عند الطلب ، على سبيل المثال: "example.com" والمسار إلى مجلد ssl في تطبيقنا (تم تكوين الخادم بحيث يعطي الملف الذي أنشأه الروبوت) "/ opt / myapp / ssl".

سيقوم الروبوت بتكوين مهمة cron نفسها لتجديد الشهادة قبل انتهاء صلاحيتها في غضون 90 يومًا.

لم أكن أعتقد أن الأمر سيستغرق الكثير من الوقت لكتابة كل شيء ، بحلول الساعة الرابعة صباحًا كان من الممكن أن يكون قد فاتني شيء ما: /

المثير للاهتمام هو رأي Habrachians والمتخصصين الذين أتقنوا هذا قماش أو قراءة بعض النقاط الفردية. كيف يتم تنظيم دورة التطوير الخاصة بك؟ هل هناك أي نقاط أكون مخطئًا أو أخطئ فيها؟

Source: https://habr.com/ru/post/ar439952/


All Articles