
يحتوي هذا المستودع على HDA يعتمد على HTMX (الواجهة الأمامية) وإطار Drogon C ++ (الواجهة الخلفية).
كان الهدف هو إنشاء "تطبيق ويب" سريع الاستجابة دون استخدام أي من أطر عمل JavaScript المعتادة.
جاءت فكرة هذا المشروع أثناء قراءة كتاب Hypermedia Systems الممتاز. في ذلك ، يتحدث المؤلفون عن طرق بديلة لكتابة تطبيقات الويب modern . على عكس معظم الكتب الأخرى حول تطوير الويب ، لا يعتمد المؤلفون على أي إطار عمل JavaScript ، ولكن بدلاً من ذلك يعودون إلى جذور بنية Hypermedia التي هي the web نفسها.
لقد كتبت أيضًا مقالًا عن هذا المشروع ودوافع عامة عن استخدام HTMX و C ++.
بدلاً من استخدام JavaScript للتغلب على HTML ، وهي إستراتيجية تتكاثر بشكل أساسي بين الأطفال السميكة في التسعينيات ، يستخدم المؤلفون htmx لزيادةها . أنها تجعلها قادرة على بذل المزيد من الجهد دون العودة إلى حيل جافا سكريبت الذكية. بالطبع ، لا يحظر JS ويعتمد htmx نفسه على تطوره الخاص ، لكن JS غير مرئي لأنه لا توجد حاجة فعلية لذلك.
لا نحتاج إلى استخدام JS لاستبدال عناصر التحكم في الوسائط المفرطة "غير الكافية" على ما يبدو ، لأن HTMX هنا لتمديدها. يجعلهم قادرين على فعل المزيد كما هو محدد في الأصل. على سبيل المثال ، يمكن "ترقية" علامة المرساة ( <a> ) ، بحيث يمكن تنفيذ الطلبات المنشورة أو وضعها أو تصحيحها أو حتى حذفها. لا يجب أن تكون العلامة <form> هي التحكم الوحيد في Mypermatiale لإرسال البيانات عبر طلبات النشر. ماذا عن كتابة عناصر التحكم الخاصة بك التي يمكن أن تفعل الشيء نفسه بالضبط؟ أو ربما <form> S التي يمكنها تصحيح الإدخالات الموجودة على الخادم؟ ما يتطلب عادةً رمز JS الصريح يمكن الآن القيام به بشكل إعلاني مع ضوابط الوسائط المفرطة .
إليك مثال من هذا المشروع. زران ( إلغاء وحفظ ) يمكن العثور عليهما في كل تطبيق ويب معقد بما فيه الكفاية.
< button hx-get =" /contacts "
hx-target =" #main "
hx-swap =" innerHTML " >
Cancel
</ button >
< button hx-post =" /contacts/{%contact.ID%}/edit "
hx-include =" input "
hx-target =" #main "
hx-swap =" innerHTML " >
Save
</ button >صدق أو لا تصدق ، ولكن هذان يستخدمان الوظائف التالية:
<button> .ولم يكن هناك حاجة إلى سطر واحد من JavaScript لجعله يعمل. هذا هو مدى قوة بنية الانسيابية في الواقع.
نستخدم أيضًا _hyperscript ، مكتبة صغيرة للتعامل مع الأحداث ومعالجة DOM. مع ذلك ، يمكننا الاستماع إلى الأحداث وإرسالها ، ومعالجة كائنات DOM ، كل ذلك دون مغادرة HTML.
إليك مثال من هذا المشروع:
< button id =" edit-c " class =" btn btn-primary "
hx-get =" /contacts/{%c.ID%}/edit "
hx-target =" #main "
hx-swap =" innerHTML " > Edit </ button >
< button class =" btn btn-danger "
hx-delete =" /contacts/{%c.ID%}/delete "
hx-confirm =" Are you sure you wish to delete this contact? "
hx-target =" this "
hx-swap =" none "
_ =" on click remove #edit-c
then remove me "
> Delete </ button >
< button class =" btn btn-info "
hx-get =" /contacts "
hx-target =" #main "
hx-swap =" innerHTML " > Back </ button > في التحكم الثاني <button> ، لدينا بضعة أجزاء من _hyperScript التي تقوم بما يلي:
والنتيجة النهائية هي إزالة الأزرار Edit Delete . يبقى الزر Back فقط.

بدلاً من إرسال Jsons ذهابًا وإيابًا ( وفي كل مرة يتم تحليلها وفقًا لبعض المنطق الداخلي ) ، يمكننا استخدام HTML كما تم تصميمه في الأصل: كأداة لتطبيقات الوسائط المفرطة ذات معنى. يوجد بروتوكول HTTP بسبب HTML ، ولكن في هذه الأيام ننقل في الغالب JSON فوقه. هذا لا معنى له في الواقع ، لأن JSON لا يمكن أن تنقل دلالات التطبيقات ، والتي تشول بشكل فعال المعنى الأصلي لخادم العميل من الويب. لا عجب أننا نحتاج إلى أطر عمل ضخمة في الجبهة لدينا ، لأن خوادمنا هي في الغالب مجرد مزودي بيانات مع واجهات برمجة تطبيقات JSON. و JSON APIs ليست "مريحة".
يتم كتابة رمز مصدر الواجهة الخلفية للكتاب في Python ويمكن استخدامه بدلاً من C ++. في الواقع ، لقد حاولت تقليد واجهات برمجة تطبيقات Python الأصلية ، بحيث لا ينبغي أن تكون هناك فجوات كبيرة في فهمهما. كنت أكتب رمز C ++ أثناء قراءة الفصول المعنية.
ولكن نظرًا لأن htmx غير مؤلفة من اللغة ، فلا توجد مشكلة في استخدام أي لغة على الإطلاق ، لذلك استخدمت C ++. هذا جيد أيضًا من منظور التعلم لأنه يجبرني على التحقق من كل شيء.
أعتقد أنه يجب علينا إزالة الانتفاخ ليس فقط من واجهةنا [ وضع أي إطار عمل ضخم JS هنا ] ، ولكن أيضًا من خلفيةنا [ ضع أي إطار عمل كبير في الواجهة الخلفية هنا ]. يستهلك البرامج الضخمة كميات هائلة من الوقت والطاقة. الوقت البشري والطاقة وكذلك دورات وحدة المعالجة المركزية والكهرباء.
هناك حاجة إلى عدد قليل من مكتبات C ++ لتحقيق التجميع. يستخدم هذا المشروع VCPKG كمدير للحزم ، لكنك حر في اختيار أي شيء آخر بدلاً من ذلك.
لتثبيت حزمة ، ما عليك سوى استدعاء vcpkg install PACKAGE_NAME .
هناك حاجة إلى الحزم التالية:
drogon
drogon[ctl]
fmt
argparse
brotli
zlib
openssl
sqlite3
soci[core]
soci[sqlite3]
البحث عنهم سهل: vcpkg search PACKAGE_NAME
sudo apt install uuid-dev libcriterion-dev
سيتعين على مستخدمي Windows إعداد بيئة MSYS أولاً. بعد التثبيت ، حدد إدخال MSYS2 MINGW64 في قائمة Start Windows. لا تستخدم MSYS UCRT4 أو أي إدخال آخر!
في نافذة Bash التي تم فتحها حديثًا ، أدخل هذا الأمر لتثبيت الحزم المطلوبة:
pacman -S git mingw-w64-x86_64-gcc mingw-w64-x86_64-cmake make mingw-w64-x86_64-c-ares mingw-w64-x86_64-jsoncpp mingw-w64-x86_64-openssl
تحقق مما إذا كان المترجم متاحًا which g++ . يجب أن ترى رسالة مثل هذه:
$ which g++
/mingw64/bin/g++ ستحتاج أيضًا إلى محرر لتحديث مسارات البيئة ، لذا قم بتثبيت مساراتك المفضلة ، مثل pacman -Sy nano أو pacman -Sy vim
افتح .bash_profile مع nano .$HOME/.bash_profile وأضف هذه الخطوط الثلاثة إلى نهاية الملف:
PATH=/mingw64/bin: $PATH
export VCPKG_DEFAULT_TRIPLET=x64-mingw-static
export VCPKG_DEFAULT_HOST_TRIPLET=x64-mingw-static حفظ وإغلاق الملف. إعادة تحميلها مع: source $HOME/.bash_profile أو . ~/.bash_profile
ستكون هناك حاجة إلى إدخالات ثلاثية في وقت لاحق لتوجيه vcpkg لاستخدام MINGW بدلاً من برنامج التحويل البرمجي C ++ الافتراضي. ولأننا نريد أيضًا تجميع المكتبات الثابتة فقط ، فإننا نعلنها باستخدام اللاحقة static .
على عكس الحزم الأخرى ، لن يتم تثبيت Drogon باستخدام vcpkg . حزمة VCPKG المتوفرة حاليًا أخطاء تجميع ، وهذا هو السبب في أننا يجب علينا تجميعها يدويًا.
استنساخ مصادر Drogon وإعداد بيئة البناء. يجب تكييف مسار /c/bin/drogon من المثال أدناه مع الإعدادات المحلية. يجب أن يرسم جذر هذا المسار ( /c/bin ) إلى مسار موجود بالفعل في نظام Windows أو على سبيل المثال C:/bin أو أي مسار آخر من اختيارك.
git clone https://github.com/drogonframework/drogon --recursive
mkdir drogon/build
cd drogon/build
cmake .. -G " MSYS Makefiles " -DCMAKE_INSTALL_PREFIX:PATH=/c/bin/drogon الآن قم بتجميع Drogon مع make -j وانتظر حتى يكمل.
أخيرًا ، قم بتثبيت Drogon مع make install .
يجب أن ترى الآن قائمة بالمجلدات في C:/bin/drogon .

والخطوة الثانية هي تثبيت بعض المكتبات التي سيتم ربطها بشكل ثابت. سوف نستخدم vcpkg لتجميعهم جميعًا.
من نفس نافذة Bash ، قم بإصدار الأوامر التالية لإعداد vcpkg .
cd $HOME
git clone https://github.com/microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.batيلاحظ:
If you pefer to install vcpkg files under different root path, change the first command "cd $HOME" from the script above.
For example: cd /c/Users/WINDOWS_USER_NAME
In MSYS Bash, the Windows file system is located under /c.
And your MSYS $HOME folder is located under "home" in your Windows MSYS root folder.
من مجلد vcpkg ، قم بإصدار الأوامر التالية لتثبيت المكتبات المطلوبة:
./vcpkg.exe install argparse
./vcpkg.exe install fmt
./vcpkg.exe install brotli
./vcpkg.exe install zlib
./vcpkg.exe install openssl
./vcpkg.exe install sqlite3
./vcpkg.exe install soci
./vcpkg.exe install soci[sqlite3] يمكنك الآن تجميع هذا المشروع عبر Poweshell مع ./buildall.ps1 .
ولكن ، لا تنس تغيير vcpkg_root في meson.build أولاً. يجب أن يشير هذا المسار إلى مستودع vcpkg المستنسخ سابقًا.

نظام البناء المفضل لدي هو Meson ، لأنه من الصعب الحفاظ على Makefiles وأنا ببساطة لا أريد أن أتعلم كيفية استخدام CMake . الحياة قصيرة جدًا بالنسبة لبرامج الاستخدام المستخدم.
هناك نوعان من البرامج النصية ، buildall.sh (MacOS/Linux) و buildall.ps1 (Windows). مع هذين الخطتين التاليين سيتم تنفيذ:
builddir ( فقط على Windows ، في MacOS/Linux سيتم ذلك بواسطة Meson )drogon_ctl لتحويل CSPs إلى ملفات مصدر C ++ ووضعها في src/viewssrcbuilddirهناك حاجة إلى برنامج التحويل البرمجي C ++ 20. أنا أستخدم GNU C ++ V12.1.0.
قبل محاولة بناء المشروع ، يرجى تكييف هذين المتغيرين في ملف meson.build :
يحمل triplet معلومات حول جهاز المضيف ، على سبيل المثال x64-osx .
vcpkg_root هو المجلد الجذر الذي يحتوي على حزم مثبتة بواسطة vcpkg .
سيتم استخدام drogon_ctl بواسطة Meson لتحويل قوالب CSP إلى ملفات C ++.

تستخدم الواجهة الأمامية مكتبة HTMX وبعض موارد Bootstrap للتصميم. لا يوجد JavaScript المكتوب يدويًا حيث يوفر HTMX بالفعل الأشياء responsive التي نتوقع أن يقدمها أي تطبيق ويب modern .
تعتمد الواجهة الخلفية على إطار الويب السريع C ++ السريع المسمى Drogon .
قاعدة البيانات المستخدمة هي SQLITE3 ولكن يمكن استبدالها بسهولة بأي قاعدة بيانات أخرى SQL. ما عليك سوى ضبط فئة src/database/db_mgr.cpp . مكتبة للوصول إلى SQLite3 هي SOCI ويدعم العديد من الخلفية الأخرى لقواعد البيانات. يحتوي جذر هذا المشروع على ملف SQLite3 ، demo.db ، الذي يستخدمه التطبيق افتراضيًا. هناك أيضًا ملف CSV متاح ، contacts.csv ، يحتوي على بعض الإدخالات التي يمكن استخدامها لملء جدول جديد.

controllers على فئات يستخدمها Drogon لتعيين مكالمات العميل إلى وظائف في الواجهة الخلفية.database على فئة غلاف صغيرة للوصول إلى مثيل SQLite3.dtos على Data Transfer Objects التي يتم استخدامها في Tansfers للبيانات بين الواجهة الأمامية والخلفية.templates على CSPs (صفحات خادم C ++) ، وهي قوالب تستخدمها drogon_ctl لإنشاء مصادر C ++. سيتم استخدام هذه المصادر لإنشاء مخرجات HTML.views تحتوي على فئات C ++ التي تم إنشاؤها بواسطة Drogon. لا ينبغي تحرير هذه الملفات يدويًا . سيتم استبدالها على كل بناء. لتغيير سلوكهم أو محتوياتهم ، استخدم CSPs من مجلد templates بدلاً من ذلك. تتم الاختبارات مع مكتبة المعيار.
يمكن تثبيت المعيار عبر brew install criterion . خلاف ذلك ، يمكنك بنائه يدويًا كما هو موضح هنا.
لبناء معيار مع Meson ، استنساخ ريبيه أولاً:
git clone --recursive https://github.com/Snaipe/Criterion.gitثم إصدار الأوامر التالية:
cd Criterion
meson - Dprefix = c: / bin / criterion build
ninja - C build installيمكن تغيير بادئة دليل التثبيت. بعد اكتمال التثبيت ، اضبط المسار إلى ملف DLL الخاص بـ Criterion. سيتم استخدام DLL هذا من قبل TESTERSIONS التي لها معيار مرتبط.

توجد مصادر اختبار هذا المشروع في test ويتم بناؤها تلقائيًا بواسطة Meson . لتنفيذ الاختبارات ، يمكنك استخدام هذين الخيارين:
PS > meson test - C .builddir
ninja: no work to do .
ninja: Entering directory ` .builddir '
ninja: no work to do.
1/1 basic OK 0.09s
Ok: 1
Expected Fail: 0
Fail: 0
Unexpected Pass: 0
Skipped: 0
Timeout: 0
Full log written to .builddirmeson-logstestlog.txtأو عن طريق استدعاء الاختبار القابل للتنفيذ مباشرة:
PS > .builddir test_demo_web_server.exe
[ ==== ] Synthesis: Tested: 1 | Passing: 1 | Failing: 0 | Crashing: 0 يبدأ تطبيق الويب عن طريق تحميل index.html الذي يحتوي على علامة div مع id = "main" . في جميع أنحاء التطبيق ، سيتم استخدام هذه العلامة بواسطة عناصر تحكم أخرى لاستبدال محتوياتها ديناميكيًا دون أي تحديث للصفحة. ومع ذلك ، على عكس تطبيقات الويب modern النموذجية الأخرى ، لا نستخدم أطر عمل JS مثل React أو Angular لجعل التطبيق يستجيب. بدلاً من ذلك ، نستخدم htmx فقط كمكتبة نصية لدينا.
هناك أيضًا ثلاثة موارد bootstrap المعنية ، ولكن هذا يجعل التطبيق يبدو أفضل. Bootstrap ليس شرطًا ويمكن استبداله بأي مكتبة أو أوراق أنماط خاصة. وينطبق الشيء نفسه على jQuery الذي يتم تضمينه كاعتماد على bootstrap. يمكن إزالة أي من هذه المكتبات بأمان لأنها لا تؤثر على htmx أو _hyperscript .
يتواصل تطبيق الويب مع الخادم بطريقة قياسية للاستجابة للاستجابة. ولكن على عكس العديد من تطبيقات الويب الأخرى هناك ، لا يتم استخدام أي JSON. بدلاً من ذلك ، يقوم الخادم بإرسال أجزاء من رمز HTML فقط الذي يستخدمه العميل لتحديث الحالة الحالية للتطبيق.
يقبل برنامج الخادم معلمتين لتحديد IP والمنفذ.
Usage: demo_web_server [options]
Optional arguments:
-h --help shows help message and exits [default: false]
-v --version prints version information and exits [default: false]
-i --ip-address Server IP Address [default: " 127.0.0.1 " ]
-p --port Port [default: 3000]
يمكنك أيضًا استخدام config.json المُشارك في Drogon للتحكم في سلوك الخادم. نظرًا لأن Drogon يقدم الكثير من الخيارات ، يجب عليك أولاً أن تجعل نفسك على دراية به. يحتوي ملف التكوين في هذا المشروع على عدد قليل من الإعدادات.
يوجد أيضًا ملف تكوين منفصل قائم على JSON ، server_config.json ، الذي سيتم استخدامه بواسطة خادم الويب. حاليًا ، يحدد موقع ملف SQLite3 فقط ، ولكن سيتم توسيعه في المستقبل.
{
"database" : {
"type" : " sqlite3 " ,
"file" : " demo.db "
}
} لا ينبغي الخلط بين هذا الملف مع JSON الخاص بـ Drogon الذي يسمى config.json .
معهد ماساتشوستس للتكنولوجيا