الموقع اللي إنت بتقرا عليه دلوقتي PWA. الكود في src/pwa/sw.js، والإعدادات في src/lib/pwa.ts. هنفكّكه هنا.
٣ أنواع ملفات، ٣ قرارات
| النوع | الاستراتيجية | الصلاحية |
|---|---|---|
| صفحات المذكرات (HTML) | Cache First بصلاحية | لحد أول deploy جديد، وبحد أقصى ٧ أيام |
_astro/ (CSS و JS والخطوط) | Cache First | مفيش، لأن الاسم فيه hash. وحد أقصى ٢٠٠ ملف |
| فهرس البحث والأيقونات | Stale-While-Revalidate | مفيش، بيتحدث في الخلفية كل مرة |
الصفحات: Cache First بس “طازة”
- فتحت صفحة ← في الكاش؟
- في الكاش؟ ← طازة؟: أيوه
- في الكاش؟ ← 📴 صفحة offline: لأ + مفيش نت
- طازة؟ ← ⚡ اعرضها فورًا: أيوه
- طازة؟ ← النت: لأ
- النت ← الجديدة + احفظها: رد
- النت ← النسخة القديمة: فشل أو اتأخر
لو الصفحة مش موجودة والنت شغال، بتتجاب من النت وتتحفظ عادي. الرسمة بتوضح الحالة الصعبة بس.
إزاي بيعرف إن الصفحة من deploy قديم؟
فكرة من ٣ حتت: رقم لكل build، مكتوب في sw.js، ومختوم على كل صفحة.
- git push ← GitHub Actions: build
- GitHub Actions ← sw.js جديد: يكتب الرقم جوّاه
- sw.js جديد ← المتصفح: اتغير؟ يعمل install
- المتصفح ← صفحة محفوظة: SW جديد يقارن
- صفحة محفوظة ← تتجاب من النت: الختم قديم: تتحدث
src/lib/pwa.ts
// على GitHub Actions = الـ commit hash، وعلى جهازك = الوقتexport const BUILD_ID = process.env.GITHUB_SHA?.slice(0, 12) ?? Date.now().toString(36);وقت الـ build، src/pages/sw.js.ts بيبدّل __BUILD__ في الكود بالرقم ده. فكل deploy بيطلّع sw.js مختلف، والمتصفح بيلاحظ. وكل صفحة بتتحفظ بختم:
src/pwa/sw.js
async function stamp(res) { const headers = new Headers(res.headers); headers.set("x-sw-cached-at", String(Date.now())); headers.set("x-sw-build", BUILD); return new Response(await res.blob(), { status: res.status, statusText: res.statusText, headers });}function isFresh(res) { if (res.headers.get("x-sw-build") !== BUILD) return false; // من deploy قديم return Date.now() - Number(res.headers.get("x-sw-cached-at")) < PAGE_MAX_AGE;}ليه stamp بيعمل Response جديد؟
لو السيرفر عمل redirect (مثلًا /docker ← /docker/)، الرد بيبقى redirected: true. المتصفح بيرفض يستخدم رد redirected كرد على navigation جاي من Service Worker. نسخ الـ body في new Response(...) بيعمل رد جديد نضيف، ومعاه بنحط الختم.
🧪 Lab: شوفه بعينك
- افتح الموقع، وبعدين DevTools ← Application ← Cache storage. هتلاقي
pages-v1وassets-v1وstatic-v1وshell-.... - افتح أي صفحة في
pages-v1، وبص على الـ headers: هتلاقيx-sw-buildوx-sw-cached-at. - في Service workers علّم على Offline، وافتح صفحة زرتها قبل كده: هتفتح. وافتح صفحة جديدة: هتلاقي صفحة “النت مقطوع” وفيها لستة اللي محفوظ عندك.
خلّصت الفصل لما
🧠 اختبر نفسك
١) نزّلت deploy جديد. الصفحات المحفوظة اتمسحت؟
لأ. بقت قديمة بس، فبتتحدث لما تفتحها والنت شغال. offline بتفضل تفتح.
٢) ليه ملفات _astro مالهاش صلاحية؟
الاسم فيه hash من المحتوى. أي تعديل بيطلّع اسم جديد، فالقديم عمره ما بيتغير.
٣) ليه فهرس البحث SWR مش Cache First؟
اسمه ثابت ومحتواه بيتغير مع كل مذكرة. SWR بيدّيك سرعة ويحدّث في الخلفية.