الوحدة 4 · بناء شيء حقيقي
استضافة موقع ثابت على S3 وCloudFront
17 دقراءة 4 درتّب الخطوات
الدرس في لمحة
انشر الواجهة الأمامية لـ Lantern من bucket خاص في S3 عبر Amazon CloudFront مع origin access control، وHTTPS على نطاق مخصّص، وترويسات cache مدروسة، وعمليات إبطال (invalidations).
لا فيديو هنا، بل الشيء الحقيقي: درس مكتوب وأمثلة قابلة للتشغيل واختبار وتدريب.
أتذكر مهرجان طعام الشارع الذي أسقط Lantern؟ معظم تلك الطلبات كانت لبضعة ملفات هي نفسها: الصفحة الرئيسية، وملف أنماط، وJavaScript، وملصق واحد. الواجهة الأمامية لـ Lantern تطبيق Vite يُبنى إلى ملفات ثابتة، فلا يحتاج إلى خادم أصلًا. إنه يحتاج إلى مكان يحفظ فيه الملفات، Amazon S3، وإلى cache عالمي أمامه، Amazon CloudFront.
الصورة العامة
معظم الطلبات cache hits، يجيب عنها موقع حافة قريب من الزائر دون لمس S3. وعند الـ miss (عدم وجود الملف في الـ cache)، يجلب CloudFront الملف من الـ bucket، موقّعًا الطلب عبر origin access control (OAC). يبقى الـ bucket خاصًّا، مع تفعيل Block Public Access، وتسمح سياسته بالقراءة من ذلك الـ distribution وحده.
خطوة بخطوة
1. ابنِ التطبيق وأنشئ bucket خاصًّا
npm run build # Vite writes dist/
aws s3 mb s3://lantern-site-prod --region eu-west-1الـ bucket الجديد خاص افتراضيًا. لا تفعّل استضافة المواقع الثابتة: يحتاج OAC إلى نقطة النهاية العادية للـ bucket، أما نقطة نهاية الموقع فلا تتحدّث إلا HTTP وتتطلّب وصولًا عامًّا.
2. ارفع الملفات بترويسات الـ cache الصحيحة
يضع Vite قيمة hash للمحتوى في أسماء ملفات الأصول (assets/index-4f8a1c.js)، فيحصل الملف المتغيّر دائمًا على اسم جديد. يمكن تخزين هذه الملفات مؤقتًا لمدة سنة. أما index.html فيحتفظ باسمه، لذا يجب أن تتحقّق المتصفّحات وCloudFront دائمًا من وجود نسخة أحدث منه:
aws s3 sync dist/ s3://lantern-site-prod/ --delete \
--exclude "index.html" \
--cache-control "public,max-age=31536000,immutable"
aws s3 cp dist/index.html s3://lantern-site-prod/index.html \
--cache-control "no-cache"يزيل --delete من الـ bucket الملفات التي لم تعد موجودة في dist/، كي لا تتراكم الحزم القديمة.
3. احصل على شهادة في us-east-1
لتفعيل HTTPS على lantern.example، اطلب شهادة عامة من AWS Certificate Manager في us-east-1. لا يستخدم CloudFront إلا الشهادات من تلك الـ Region، أيًّا كانت الـ Region التي فيها الـ bucket الخاص بك. تحقّق منها بسجل DNS الذي يعطيك إياه ACM.
aws acm request-certificate --region us-east-1 \
--domain-name lantern.example --validation-method DNS4. أنشئ الـ distribution
في console الـ CloudFront، أنشئ distribution بالإعدادات التالية:
- Origin: نقطة النهاية العادية للـ bucket، مع origin access control (توقيع الطلبات).
- Default root object:
index.html. - Viewer protocol policy: إعادة توجيه HTTP إلى HTTPS.
- Alternate domain name هو
lantern.example، مع شهادة us-east-1. - Cache policy هي
CachingOptimized، وسياسة ترويسات الاستجابة المُدارة SecurityHeadersPolicy، التي تضيف HSTS والترويسات المرتبطة به.
إذا كانت الواجهة الأمامية تستخدم مسارات من جهة العميل مثل /events/street-food، فهذه المسارات لا توجد كملفات، فيجيب S3 عبر OAC بالرمز 403. أضف استجابة خطأ مخصّصة تقدّم /index.html بالرمز 200 لأخطاء 403، أو CloudFront Function صغيرة تعيد كتابة تلك المسارات، كي تفتح الروابط العميقة المتداولة على وسائل التواصل الصفحة الصحيحة بدلًا من صفحة خطأ.
5. اسمح لذلك الـ distribution وحده بقراءة الـ bucket
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowCloudFrontServicePrincipalReadOnly",
"Effect": "Allow",
"Principal": { "Service": "cloudfront.amazonaws.com" },
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::lantern-site-prod/*",
"Condition": {
"StringEquals": {
"AWS:SourceArn": "arn:aws:cloudfront::111122223333:distribution/E2QWRUHEXAMPLE"
}
}
}
]
}الشرط هو ما يجعل هذا آمنًا: من دونه، يستطيع أي distribution في CloudFront في أي حساب قراءة الـ bucket.
6. وجّه DNS واختبر
أنشئ سجلات alias من نوع A وAAAA لـ lantern.example تشير إلى الـ distribution (في Amazon Route 53، أو كسجل CNAME لدى مزوّد DNS آخر إن كان نطاقًا فرعيًا). ثم تحقّق من أن https://lantern.example يُحمَّل، وأن رابط الـ bucket نفسه يعيد 403 Access Denied: هذا الـ 403 يثبت أن الـ bucket خاص.
7. في كل عملية نشر
كرّر الخطوة 2، ثم أبطل الملف الوحيد الذي يحتفظ باسمه:
aws cloudfront create-invalidation \
--distribution-id E2QWRUHEXAMPLE --paths "/index.html"التكلفة والأمان في لمحة
تدفع لـ S3 مقابل التخزين والطلبات، ومع وجود CloudFront في الأمام، لا يرى S3 إلا حالات الـ miss. النقل من S3 إلى CloudFront لا يُحتسب؛ ويحتسب CloudFront الطلبات والبيانات المقدَّمة للزوّار بنظام الدفع حسب الاستخدام، أو يمكنك اختيار إحدى خططه ذات السعر الثابت التي تجمع الـ CDN مع AWS WAF وDNS وأرصدة S3 بسعر شهري ثابت دون رسوم تجاوز. وفي الحالتين، تهبط ذروة المهرجان الآن على مواقع حافة بُنيت لتحمّلها.
من ناحية الأمان: bucket خاص واحد، وسياسة bucket واحدة بشرط SourceArn، وHTTPS فقط، وترويسات الأمان مفعّلة. في الدرس التالي تضيف الجزء الديناميكي: الـ API الخاص بتأكيد الحضور.
أهم النقاط
- يبقى الـ bucket خاصًّا؛ يقرؤه CloudFront عبر origin access control، وتسمح سياسة الـ bucket لذلك الـ distribution وحده.
- يعمل origin access control مع نقطة النهاية العادية للـ bucket، لا مع نقطة النهاية الخاصة باستضافة المواقع الثابتة في S3.
- شهادة النطاق المخصّص في CloudFront يجب أن تكون في AWS Certificate Manager في us-east-1، مطلوبةً هناك أو مستوردةً إليها.
- امنح ملفات الأصول ذات الأسماء المحتوية على hash عمر cache طويلًا، وامنح index.html عمرًا قصيرًا، كي تظهر عمليات النشر دون إبطال جماعي.
- التقديم من مواقع الحافة يمتصّ ذروات الزيارات ويقلّل نقل البيانات من الـ origin.