
ที่เก็บนี้มี HDA ที่ใช้ HTMX (ส่วนหน้า) และเฟรมเวิร์ก Drogon C ++ (แบ็กเอนด์)
จุดมุ่งหมายคือการสร้าง "เว็บแอป" ที่ตอบสนองได้โดยไม่ต้องใช้เฟรมเวิร์ก JavaScript ตามปกติ
แนวคิดสำหรับโครงการนี้มาในขณะที่อ่านหนังสือ Hypermedia ที่ยอดเยี่ยม ในนั้นผู้เขียนพูดคุยเกี่ยวกับวิธีทางเลือกสำหรับการเขียนเว็บแอปพลิเคชัน modern ซึ่งแตกต่างจากหนังสือเล่มอื่น ๆ เกี่ยวกับการพัฒนาเว็บผู้เขียนไม่พึ่งพากรอบ JavaScript ใด ๆ แต่กลับไปที่รากของสถาปัตยกรรม Hypermedia ที่เป็น the web เอง
ฉันยังเขียนบทความเกี่ยวกับโครงการนี้และแรงจูงใจทั่วไปในการใช้ HTMX และ C ++
แทนที่จะใช้ JavaScript เพื่อเอาชนะ HTML ซึ่งเป็นกลยุทธ์ที่ทำซ้ำกับลูกค้าที่มีความหนาของยุค 90 ผู้เขียนใช้ htmx เพื่อเพิ่ม พวกเขาทำให้มันสามารถทำ มากขึ้น โดยไม่ต้องกลับไปใช้เทคนิคจาวาสคริปต์ที่ฉลาด แน่นอนว่า JS ไม่ได้ห้ามและ htmx นั้นอาศัยมันสำหรับการพัฒนาของตัวเอง แต่ JS ไม่สามารถมองเห็นได้เนื่องจากไม่จำเป็นต้องใช้จริง
เราไม่จำเป็นต้องใช้ JS เพื่อแทนที่การควบคุม Hypermedia ที่ "ไม่เพียงพอ" ดูเหมือนว่า HTMX อยู่ที่นี่เพื่อขยายพวกเขา มันทำให้พวกเขาสามารถทำ มากขึ้น ตามที่กำหนดไว้เดิม ยกตัวอย่างเช่นแท็กสมอ ( <a> ) สามารถ "อัปเกรด" เพื่อให้สามารถดำเนินการโพสต์ใส่แพทช์หรือลบคำขอ แท็ก <form> ไม่จำเป็นต้องเป็นตัวควบคุม Hypermedia เพียงอย่างเดียวสำหรับการส่งข้อมูลผ่านคำขอโพสต์ วิธีการเกี่ยวกับการเขียนการควบคุมของคุณเองที่สามารถทำได้เหมือนกัน? หรืออาจ <form> s ที่สามารถแก้ไขรายการที่มีอยู่บนเซิร์ฟเวอร์ได้หรือไม่? สิ่งที่มักจะเรียกร้องรหัส JS ที่ชัดเจนสามารถทำได้ อย่างเปิดเผย ด้วยการควบคุม Hypermedia ที่ได้รับการอัพเกรด
นี่คือตัวอย่างจากโครงการนี้ สองปุ่ม ( ยกเลิก & บันทึก ) ซึ่งสามารถพบได้ในเกือบทุกแอพพลิเคชั่นเว็บที่ซับซ้อนเพียงพอ
< 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 บรรทัดเดียวเพื่อให้มันใช้งานได้ นี่คือสถาปัตยกรรม Hypermedia ที่ทรงพลังจริง ๆ
นอกจากนี้เรายังใช้ _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 ตามที่ออกแบบมาเดิม: เป็นยานพาหนะสำหรับแอปพลิเคชัน Hypermedia ที่มีความหมาย โปรโตคอล HTTP มีอยู่เนื่องจาก HTML แต่วันนี้เราส่วนใหญ่ถ่ายโอน JSON ไป สิ่งนี้สมเหตุสมผลน้อยเพราะ JSON ไม่สามารถขนส่งความหมายของแอปพลิเคชันซึ่งทำให้ความหมายดั้งเดิมของ ไคลเอนต์เซิร์ฟเวอร์ ของเว็บมีประสิทธิภาพได้อย่างมีประสิทธิภาพ ไม่น่าแปลกใจที่เราต้องการเฟรมเวิร์ก JS ขนาดใหญ่ในส่วนหน้าของเราเพราะเซิร์ฟเวอร์ของเราส่วนใหญ่เป็นเพียงผู้ให้บริการข้อมูลที่มี JSON API และ JSON APIs ไม่ใช่ "พักผ่อน"
ตัวอย่างแหล่งข้อมูลแบ็กเอนด์ของหนังสือเล่มนี้เขียนด้วย Python และสามารถใช้แทน C ++ ได้ ในความเป็นจริงฉันได้พยายามเลียนแบบ Python APIs ดั้งเดิมเพื่อไม่ให้มีช่องว่างขนาดใหญ่ในการทำความเข้าใจทั้งคู่ ฉันกำลังเขียนรหัส C ++ ในขณะที่อ่านบทที่เกี่ยวข้อง
แต่เนื่องจาก htmx เป็นภาษาที่ไม่เชื่อเรื่องพระเจ้ามากจึงไม่มีปัญหาในการใช้ภาษาใด ๆ ดังนั้นฉันจึงใช้ C ++ นี่เป็นสิ่งที่ดีจากมุมมองการเรียนรู้เพราะมันบังคับให้ฉันตรวจสอบทุกอย่างอีกครั้ง
ฉันคิดว่าเราควรลบ Bloat ไม่เพียง แต่จากส่วนหน้าของเรา [ ใส่กรอบ JS ขนาดใหญ่ที่นี่ ] แต่ยังมาจากแบ็ ก เอนด์ของเรา ซอฟต์แวร์ขนาดใหญ่ใช้เวลาและพลังงานจำนวนมาก เวลาและพลังงาน ของมนุษย์ เช่นเดียวกับวัฏจักร CPU และไฟฟ้า
จำเป็นต้องใช้ไลบรารี 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 ในเมนู Windows Start อย่าใช้ 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
รายการ Triplet สองรายการจะต้องใช้ในภายหลังเพื่อสั่งให้ vcpkg ใช้ MINGW แทนคอมไพเลอร์ Visual Visual 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 มีคลาส wrapper ขนาดเล็กสำหรับการเข้าถึงอินสแตนซ์ SQLite3dtos มี Data Transfer Objects ที่ใช้สำหรับ data tansfers ระหว่างส่วนหน้าและแบ็กเอนด์templates ประกอบด้วย CSPS (หน้าเซิร์ฟเวอร์ C ++) ซึ่งเป็นเทมเพลตที่ drogon_ctl ใช้เพื่อสร้างแหล่ง C ++ แหล่งข้อมูลเหล่านี้จะถูกใช้เพื่อสร้างเอาต์พุต HTMLviews ประกอบด้วยคลาส C ++ ที่สร้างจาก Drogon ไฟล์เหล่านี้ ไม่ควรแก้ไขด้วยตนเอง พวกเขาจะถูกแทนที่ในทุกงานสร้าง หากต้องการเปลี่ยนพฤติกรรมหรือเนื้อหาให้ใช้ CSPs จาก templates เทมเพลตแทน การทดสอบจะทำด้วยห้องสมุดเกณฑ์
เกณฑ์สามารถติดตั้งผ่าน brew install criterion มิฉะนั้นคุณสามารถสร้างมันด้วยตนเองตามที่อธิบายไว้ที่นี่
เพื่อสร้างเกณฑ์ด้วย Meson ให้โคลน repo ก่อน:
git clone --recursive https://github.com/Snaipe/Criterion.gitจากนั้นออกคำสั่งต่อไปนี้:
cd Criterion
meson - Dprefix = c: / bin / criterion build
ninja - C build installคำนำหน้าไดเรกทอรีการติดตั้งสามารถเปลี่ยนแปลงได้ หลังจากการติดตั้งเสร็จสมบูรณ์ให้ตั้งค่าเส้นทางไปยังไฟล์ DLL ของ Criterion DLL นี้จะถูกใช้โดยการทดสอบที่มีการเชื่อมโยงเกณฑ์

แหล่งทดสอบของโครงการนี้ตั้งอยู่ใน 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 = "หลัก" ตลอดทั้งแอพแท็กนี้จะถูกใช้โดยตัวควบคุมอื่นเพื่อแทนที่เนื้อหาแบบไดนามิกโดยไม่ต้องรีเฟรชหน้าใด ๆ อย่างไรก็ตามแตกต่างจากแอพพลิเคชั่นเว็บ 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
มิกซ์