siwane

كيفية إنشاء تطبيق ويب تقدمي (PWA) بسهولة لموقعك دون الحاجة لخبرة برمجية

تطبيقات الويب التقدمية (PWAs): ما هي؟ وما هي مزاياها وعيوبها؟ كيفية انشاء تطبيق PWA؟
Split Post - Split Article Into Several Pages كيفية إنشاء تطبيق ويب تقدمي (PWA) بسهولة لموقعك دون الحاجة لخبرة برمجية

السلام عليكم ورحمة الله وبركاته

لا تكاد تكمل يومك دون أن تستخدم تطبيقًا على هاتفك المحمول أو جهاز الكمبيوتر اللوحي. تعتمد حياتنا اليومية على التطبيقات التي تقدم لنا خدمات ومعلومات. ولكن هل فكرت يومًا في كيف يمكن تحسين تلك التجربة؟ هنا تأتي تطبيقات الويب التقدمية (PWAs) لتقدم جوابًا مثيرًا للاهتمام.
من خلال هذا الدرس ستنشئ تطبيق تقدمي خاص بموقعك دون الحاجة لخبرة تقنية، كل ما ستحتاج اليه هو التركيز مع المقال و متابعة الشرح خطوة خطوة، لا انكر ان المسالة ستكون صعبة شيئا ما عليك ولكنك ستنجح فالنهاية انا متاكد.
اذا احتجت لاي مساعدة اترك تعليقا لاستفسارك و ساقوم بالرد عليك انتبه على تاشير علامة الاشعار فالبريد حتى تتوصل على اشعار الرد في بريدك الخاص.

تعريف PWAs

اولا وقبل كل شئ دعنا نتعرف على ميزة PWAs! هي تكنولوجيا حديثة تمثل تطورًا ملحوظًا في عالم تطبيقات الويب. تجمع بين ميزات تطبيقات الهاتف المحمول ومواقع الويب التقليدية لتقديم تجربة جذابة ومفيدة للمستخدمين.

ميزات رئيسية لـ PWAs

قدرة الوصول الفوري:
الـ PWAs تتيح للمستخدمين الوصول الفوري إلى المحتوى دون الحاجة إلى تثبيت التطبيق، مما يوفر وقتًا ومساحة تخزين على الأجهزة.
2. العمل دون اتصال:
تسمح PWAs بالوصول إلى المحتوى حتى في حالة عدم الاتصال بالإنترنت، مما يعني أنك لن تفقد الوصول إلى معلوماتك المفضلة عندما تكون بلا اتصال.
3. تحسين سرعة التحميل:
تقلل PWAs من وقت التحميل وتحسن الأداء، مما يجعل تجربة التصفح على الإنترنت أكثر سلاسة وسرعة.

مزايا PWAs

الـ PWAs تقدم العديد من المزايا. إنها توفر مساحة تخزين على الأجهزة، تساهم في تقليل تكاليف التطوير، وتسهم في تحسين تجربة المستخدم على الويب.

نماذج ناجحة

Gmail و Twitter Lite و Google Paly وغيرهم تعد أمثلة مشهورة على استخدام PWAs بنجاح لتحسين تجربة المستخدم.

كيف ذلك؟

-تطبيق Gmail: يمكن تثبيت تطبيق Gmail على أجهزة iOS و Android كتطبيق ويب تقدمي. يتيح ذلك للمستخدمين الوصول إلى بريدهم الإلكتروني دون الحاجة إلى فتح المتصفح.
-تطبيق Twitter: يمكن تثبيت تطبيق Twitter Lite على أجهزة iOS و Android كتطبيق ويب تقدمي. يتيح ذلك للمستخدمين الوصول إلى حساباتهم على Twitter دون الحاجة إلى فتح المتصفح.
-تطبيق متجر Google Play: يمكن تثبيت تطبيق متجر Google Play على أجهزة Android كتطبيق ويب تقدمي. يتيح ذلك للمستخدمين الوصول إلى متجر Google Play دون الحاجة إلى اتصال بالإنترنت.
-تطبيق Instagram: يمكن تثبيت تطبيق Instagram على أجهزة iOS و Android كتطبيق ويب تقدمي. يتيح ذلك للمستخدمين الوصول إلى حساباتهم على Instagram دون الحاجة إلى فتح المتصفح.
-تطبيق Spotify: يمكن تثبيت تطبيق Spotify على أجهزة iOS و Android كتطبيق ويب تقدمي. يتيح ذلك للمستخدمين الاستماع إلى الموسيقى دون الحاجة إلى فتح المتصفح.

مزايا تطبيقات الويب التقدمية:
تتمتع تطبيقات الويب التقدمية بالعديد من المزايا، بما في ذلك:
الأداء: يمكن أن تعمل تطبيقات الويب التقدمية بشكل أسرع من تطبيقات الويب التقليدية.
التفاعلية: يمكن أن تكون تطبيقات الويب التقدمية أكثر تفاعلية من تطبيقات الويب التقليدية.
الاستقلالية: يمكن تشغيل تطبيقات الويب التقدمية دون اتصال بالإنترنت. اقتباس من كتاب تطبيقات الويب التقدمية للمؤلف محمد أمين عبد العال

تطور ومستقبل PWAs

مع استمرار التطور التقني، يمكننا توقع رؤية المزيد من PWAs المبتكرة تجعل حياتنا الرقمية أكثر سهولة وجاذبية في المستقبل.

المشاركات ذات الصلة

مراجع عربية متعلقة بتطبيقات الويب التقدمية:
•كتاب تطبيقات الويب التقدمية: محمد أمين عبد العال، دار النشر المصرية، 2023.
•دورة تطوير تطبيقات الويب التقدمية: Udemy، 2023.
•مقال تطبيقات الويب التقدمية: ما هي؟ وكيف تعمل؟: أكاديمية حسوب، 2023.


خطوة بخطوة: كيفية إنشاء تطبيق ويب تقدمي (PWA) بسهولة لموقعك دون الحاجة لخبرة برمجية

إذا كنت مالك مدونة على منصة بلوجر وترغب في تحسين تجربة زوار موقعك على الويب، فإن تطبيقات الويب التقدمية (PWAs) هي الخيار الذي يمكن أن يجلب لك النتائج المرجوة دون الحاجة لمعرفة برمجية عميقة. في هذا المقال، سنأخذك خطوة بخطوة عبر عملية إنشاء PWA لموقعك باستخدام منصة GitHub وخدمة Cloudflare للتسريع.


في هذا القسم، سنشرح كيفية اختبار PWA الخاص بك ونشره لجمهورك.

المتطلبات

قبل أن نبدأ، هناك العديد من الأمور التي يجب أن تتوفر لتفعيل تطبيق الويب التقدمي (PWA):

  1. يجب وجود أيقونة للمدونة بصيغة .png بحجم 512×512.
  2. 5 لقطات شاشة لصفحات موقع الويب الخاص بك بصيغة .png.
  3. يجب أن يكون لديك حساب على GitHub.
  4. إدارة DNS: يجب أن يمر موقع الويب عبر خدمة Cloudflare.
تحميل الأيقونات

- قم بإعداد أيقونة لمدونتك بصيغة .png بحجم 512×512.

انا استعملت تطبيق بيكسارت لتصميم ايقونة لمدونتي، يمكنك الحصول على تطبيق نسخة كاملة لـ PicsArt.

قم بإعادة تسمية الملف ايقونة مدونتك إلى android-icon-512x512.png.
- اذهب إلى موقع favicon-generator.org وقم بتحميل أيقونة المدونة.
- قم بتنزيل الأيقونات المُولَّفة واستخرج الملفات.
- احذف الملفات غير الضرورية مثل browserconfig.xml و manifest.json.
- قم بإنشاء مستودع على GitHub، على سبيل المثال باسم SiwaneXYZ.github.io، عد الى هذا الدرس لتعلم كيفية انشاء حساب GitHub و متستودع. وقم برفع جميع ملفات الأيقونات في الفرع الرئيسي (main branch). قم برفع الملف الأصلي أيضًا، مثل android-icon-512x512.png. إجمالي عدد الأيقونات سيكون حوالي 26.

تحميل لقطات الشاشة

- قم بإعداد 5 لقطات شاشة لصفحات موقع الويب الخاص بك بصيغة .png والتي ستظهر عند ظهور زر التثبيت.

انصحك بتطبيق Instamocks لتعديل لقطات شاشة لصفحات مدونتك لتجعل المظهر اكثر اناقة.

- قم بتسمية اللقطات بالتسلسل:
scr1.png
scr2.png
scr3.png
scr4.png
scr5.png
- قم برفع هذه اللقطات في الفرع الرئيسي (main branch) في نفس مستودع GitHub نفسه.

إنشاء Workers في Cloudflare

اولا يجب ان اخبرك ان العملية التعامل مع كلاود فلير اسهل بواسطة الحاسوب بمراحل ولكن ان كنت تستخدم الهاتف لاسهل عليك العملية استخدم تطبيق لوحة مفاتيح كيبورد Hacker's Keyboard لانها تضم جميع الاختصارات التي ستحتاج لها مثل كيبورد الحاسوب.

سنقوم بإنشاء 4 عمال خدمة في Cloudflare لتسهيل إنشاء مسار لاحقًا، أنصحك بحفظها بأسماء عمال (Workers) وأسم المدونة، بهذه الصيغة على سبيل المثال:
- main-siwane
- manifest-siwane
- serviceworker-siwane
- offline-siwane

ان كنت تستخدم الهاتف و تريد تعديل الاكواد انصحك بتطبيق QuickEdit+ سيوفر عليك عناء تعديل النصوص البرمجية التي سنعمل عليها.


Main Worker

- قم بتسجيل الدخول إلى حسابك على Cloudflare، عد الى درس كيفية انشاء حساب كلاود فلير و ربطه مع بلوجر .
- انتقل إلى قسم Workers وانقر على إدارة الأعمال.
- انقر على إنشاء خدمة وقم بإعادة تسمية الخدمة باسم main-blogname، على سبيل المثال main-siwane.
- احذف البرنامج النصي الحالي واستبدله بالبرنامج النصي التالي:

addEventListener("fetch", event => {
  event.respondWith(handleRequest(event))
})

//const BUCKET_NAME = "main"
const BUCKET_URL = `https://cdn.statically.io/gh/XYZSiwane/SiwaneXYZ`

async function serveAsset(event) {
  const url = new URL(event.request.url)
  const cache = caches.default
  let response = await cache.match(event.request)

  if (!response) {
    response = await fetch(`${BUCKET_URL}${url.pathname}`)
    const headers = { "cache-control": "public, max-age=14400" }
    response = new Response(response.body, { ...response, headers })
    event.waitUntil(cache.put(event.request, response.clone()))
  }
  return response
}

async function handleRequest(event) {
  if (event.request.method === "GET") {
    let response = await serveAsset(event)
    if (response.status > 399) {
      response = new Response(response.statusText, { status: response.status })
    }
    return response
  } else {
    return new Response("Method not allowed", { status: 405 })
  }
}

- استبدل الأجزاء المشار إليها بواسطة اسم مستخدم GitHub الخاص بك (مثل XYZSiwane) واسم المستودع الخاص بك (مثل SiwaneXYZ.github.io).


Manifest.json

بنفس الطريقة، قم بإنشاء خدمة وقم بإعادة تسميتها باسم manifest-blogname، على سبيل المثال manifest-siwane.

- احذف البرنامج النصي الحالي واستبدله بالبرنامج النصي التالي:

addEventListener("fetch", event => {
  const data = {
    name: "صِوانˣʸᶻ",
    short_name: "SiwaneXYZ",
    description: "ثبت صوانˣʸᶻ الان و استمتع بمجمل المواضيع المفيدة و الحصرية",
    display: "standalone",
    prefer_related_applications: false,
    start_url: "\/?utm_source=homescreen",
    scope: "\/",
    background_color: "#686868",
    theme_color: "#AOAOAO",
    icons: [
      {
      src: "\/main\/android-icon-512x512.png",
      sizes: "512x512",
      type: "image\/png",
      density: "4.0",
      purpose: "any maskable"
      },
      {
      src: "\/main\/android-icon-192x192.png",
      sizes: "192x192",
      type: "image\/png",
      density: "4.0",
      purpose: "any maskable"
      },
      {
      src: "\/main\/apple-icon-144x144.png",
      sizes: "144x144",
      type: "image\/png",
      density: "3.0",
      purpose: "any maskable"
      },
      {
      src: "\/main\/android-icon-96x96.png",
      sizes: "96x96",
      type: "image\/png",
      density: "2.0",
      purpose: "any maskable"
      },
      {
      src: "\/main\/android-icon-72x72.png",
      sizes: "72x72",
      type: "image\/png",
      density: "1.5",
      purpose: "any maskable"
      },
      {
      src: "\/main\/android-icon-48x48.png",
      sizes: "48x48",
      type: "image\/png",
      density: "1.0",
      purpose: "any maskable"
      },
      {
      src: "\/main\/android-icon-36x36.png",
      sizes: "36x36",
      type: "image\/png",
      density: "0.75",
      purpose: "any maskable"
      }
    ],
    shortcuts: [
      {
      name: "صِوانˣʸᶻ",
      short_name: "SiwaneXYZ",
      description: "صوانˣʸᶻ مدونة تعليمية تقدم دروس في احتراف بلوجر و اليوتيوب و الربح من الانترنت.",
      url: "\/?utm_source=homescreen",
      icons: [
          {
          src: "\/main\/android-icon-192x192.png",
          sizes: "192x192"
          }
        ]
      },
      {
      name: "حول المدونة",
      short_name: "حول المدونة",
      description: " استكشف مدونة صوان للتقنية",
      url: "\/p/about.html?utm_source=homescreen",
      icons: [
          {
          src: "\/main\/android-icon-192x192.png",
          sizes: "192x192"
          }
        ]
      },
      {
      name: " سياسة الخصوصية",
      short_name: "الخصوصية",
      description: "احتراف التدوين و اليوتيوب و تطوير المحتوى و السيو و الربح من الانترنت.",
      url: "\/p/privacy.html?utm_source=homescreen",
      icons: [
          {
          src: "\/main\/android-icon-192x192.png",
          sizes: "192x192"
          }
        ]
      }
    ],
    screenshots: [
      {
      src: "\/main\/scr1.png",
      type: "image\/png",
      sizes: "540x720"
      },
      {
      src: "\/main\/scr2.png",
      type: "image\/png",
      sizes: "540x720"
      },
      {
      src: "\/main\/scr3.png",
      type: "image\/png",
      sizes: "540x720"
      },
      {
      src: "\/main\/scr4.png",
      type: "image\/png",
      sizes: "540x720"
      },
      {
      src: "\/main\/scr5.png",
      type: "image\/png",
      sizes: "540x720"
      }
    ],
    serviceworker: {
      src: "\/sw.js"
    }
  }

  const json = JSON.stringify(data, null, 2)

  return event.respondWith(
    new Response(json, {
      headers: {
        "content-type": "application/json;charset=UTF-8"
      }
    })
  )
})

ServiceWorker

- كما هو مذكور أعلاه، قم بإنشاء خدمة وقم بتسميتها باسم serviceworker-blogname، على سبيل المثال serviceworker-siwane.
- احذف البرنامج النصي الحالي واستبدله بالبرنامج النصي التالي:

const js = `
importScripts('https://storage.googleapis.com/workbox-cdn/releases/5.1.2/workbox-sw.js');
if (workbox) {
workbox.core.skipWaiting();
workbox.core.clientsClaim();
workbox.core.setCacheNameDetails({
  prefix: 'thn-sw',
  suffix: 'v22',
  precache: 'install-time',
  runtime: 'run-time'
});
const FALLBACK_HTML_URL = '/offline.html';
const version = workbox.core.cacheNames.suffix;
workbox.precaching.precacheAndRoute([{url: FALLBACK_HTML_URL, revision: null},{url: '/manifest.json', revision: null},{url: '/main/favicon.ico', revision: null}]);
workbox.routing.setDefaultHandler(new workbox.strategies.NetworkOnly());
workbox.routing.registerRoute(
    new RegExp('.(?:css|js|png|gif|jpg|svg|ico)$'),
    new workbox.strategies.CacheFirst({
        cacheName: 'images-js-css-' + version,
        plugins: [
            new workbox.expiration.ExpirationPlugin({
                maxAgeSeconds: 60 * 24 * 60 * 60,
                maxEntries:200,
                purgeOnQuotaError: true
            })
        ],
    }),'GET'
);
workbox.routing.setCatchHandler(({event}) => {
      switch (event.request.destination) {
        case 'document':
        return caches.match(FALLBACK_HTML_URL);
      break;
      default:
        return Response.error();
  }
});

self.addEventListener('activate', function(event) {
  event.waitUntil(
    caches
      .keys()
      .then(keys => keys.filter(key => !key.endsWith(version)))
      .then(keys => Promise.all(keys.map(key => caches.delete(key))))
  );
});

}
else {
    console.log('Oops! Workbox did not load');
}
`
async function handleRequest(request) {
  return new Response(js, {
    headers: {
      "content-type": "application/javascript;charset=UTF-8",
    },
  })
}
addEventListener("fetch", event => {
  return event.respondWith(handleRequest(event.request))
})

تم استخدام *Workbox، حيث يمكننا تخزين الصفحات *HTML و *CSS و *JS وأي ملفات ثابتة أخرى.


Offline

- كما هو مذكور أعلاه، قم بإنشاء خدمة وقم بتسميتها باسم offline-blogname، على سبيل المثال offline-siwane.
- احذف البرنامج النصي الحالي واستبدله بالبرنامج النصي التالي:

const html = `<!DOCTYPE html>
<html dir='rtl'>
<head>
  <!--[ Meta Tags ]-->
  <title>عفوًا ، أنت غير متصل!</title>
  <meta charset='UTF-8'/>
  <meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0' name='viewport'/>
  <meta content='IE=edge' http-equiv='X-UA-Compatible'/>
  <!--[ Theme Color ]-->
  <meta content='#299e94' name='theme-color'/>
  <meta content='#299e94' name='msapplication-navbutton-color'/>
  <meta content='#299e94' name='apple-mobile-web-app-status-bar-style'/>
  <meta content='true' name='apple-mobile-web-app-capable'/>
  <!--[ Favicon ]-->
  <link href='/main/apple-icon-120x120.png' rel='apple-touch-icon' sizes='120x120'/>
  <link href='/main/apple-icon-152x152.png' rel='apple-touch-icon' sizes='152x152'/>
  <link href='/main/favicon-32x32.png' rel='icon' sizes='32x32' type='image/png'/>
  <link href='/main/favicon-96x96.png' rel='icon' sizes='96x96' type='image/png'/>
  <link href='/main/favicon-16x16.png' rel='icon' sizes='16x16' type='image/png'/>
  <link href='/main/favicon.ico' rel='icon' type='image/x-icon'/>
  <link href='/main/favicon.ico' rel='shortcut icon' type='image/x-icon'/>
  <!--[ Stylesheet ]-->
  <style>/*<![CDATA[*/
/* Merriweather - Font */ @font-face{font-family: 'Merriweather'; font-style: italic; font-weight: 300; font-display: swap; src: local('Merriweather-LightItalic'), url(https://fonts.gstatic.com/s/merriweather/v22/u-4l0qyriQwlOrhSvowK_l5-eR7lXff4jvw.woff2) format('woff2'), url(https://fonts.gstatic.com/s/merriweather/v22/u-4l0qyriQwlOrhSvowK_l5-eR7lXcf8.woff) format('woff')} @font-face{font-family: 'Merriweather'; font-style: italic; font-weight: 700; font-display: swap; src: url(https://fonts.gstatic.com/s/merriweather/v22/u-4l0qyriQwlOrhSvowK_l5-eR7NWPf4jvw.woff2) format('woff2'), url(https://fonts.gstatic.com/s/merriweather/v22/u-4l0qyriQwlOrhSvowK_l5-eR71Wsf8.woff) format('woff')} @font-face{font-family: 'Merriweather'; font-style: italic; font-weight: 900; font-display: swap; src: url(https://fonts.gstatic.com/s/merriweather/v22/u-4l0qyriQwlOrhSvowK_l5-eR7NWPf4jvw.woff2) format('woff2'), url(https://fonts.gstatic.com/s/merriweather/v22/u-4l0qyriQwlOrhSvowK_l5-eR7NWMf8.woff) format('woff')} @font-face{font-family: 'Merriweather'; font-style: normal; font-weight: 300; font-display: swap; src: url(https://fonts.gstatic.com/s/merriweather/v22/u-4n0qyriQwlOrhSvowK_l521wRZWMf6.woff2) format('woff2'), url(https://fonts.gstatic.com/s/merriweather/v22/u-4n0qyriQwlOrhSvowK_l521wRpXA.woff) format('woff')} @font-face{font-family: 'Merriweather'; font-style: normal; font-weight: 700; font-display: swap; src: url(https://fonts.gstatic.com/s/merriweather/v22/u-4n0qyriQwlOrhSvowK_l52xwNZWMf6.woff2) format('woff2'), url(https://fonts.gstatic.com/s/merriweather/v22/u-4n0qyriQwlOrhSvowK_l52xwNpXA.woff) format('woff')} @font-face{font-family: 'Merriweather'; font-style: normal; font-weight: 900; font-display: swap; src: url(https://fonts.gstatic.com/s/merriweather/v22/u-4n0qyriQwlOrhSvowK_l52_wFZWMf6.woff2) format('woff2'), url(https://fonts.gstatic.com/s/merriweather/v22/u-4n0qyriQwlOrhSvowK_l52_wFpXA.woff) format('woff')}
/* Content */ body{background:#f1f3f6;color:#1f1f1f;font-family:'Merriweather',serif;font-weight:400;-webkit-tap-highlight-color:transparent;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}body:focus{outline:none !important} .mainCont{margin:0 auto;position:fixed;left:0;top:0;right:0;bottom:0;display:flex;align-items:center;justify-content:center;padding:15px} .noIntPop{position:relative;overflow:hidden;text-align:center;padding:15px;border-radius:30px;background:#f1f3f6;box-shadow:inset 0 0 15px rgba(55, 84, 170, 0), inset 0 0 20px rgba(255, 255, 255, 0), 7px 7px 15px rgba(55, 84, 170, 0.15), -7px -7px 20px white, inset 0px 0px 4px rgba(255, 255, 255, 0.2)} .circle.t{top:-150px;right:-150px} .circle.b{bottom:-150px;left:-150px} .noIntCont{position:relative;z-index:1} .noIntIcon{padding:30px} .noConHead{font-weight:700;font-size:1.3rem} .noConDesc{font-size:16px;line-height:1.4em;padding-top:20px;font-weight:400;opacity:.8} .cta,.relCont{display:flex;justify-content:center;align-items:center} .relCont{padding:30px} .cta{width:66px;height:66px;background:#f1f3f6;outline:none;border:none;border-radius:690px;box-shadow:inset 0 0 15px rgba(55, 84, 170, 0), inset 0 0 20px rgba(255, 255, 255, 0), 7px 7px 15px rgba(55, 84, 170, 0.15), -7px -7px 20px white, inset 0px 0px 4px rgba(255, 255, 255, 0.2);transition:box-shadow 399ms ease-in-out} .cta:hover{box-shadow:inset 7px 7px 15px rgba(55, 84, 170, 0.15), inset -7px -7px 20px white, 0px 0px 4px rgba(255, 255, 255, 0.2)} .icon{content:'';width:25px;height:25px;display:inline-block} .iconB{content:'';width:50px;height:50px;display:inline-block} .icon.reload{background:url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239dabc0' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='23 4 23 10 17 10'/><path d='M20.49 15a9 9 0 1 1-2.12-9.36L23 10'/></svg>") center / 25px no-repeat} .iconB.wifiOff{background:url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%231f1f1f' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><line x1='1' y1='1' x2='23' y2='23'/><path d='M16.72 11.06A10.94 10.94 0 0 1 19 12.55'/><path d='M5 12.55a10.94 10.94 0 0 1 5.17-2.39'/><path d='M10.71 5.05A16 16 0 0 1 22.58 9'/><path d='M1.42 9a15.91 15.91 0 0 1 4.7-2.88'/><path d='M8.53 16.11a6 6 0 0 1 6.95 0'/><line x1='12' y1='20' x2='12.01' y2='20'/></svg>") center / 50px no-repeat} .circle{position:absolute;z-index:1;width:280px;height:280px;border-radius:50%;background-color:#f1f3f6;box-shadow:inset 8px 8px 12px #d1d9e6, inset -8px -8px 12px #f9f9f9}
  /*]]>*/</style>
</head>
<body>
  <div class='mainCont notranslate'>
    <div class='noIntPop'>
      <div class='circle t'></div>
      <div class='circle b'></div>
      <div class='noIntCont'>
        <div class='noIntIcon'>
          <i class='iconB wifiOff'></i>
        </div>
        <div class='noConHead'>أوبس، انت غير متصل!</div>
        <div class='noConDesc'>يبدو أن اتصالك بالشبكة لا يعمل الآن .</div>
        <div class='relCont'>
          <button class='cta' onclick='window.location.reload()'>
            <i class='icon reload'></i>
          </button>
        </div>
      </div>
    </div>
  </div>
</body>

</html>`
async function handleRequest(request) {
  return new Response(html, {
    headers: {
      "content-type": "text/html;charset=UTF-8",
    },
  })
}
addEventListener("fetch", event => {
  return event.respondWith(handleRequest(event.request))
})

قم بتعديل الأجزاء المشار إليها.

إنشاء مسارات

- الآن ارجع إلى قسم Workers ومن ثم انقر على إضافة مسار.

- أدخل الحقول كما هو موضح في الجدول التالي:

Route Service Environment
www.siwane.xyz/main/* main-siwane production
www.siwane.xyz/manifest.json manifest-siwane production
www.siwane.xyz/sw.js serviceworker-siwane production
www.siwane.xyz/offline.html offline-siwane production

قم بإدخال الحقول وفقًا لعنوان مدونتك واسم المدونة.

الآن، حاول فتح عناوين URL واحدة تلو الأخرى، على سبيل المثال:

www.siwane.xyz/main/android-icon-512x512.png
www.siwane.xyz/manifest.json
www.siwane.xyz/sw.js
www.siwane.xyz/offline.html

إذا تمكنت من فتح هذه العناوين URL، فهذا يعني أنه ليس هناك مشكلة، وقد قمت بإعداد إعدادات Cloudflare بنجاح. الآن حان الوقت لإجراء تغييرات على المدونة.

تحرير المدونة

- الآن انتقل إلى لوحة تحكم Blogger. اذهب إلى قسم السمات (Themes).
- انقر السهم بجواره اختر تحرير HTML (Edit HTML).
- قم بلصق الأكواد التالية أدناه تحت علامة <head>. إذا لم تجدها، ربما تم تحللها بالفعل وستظهر ك &lt;head&gt;. احذف أي أكواد مماثلة موجودة بالفعل.

<link href='/main/apple-icon-57x57.png' rel='apple-touch-icon' sizes='57x57'/>
<link href='/main/apple-icon-60x60.png' rel='apple-touch-icon' sizes='60x60'/>
<link href='/main/apple-icon-72x72.png' rel='apple-touch-icon' sizes='72x72'/>
<link href='/main/apple-icon-76x76.png' rel='apple-touch-icon' sizes='76x76'/>
<link href='/main/apple-icon-114x114.png' rel='apple-touch-icon' sizes='114x114'/>
<link href='/main/apple-icon-120x120.png' rel='apple-touch-icon' sizes='120x120'/>
<link href='/main/apple-icon-114x114.png' rel='apple-touch-icon' sizes='144x144'/>
<link href='/main/apple-icon-152x152.png' rel='apple-touch-icon' sizes='152x152'/>
<link href='/main/apple-icon-180x180.png' rel='apple-touch-icon' sizes='180x180'/>
<link href='/main/android-icon-192x192.png' rel='icon' sizes='192x192' type='image/png'/>
<link href='/main/favicon-32x32.png' rel='icon' sizes='32x32' type='image/png'/>
<link href='/main/favicon-96x96.png' rel='icon' sizes='96x96' type='image/png'/>
<link href='/main/favicon-16x16.png' rel='icon' sizes='16x16' type='image/png'/>
<link href='/main/favicon.ico' rel='icon' type='image/x-icon'/>
<meta content='#299e94' name='msapplication-TileColor'/>
<meta content='/main/ms-icon-144x144.png' name='msapplication-TileImage'/>
<meta content='#299e94' name='theme-color'/>
<link href='/manifest.json' rel='manifest'/>

- استبدل رمز اللون المشار اليه بنفس اللون الذي تم استخدامه في ملف manifest.json.

ميزة AMP

الآن اتبع الخطوات حسب القالب الخاص بك، سواء كان بقالب يدعم AMP أو قالب لا يعم AMP.

قالب يدعم AMP

إذا كنت تستخدم قالب يدعم AMP، يجب عليك اتباع الخطوات التالية:

- قم بإضافة الكود التالي لجافا سكريبت AMP Serviceworker أدناه على العلامة <head> أو فوقها.

<script async='async' custom-element='amp-install-serviceworker' src='https://cdn.ampproject.org/v0/amp-install-serviceworker-0.1.js'/>

- قم بلصق الكود التالي أعلاه على العلامة </body>.

<amp-install-serviceworker data-iframe-src='/offline.html' layout='nodisplay' src='/sw.js'/>

قالب لا يدعم AMP

إذا كنت تستخدم قالب غير قالب AMP، يجب عليك اتباع الخطوات التالية:
- قم بإضافة الكود الجافا سكريبت التالي أعلى العلامة </body>.

<script>/*<![CDATA[*/ /* Service Worker */ if('serviceWorker' in navigator){window.addEventListener('load',()=>{navigator.serviceWorker.register('/sw.js').then(registration=>{console.log('ServiceWorker registeration successful')}).catch(registrationError=>{console.log('ServiceWorker registration failed: ', registrationError)})})}; /*]]>*/</script>

أخيرًا، قم بالنقر على لحفظ التغييرات مباشرة قم بزيارة مدونتك على هاتفك المحمول، مثلاً جهاز Android او Iphone، حيث ستظهر لديك زرًا لتثبيت تطبيق الويب التقدمي.

مسح ذاكرة مؤقتة JsDelivr

بعد مراجعتي لسلسة الاسئلة الشائعة عن تكوير WPAs تبين لي ان العديد من المستخدمين يسألوا عن طريقة مسح ذاكرة مؤقتة لملفات JsDelivr.

هذا هو الحل، قم ببساطة بفتح الرابط التالي في المتصفح:

https://purge.jsdelivr.net/gh/<GITUSERNAME>/<REPO>@<BRANCH>/<PATH>

الحصيلة

إن إنشاء تطبيق ويب تقدمي (PWA) لموقعك على بلوجر باستخدام منصة GitHub وخدمة Cloudflare يمكن أن يكون عملية سهلة ومثيرة. هذه الخطوات البسيطة يمكنها تحسين تجربة الزوار وجعل موقعك أكثر تفاعلية ومتاحية.
تُظهر PWAs أن التقنية لا تتوقف عند حدود معينة وأن هناك دائمًا مجال للتحسين. باستخدام تلك التكنولوجيا، يمكن أن نشهد تغييرات إيجابية كبيرة في تجربتنا على الإنترنت واستفادتنا من التكنولوجيا.

تحديث نسبي للمقال

بدلا من اعادة هيكلة الموضوع و بناءه على التحديثاث الحالية للمدونة، سأدرج قائمة بالتوضيحات و الافكار التي جائتني من خلال مراجعتي لاقتراحات المتابعين في الاسفل سوف اتطرق للمقالات التي نشرتها مؤخرا لها علاقة مباشرة و غير مباشرة بهذا المقال (كيفية إنشاء تطبيق ويب تقدمي (PWA) بسهولة لموقعك دون الحاجة لخبرة برمجية) مثلا انشاء حساب على جيتهب و ربط المدونة مع كلاود فلير و ايضا انشاء مستودع على جيتهب, ايضا تصميم ايقونة هوية المدونة بشكل إحترافي و مثقن، و كذلك تصميم لقطات الشاشة للمدونة حتى يمكننا ادراجها في زر تثبيت تطبيق PWAs. هذه الاشياء ذكرتها بشكل موجز في المقال و ارثأيت ان اضع روابط المقالات هنا بين يديك حتى يسهل عليك الوصول لها.

  1. كيفية إنشاء حساب كلاودفلير وربطه بمدونة Blogger بسهولة وأمان
  2. كيفية انشاء حساب و مستودع على جيتهب
  3. دور Favicon في تحديد هوية الموقع على الويب
  4. أهمية سكرين شوتات التطبيقات وتقنية التطبيق التقدمي (ScreenShot-PWA)

المصادر:
®Fineshop Design©, OpenAi®, Google®, Cloudflare .
بتصريف: ©SiwaneXYZ, elhizazi


عن المؤلف

جمال الحزازي
مرحبا انا منشئ محتوى رقمي (صِوانˣʸᶻ) مهتم بالتصميم ui/ux، مدون في مجال التقنية و العلوم تعرف على المزيد.
اشتري لي كوب قهوة ☕

3 تعليقات

  1. جمال الحزازي
    جمال الحزازي
    كيفية إنشاء تطبيق ويب تقدمي (PWA) بسهولة لموقعك دون الحاجة لخبرة برمجية
  2. جمال الحزازي
    جمال الحزازي
    <amp-install-serviceworker data-iframe-src='/offline.html' layout='nodisplay' src='/sw.js'/>
  3. جمال الحزازي
    جمال الحزازي
    مزايا تطبيقات الويب التقدمية:
    تتمتع تطبيقات الويب التقدمية بالعديد من المزايا، بما في ذلك:
    الأداء: يمكن أن تعمل تطبيقات الويب التقدمية بشكل أسرع من تطبيقات الويب التقليدية.
    التفاعلية: يمكن أن تكون تطبيقات الويب التقدمية أكثر تفاعلية من تطبيقات الويب التقليدية.
    الاستقلالية: يمكن تشغيل تطبيقات الويب التقدمية دون اتصال بالإنترنت.
اكتب تعليقك 🤗، لكن تيقن ان كلماتك تعبر عن من انت.
"لا يقال قف لاراك بل تكلم لأعرفك"

الانضمام إلى المحادثة

الانضمام إلى المحادثة