الأخبار التكنولوجية والاستعراضات والنصائح!

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

فوربس، Twitterأوبر أو لو إكويب أو برقية أو Instagram هم بعض من العمالقة الذين تقدموا إلى الأمام وأنشأوا PWA الخاصة بهم ، أو التطبيقات التقدمية كما هي معروفة بشكل شائع. يشير هذا السيناريو إلى احتمال نسيان المواقع التقليدية.

من الطبيعي أن تطورت مواقع الويب كما نعرفها أكثر فأكثر حتى تصبح نسخًا متماثلة أقل قوة من التطبيقات الأصلية. و PWA هو في الأساس نتاج هذا التطور، التي وجدت الآن طريقة لتقديم تجربة مماثلة لتجربة تطبيقات الهاتف المتحرك من أي متصفح.

إذا كنت لا تريد أن يتم جرها عبر الزمن ، من المهم أن تبدأ في التفكير في جعل موقع الويب الخاص بك تقدمًا ، أو على الأقل أقرب ما يمكن، نظرًا لأن هذا سيبدأ في زيادة الوزن عند تحديد موضعه عاجلاً وليس آجلاً.

ما هو تطبيق الويب التدريجي وكيف يختلف عن التطبيق الأصلي؟

تطبيق التدريجي هو أداة مبرمجة ومكتوبة بلغات الويب مثل HTML5 و JavaScripts و CSS ، ولكن هذا يتصرف مثل تطبيق الهاتف المحمول، الحفاظ على خصائص هذه باعتبارها وجود تخزين على الجهاز ، مما يسمح لاستخدامه دون اتصال بالإنترنت.

الاختلافات بين التقدمي والمواطن ليست كثيرة ، منذ أول شيء تحاول القيام به هو أن تبدو مثل الثانية، ولكن إذا استطعنا تحديد عدة التي تجعلنا نفضل واحد على الآخر:

  • المتعدد: يتمثل الاختلاف الرئيسي بين الآخر والآخر في حقيقة أنه لا يمكن استخدام التطبيق الأصلي إلا على الجهاز الذي تم تثبيته عليه ، لذا لاستخدامه على جهاز آخر ، يجب عليك تنزيله من نقطة الصفر. تطبيق الويب من جانبه عبارة عن نظام أساسي مشترك حيث يمكنك الوصول إليه من أي متصفح كما لو كان موقع ويب.
  • الوزن: حاليًا يمكننا العثور على تطبيقات أصلية ثقيلة كبرنامج كمبيوتر ، لذلك يعتمد ذلك على الطاقة. من جانبها ، نادراً ما تتجاوز مواقع الويب التقدمية ميغابايت.
  • تحديثات سريعة: إذا كان التطبيق كبيرًا جدًا ، في كل مرة يتم تحديثه ، سيستغرق الأمر بضع دقائق للقيام بذلك. يعد التطبيق التدريجي أكثر تنوعًا في هذا الصدد نظرًا لكونه خفيفًا جدًا ، يتم إجراء التحديثات في غضون ثوانٍ.

مكونات PWA ما الذي يتطلبه الأمر لصنع واحدة؟

يتكون التطبيق التدريجي أساسًا من أربعة أجزاء ؛ البيان ، عامل الخدمة ، الأيقونة والخادم. كل واحد منهم لديه دور أساسي في هيكل الأداة بأكملها.

بيان التطبيق

بيان تطبيق PWA إنه ملف JSON الذي تحدد فيه كل معلومات هذا. حيث يتم الإشارة إلى لون السمة والاسم ولون الخلفية والرمز والتفاصيل.

عامل الخدمة

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

أيقونة

الرمز ليس أكثر من الصورة التي ستعرف تطبيقك من تطبيقات الويب الأخرى في السوق ، يجب أن تصممها بنفسك لأن هذا سيكون السمة المميزة للويب.

HTPPS

أخيرًا ، سيكون من الضروري وجود خادم آمن مع شهادة SSL المقابلة له. لن تقوم المستعرضات أبدًا بتشغيل PWA التي يتم استضافتها على HTPP مثل العديد من مواقع الويب حاليًا. أهم شيء في التطبيق التدريجي هو أمانه ، وستراقبه المتصفحات.

ما الذي سنحتاجه لبرمجة تطبيق الويب التدريجي هذا؟

لقد وصلنا إلى لحظة الحقيقة التي سيتعين علينا فيها العمل لإنشاء تطبيق الويب التدريجي الخاص بنا. لن يكون هذا أكثر من مجرد عامل تنبؤ بسيط بالطقس سيخبرك عن درجة الحرارة والرطوبة والضغط الجوي.

لتكون قادرًا على إنشائه ، سيكون من الضروري أن نفي ببعض المتطلبات الهامة التي سيتعين علينا القيام بها قبل أن نبدأ البرمجة. هذه هي التالية:

  • مفتاح Dark Sky API: ستأتي بيانات تطبيق الطقس لدينا مباشرةً من واجهة برمجة التطبيقات هذه ، لذلك يجب أن تحصل على مفتاح منها. هذه مجانية تمامًا للمشاريع الصغيرة غير الهادفة للربح مثل تلك التي سنقوم بإنشائها.
  • المعرفة البرمجة: لن نخدعك ، لفهم ما سنخبرك أنه يجب عليك على الأقل فهم برمجة الويب وأهم لغات HTML5 و CSS و JavaScripts.

خطوات لإنشاء تطبيق ويب تدريجي يعمل مع وبدون الإنترنت

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

الحصول على Dark Sky API

كما ذكرنا من قبل ، فإن أول شيء يجب عليك فعله هو الحصول على مفتاح Dark Sky API، والتي سوف توفر بيانات الطقس إلى التطبيق التدريجي لدينا. للقيام بذلك يجب أن تذهب مباشرة إلى https://darksky.net/dev، تسجيل وطلب المفتاح.

بمجرد الحصول عليها يجب عليك التحقق من أنه يعمل بشكل مثالي. للقيام بذلك ، يجب أن تأخذ الرابط التالي واستبدل مكانه "ClaveAqui" لمفتاح API الذي حصلت عليه للتو. إذا سارت الأمور على ما يرام ، يجب أن تكون قادرًا على رؤية توقعات مدينة نيويورك دون مشاكل.

https://api.darksky.net/forecast/ClaveAqui/40.7720232،-73.9732319

احصل على كود التطبيق

هذا في الواقع مختبر تجريبي ، لذلك أخذنا مستودعًا مباشرةً من Developers Google حتى تتمكن من إجراء هذا الاختبار الموجه. للحصول على هذا المستودع ، تحتاج إلى استخدام Glitch ، وهي منصة مفيدة للغاية تساعد المطورين على تبادل المعلومات دون مشاكل. ما يجب عليك فعله هو ما يلي:

  • اذهب إلى Glitch.com وفي الزاوية اليمنى العليا من الشاشة ، انقر فوق «مشروع جديد» ثم أين تقول «استنساخ من جيت ريبو ».
  • سيؤدي ذلك إلى فتح نافذة صغيرة حيث سيكون عليك لصق العنوان التالي "Https://github.com/googlecodelabs/your-first-pwapp.git" وانقر على "OK".

مستودع مفتوح en-glitch "width =" 800 "height =" 384 "src =" https://internetpasoapaso.com/wp-content/uploads/abrir-reposititorio-en-glitch-e1564160680590.jpg "data-pagespeed -url-hash = "300248324" onload = "pagespeed.CriticalImages.checkImageForCriticality (this)؛" /></p><ul><li>في هذا المستودع هو كل المعلومات التي تحتاجها. الآن يجب عليك الانتقال إلى ملف .env وتعديل حيث يقول <strong>DARKSKY_API_KEY = »كلمة المرور هنا»</strong> ووضع مفتاح واجهة برمجة تطبيقات Dark Sky حيث يقول <strong>كلمة المرور هنا.</strong></li></ul><p><img class= مراجعة المنارة

أساسا مع هذا الرمز اكتمال PWA ، لكن لا تزال هناك عيوب يجب أن نصحح أنفسنا وسوف نكتشفها بفضل هذه المراجعة. تحتوي هذه الأداة على قسم مصمم خصيصًا لإجراء عمليات تدقيق للمواقع التقدمية مثل الذي نقوم بإنشائه ولهذا يجب علينا القيام بما يلي:

  • افتح مشروعك في علامة تبويب جديدة في متصفح Chrome.
  • مفتوحة في وقت لاحق كروم DevTools وتضع نفسك في علامة التبويب مراجعة الحسابات. يعرض النظام الأساسي هنا قائمة بفئات التدقيق التي يجب أن تتركها ممكنة.
  • الشيء التالي هو الضغط على تنفيذ عمليات التدقيق وبعد بضع ثوانٍ ، تمنحك Lighthouse تقريرًا عن الصفحة.

تدوين PWA "width =" 800 "height =" 517 "src =" https://internetpasoapaso.com/wp-content/uploads/Auditoria-de-la-la-PWA-e1564573202784.jpg "data-pagespeed -url-hash = "778247044" onload = "pagespeed.CriticalImages.checkImageForCriticality (this)؛" /></p><p>في هذه الحالة ، سنركز فقط على نتائج قسم PWA ، والتي هي التي تهمنا. <strong>بالتأكيد سوف يلقي المشاكل التالية:</strong></p><ul><li><strong>❗ فشل:</strong> الصفحة الحالية لا تستجيب مع 200 عند قطع الاتصال.</li><li><strong>❗ فشل:</strong> لا يستجيب start_url مع 200 عند قطع الاتصال.</li><li><strong>❗ فشل:</strong> لا تقم بتسجيل عامل خدمة يتحكم في الصفحة و start_url.</li><li><strong>❗ فشل:</strong> بيان تطبيق الويب لا يلبي متطلبات التثبيت.</li><li><strong>❗ فشل:</strong> لم يتم تكوينه لشاشة رئيسية مخصصة.</li><li><strong>❗ فشل:</strong> لا يتم تعيين لون سمة شريط العناوين.</li></ul><div class='code-block code-block-9' style='margin: 8px auto; text-align: center; display: block; clear: both;'><style>.ai-rotate {position: relative;}
.ai-rotate-hidden {visibility: hidden;}
.ai-rotate-hidden-2 {position: absolute; top: 0; left: 0; width: 100%; height: 100%;}
.ai-list-data, .ai-ip-data, .ai-filter-check, .ai-fallback, .ai-list-block, .ai-list-block-ip, .ai-list-block-filter {visibility: hidden; position: absolute; width: 50%; height: 1px; top: -1000px; z-index: -9999; margin: 0px!important;}
.ai-list-data, .ai-ip-data, .ai-filter-check, .ai-fallback {min-width: 1px;}</style><div class='ai-rotate ai-unprocessed ai-timed-rotation ai-9-1' data-info='WyI5LTEiLDJd' style='position: relative;'><div class='ai-rotate-option' style='visibility: hidden;' data-index=

الآن ، مهمتنا في البرنامج التعليمي التالي هي جعل كل هذا معتمدًا ، حتى نجعلنا الويب التدريجي العمل مع وبدون اتصال بالإنترنت ، وتكون قابلة للتثبيت ولها بيان تطبيق لائق.

إنشاء بيان التطبيق

السبب وراء فشل التطبيق في الظهور هو أنه لا يحتوي في الأساس على أحد ، لذا يتعين علينا تصديقه ، على الرغم من أنه في حالتك ، سيتعين عليك ببساطة تعديل الكود الأساسي للبيان الذي أعددناه لك.

{   "name": "Clima",   "short_name": "Clima",   "icons": ({     "src": "/images/icons/icon-128x128.png",       "sizes": "128x128",       "type": "image/png"     }, {       "src": "/images/icons/icon-144x144.png",       "sizes": "144x144",       "type": "image/png"     }, {       "src": "/images/icons/icon-152x152.png",       "sizes": "152x152",       "type": "image/png"     }, {       "src": "/images/icons/icon-192x192.png",       "sizes": "192x192",       "type": "image/png"     }, {       "src": "/images/icons/icon-256x256.png",       "sizes": "256x256",       "type": "image/png"     }, {       "src": "/images/icons/icon-512x512.png",       "sizes": "512x512",       "type": "image/png"     }),   "start_url": "/index.html",   "display": "standalone",   "background_color": "#3E4EB8",   "theme_color": "#2F3BA2" }

لإضافة هذا البيان إلى التطبيق الخاص بك. ثم يجب أن نخطر المتصفح ببياننا بإضافة <link rel = "manifest" … لكل صفحة من طلباتنا. أضف الآن السطر التالي إلى العنصر في ملف index.html.

 

بعد ذلك يجب أن نضيف وصفا ميتا لتطبيقنا. لهذا يجب علينا ببساطة أضف سطر التعليمات البرمجية التالي إلى رأس التطبيق:

أخيرًا ، قمنا بتعيين لون شريط العناوين الخاص بالتطبيق التدريجي، التي يجب عليك نسخ سطر التعليمات البرمجية التالي في من التطبيق الخاص بك

 

جعل شبكة الإنترنت حاليا

الآن يأتي أحد أكثر الأجزاء تعقيدًا في الدليل بأكمله ، سوف ندخل في البرمجة الصعبة والصعبة لإنشاء عامل الخدمة لدينا بشكل صحيح، عنصر ذكرناه مسبقًا لا غنى عنه لأي تطبيق تدريجي.

جميع المستخدمين ما نتوقعه من تطبيق ما هو أنه يمكن استخدامه دون اتصال بالإنترنت ، بحيث يسهل علينا إدخال المحتوى دون وجوده على أي شبكة. هذا مهم بنفس القدر في التطبيق التدريجي ، وبالتالي فإن الحاجة إلى خروج ديناصور كروم أمر لا غنى عنه.

ما سنفعله هنا هو صفحة غير متصلة بالإنترنت مخصصة. لذلك عندما يدخل شخص ما إلى التطبيق ولا يوجد لديه اتصال ، فإنه هو الذي يتم عرضه بدلاً من الديناصور المزعج. لهذا سنقوم بإنشاء عامل الخدمة الأول لدينا.

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

أول شيء سنفعله هو تسجيل عامل الخدمة ، الذي يجب عليك إضافة سطر التعليمات البرمجية التالي إلى ملف الفهرس للتطبيق التدريجي:

// CODELAB: Register service worker. if ('serviceWorker' in navigator) {   window.addEventListener('load', () => {     navigator.serviceWorker.register('/service-worker.js')         .then((reg) => {           console.log('Service worker registered.', reg);         });   }); }

الآن يجب أن تشير إلى عامل الخدمة الصفحة التي سيتم عرضها عندما تكون غير متصل. داخل المستودع ، قمنا بالفعل بإنشاء صفحة مخصصة في وضع عدم الاتصال في (عام / متواجد حاليا. html). ما يجب عليك فعله هو مجرد الذهاب إلى عام / خدمة عامل في مستودع وفي قسم const "FILES_TO_CACHE = (
) ؛ » تشمل القيمة "Offline.html". يجب أن تبدو في الصورة:

الآن الشيء التالي الذي يجب أن نفعله هو إضافة سطر التعليمات البرمجية هذا إلى الحدث 'تثبيت' ليقول عامل الخدمة الذي يقوم بتصحيح الشبكة التقدمية في وضع عدم الاتصال:

evt.waitUntil(     caches.open(CACHE_NAME).then((cache) => {       console.log('(ServiceWorker) Pre-caching offline page');       return cache.addAll(FILES_TO_CACHE);     }) );

حتى الآن نذهب في منتصف الطريق. الشيء التالي هو جعل عامل الخدمة لدينا يقوم بتنظيف ذاكرة التخزين المؤقت بحيث لا توجد بيانات قديمة فيها. لهذا السبب يتعين علينا إضافة هذا الرمز في مجلد public / service-worker.js:

// CODELAB: Remove previous cached data from disk. evt.waitUntil(     caches.keys().then((keyList) => {       return Promise.all(keyList.map((key) => {         if (key !== CACHE_NAME) {           console.log('(ServiceWorker) Removing old cache', key);           return caches.delete(key);         }       }));     }) );

أخيرًا ، سنقوم بإضافة سطر آخر من التعليمات البرمجية لجعل طلبات شبكة عامل الخدمة أكثر فاعلية وفي حالة الفشل ، دعنا نعيد توجيهك إلى الصفحة غير المتصلة التي ذكرناها أعلاه. ما يجب عليك فعله هو إضافة ما يلي في المجلد public / service-worker.js:

// CODELAB: Remove previous cached data from disk. evt.waitUntil(     caches.keys().then((keyList) => {       return Promise.all(keyList.map((key) => {         if (key !== CACHE_NAME) {           console.log('(ServiceWorker) Removing old cache', key);           return caches.delete(key);         }       }));     }) );

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

تقديم تجربة كاملة حاليا

لفهم هذا بشكل أفضل ، من المهم للغاية أن تبحث في دورة حياة عامل الخدمة، لأن هذه الخطوات مرتبطة جدا بذلك.

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

// CODELAB: Add code to get weather forecast from the caches object. if (!('caches' in window)) {   return null; } const url = `${window.location.origin}/forecast/${coords}`; return caches.match(url)     .then((response) => {       if (response) {         return response.json();       }       return null;     })     .catch((err) => {       console.error('Error getting data from cache', err);       return null;     });

الآن الشيء التالي هو تعديل العنصر UpdateData، وهو أقل من السابق. لذلك نقوم بتعديل الكود كما يلي:

// CODELAB: Add code to call getForecastFromCache. getForecastFromCache(location.geo)     .then((forecast) => {       renderForecast(card, forecast);     });

مع هذا ، قمنا بالفعل بحل مشكلة الطلبات غير المتزامنة التي يجب عليك تقديمها، حتى الآن ، فإنه قادر بالفعل على توفير تجربة دون اتصال كاملة أو أقل. لكنه لا يزال غير قادر على العمل بنسبة 100 ٪ دون اتصال بالإنترنت.

للقيام بذلك ، يجب أولاً تخزين موارد التطبيق مسبقًا مؤقتًا ، والتي تتم عن طريق إضافة ملف Data_Cache_NAME في المجلد عام / عامل خدمة. نحن نفعل ذلك مع الكود التالي:

// CODELAB: Update cache names any time any of the cached files change. const CACHE_NAME = 'static-cache-v2'; const DATA_CACHE_NAME = 'data-cache-v1';

الآن ، والشيء التالي هو تحديث File_TO_CACHE في نفس مجلد عامل الخدمة ، لذلك نضيف قائمة الملفات كاملة. ويتم ذلك مع الكود التالي:

// CODELAB: Add list of files to cache here. const FILES_TO_CACHE = (   '/',   '/index.html',   '/scripts/app.js',   "http://internetpasoapaso.com/scripts/install.js",   '/scripts/luxon-1.11.4.js',   '/styles/inline.css',   '/images/add.svg',   '/images/clear-day.svg',   '/images/clear-night.svg',   '/images/cloudy.svg',   '/images/fog.svg',   '/images/hail.svg',   '/images/install.svg',   '/images/partly-cloudy-day.svg',   '/images/partly-cloudy-night.svg',   '/images/rain.svg',   '/images/refresh.svg',   '/images/sleet.svg',   '/images/snow.svg',   '/images/thunderstorm.svg',   '/images/tornado.svg',   '/images/wind.svg', );

ما يجب أن نأخذه في الاعتبار هو أنه يجب علينا تحديث Cache_NAME باستمرار عند إضافة ملف جديد. لقد أزلنا offline.html لأنه في هذه الحالة ، لا يحتاج موقع الويب الخاص بنا إلى ذلك لأنه يحتوي الآن على جميع الموارد اللازمة للعمل دون اتصال بالإنترنت وعدم عرض صفحة «لا يوجد اتصال».

للتأكد من حدثنا "تنشيط" لا تحذف أي نوع من الملفات ، يجب علينا تغيير القيمة «إذا (مفتاح! == CACHE_NAME) {« بواسطة «إذا (مفتاح! == CACHE_NAME && key! == DATA_CACHE_NAME) {«. في مجلد Service-worker.js الخاص بنا.

والخطوة التالية في البرمجة لدينا هي تأكد من أن التطبيق يحفظ توقعات الطقس حتى تتمكن من الوصول إليها بسهولة أكبر في المستقبل. لهذا سيكون لديك ل أضف ما يلي في ملف service-worker.js:

// CODELAB: Add fetch event handler here. if (evt.request.url.includes('/forecast/')) {   console.log('(Service Worker) Fetch (data)', evt.request.url);   evt.respondWith(       caches.open(DATA_CACHE_NAME).then((cache) => {         return fetch(evt.request)             .then((response) => {               // If the response was good, clone it and store it in the cache.               if (response.status === 200) {                 cache.put(evt.request.url, response.clone());               }               return response;             }).catch((err) => {               // Network request failed, try to get it from the cache.               return cache.match(evt.request);             });       }));   return; } evt.respondWith(     caches.open(CACHE_NAME).then((cache) => {       return cache.match(evt.request)           .then((response) => {             return response || fetch(evt.request);           });     }) );

بعد القيام بكل هذا سيكون لدينا تطبيق تدريجي يوفر تجربة كاملة دون اتصال بالإنترنت يمكننا استخدامه من أي متصفح. لدينا عمليا كل العمل المنجز ، ولكن لا يزال هناك واحد آخر التفاصيل لدعم:

اجعل التطبيق قابلاً للتثبيت

لإنهاء دليلنا ، ما يجب علينا فعله هو ببساطة أن تطبيقنا قابل للتثبيت في المتصفح ، شيء على الرغم من أنه يبدو صعباً هو أسهل شيء نفعله في العملية برمتها التي علمناها حتى الآن.

أول شيء سنفعله هو إضافة الملف install.js لدينا index.html و، أيا كان يتم تحقيق ذلك عن طريق نسخ هذا الرمز إلى الملف:

 

الآن يجب أن نذهب إلى الحدث install.js واكتب السطر التالي من التعليمات البرمجية لمتابعة عملية جعل تطبيقنا قابلاً للتثبيت:

// CODELAB: Add event listener for beforeinstallprompt event window.addEventListener('beforeinstallprompt', saveBeforeInstallPromptEvent);

ثم لإظهار زر التثبيت ، وهو أمر أساسي في كل هذا ، يجب أن نواصل تعديلنا install.js مع الكود التالي:

// CODELAB: Add code to save event & show the install button. deferredInstallPrompt = evt; installButton.removeAttribute('hidden');

الآن هو الوقت المناسب لجدولة لإظهار موجه وإخفاء زر التثبيت لأنه لا يمكن القيام بذلك إلا مرة واحدة. نتبع التالي في ملف install.js:

// CODELAB: Add code show install prompt & hide the install button. deferredInstallPrompt.prompt(); // Hide the install button, it can't be called twice. evt.srcElement.setAttribute('hidden', true);

جاهز ، الآن أصبح التطبيق التدريجي الذي أنشأناه قابلاً للتثبيت تمامًا وتعلمت أن تفعل مع internetpasoapaso.com أننا نعلمك دائمًا كل ما تحتاج لمعرفته حول الإنترنت والحوسبة. نأمل أن تجد هذه المعلومات مفيدة للغاية.

إذا كانت لديك أي أسئلة ، فاتركها في التعليقات ، وسوف نقوم بالرد عليك في أقرب وقت ممكن ، وسيكون بالتأكيد عونًا كبيرًا لمزيد من أعضاء المجتمع. شكرا! ????