برمجة اختيار الموارد باستخدام تعديلات العميل

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

  • تحديد التنسيق المناسب (المتجه مقابل النقطي)
  • تحديد تنسيقات الترميز الأمثل (jpeg وwebp وما إلى ذلك)
  • تحديد إعدادات الضغط الصحيحة (فقدان الجهاز مقابل فقدان البيانات)
  • تحديد البيانات الوصفية التي يجب الاحتفاظ بها أو إزالتها
  • إنشاء صيغ متعددة لكل شاشة عرض + دقة DPR
  • ...
  • مراعاة نوع الشبكة لدى المستخدم وسرعته وتفضيلاته

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

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

قصة مطوّر البرامج المهتم بالأداء

هناك مرحلتان مختلفتان للبحث من خلال مساحة تحسين الصور: وقت الإنشاء ووقت التشغيل.

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

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

<img src="/image/thing" sizes="50vw"
        alt="image thing displayed at 50% of viewport width">

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

  1. وللحصول على أفضل ضغط، فإنها تريد استخدام تنسيق الصورة الأمثل لكل عميل: WebP for Chrome، وJPEG XR for Edge، وJPEG بالنسبة إلى الباقي.
  2. للحصول على أفضل جودة مرئية، تحتاج إلى إنشاء متغيرات متعددة لكل صورة بدرجات دقة مختلفة: 1x، 1.5x، 2x، 2.5x، 3x، وربما بضع مرات أكثر بينهما.
  3. ولتجنّب عرض وحدات بكسل غير ضرورية، يجب أن تفهم ما يعنيه "50% من إطار عرض المستخدم فعليًا"، فهناك الكثير من مساحات العرض المختلفة لإطار العرض.
  4. ومن الناحية المثالية، تريد أيضًا تقديم تجربة مرنة تتيح لمستخدمي الشبكات البطيئة جلب درجة دقة أقل تلقائيًا. بعد كل شيء، كل شيء يتعلق بالوقت للزجاج.
  5. يعرض التطبيق أيضًا بعض عناصر التحكم الخاصة بالمستخدم التي تؤثر في مورد الصورة الذي يجب جلبه، لذا يجب أخذ ذلك في الاعتبار أيضًا.

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

<picture>
    <!-- serve WebP to Chrome and Opera -->
    <source
    media="(min-width: 50em)"
    sizes="50vw"
    srcset="/image/thing-200.webp 200w, /image/thing-400.webp 400w,
        /image/thing-800.webp 800w, /image/thing-1200.webp 1200w,
        /image/thing-1600.webp 1600w, /image/thing-2000.webp 2000w"
    type="image/webp">
    <source
    sizes="(min-width: 30em) 100vw"
    srcset="/image/thing-crop-200.webp 200w, /image/thing-crop-400.webp 400w,
        /image/thing-crop-800.webp 800w, /image/thing-crop-1200.webp 1200w,
        /image/thing-crop-1600.webp 1600w, /image/thing-crop-2000.webp 2000w"
    type="image/webp">
    <!-- serve JPEGXR to Edge -->
    <source
    media="(min-width: 50em)"
    sizes="50vw"
    srcset="/image/thing-200.jpgxr 200w, /image/thing-400.jpgxr 400w,
        /image/thing-800.jpgxr 800w, /image/thing-1200.jpgxr 1200w,
        /image/thing-1600.jpgxr 1600w, /image/thing-2000.jpgxr 2000w"
    type="image/vnd.ms-photo">
    <source
    sizes="(min-width: 30em) 100vw"
    srcset="/image/thing-crop-200.jpgxr 200w, /image/thing-crop-400.jpgxr 400w,
        /image/thing-crop-800.jpgxr 800w, /image/thing-crop-1200.jpgxr 1200w,
        /image/thing-crop-1600.jpgxr 1600w, /image/thing-crop-2000.jpgxr 2000w"
    type="image/vnd.ms-photo">
    <!-- serve JPEG to others -->
    <source
    media="(min-width: 50em)"
    sizes="50vw"
    srcset="/image/thing-200.jpg 200w, /image/thing-400.jpg 400w,
        /image/thing-800.jpg 800w, /image/thing-1200.jpg 1200w,
        /image/thing-1600.jpg 1600w, /image/thing-2000.jpg 2000w">
    <source
    sizes="(min-width: 30em) 100vw"
    srcset="/image/thing-crop-200.jpg 200w, /image/thing-crop-400.jpg 400w,
        /image/thing-crop-800.jpg 800w, /image/thing-crop-1200.jpg 1200w,
        /image/thing-crop-1600.jpg 1600w, /image/thing-crop-2000.jpg 2000w">
    <!-- fallback for browsers that don't support picture -->
    <img src="/image/thing.jpg" width="50%">
</picture>

لقد تعاملنا مع الاتجاه الفني واختيار التنسيق وقدّمنا ستة صيغ لكل صورة لمراعاة التباين في DPR وعرض إطار العرض لجهاز العميل. مذهل!

لا يسمح لنا العنصر picture بتحديد أي قواعد لكيفية عمل الجهاز استنادًا إلى نوع اتصال العميل أو سرعته. مع ذلك، تسمح خوارزمية المعالجة لوكيل المستخدم بتعديل المورد الذي يجلبه في بعض الحالات. راجِع الخطوة 5. علينا فقط أن نأمل أن يكون وكيل المستخدم ذكيًا بما فيه الكفاية. (ملاحظة: لا تنطبق أي من عمليات التنفيذ الحالية). وبالمثل، لا تتوفّر عناصر الجذب في العنصر picture للسماح بمنطق خاص بالتطبيق يراعي ما يفضّله التطبيق أو المستخدم. وللحصول على آخر جزءَين من البيانات، علينا نقل كل المنطق أعلاه إلى JavaScript، ولكن هذا يؤدّي إلى فقدان تحسينات الماسح الضوئي للتحميل المُسبق التي تقدّمها picture. حسنًا،

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

التشغيل الآلي لاختيار الموارد من خلال تعديلات البرنامج

خذ نفسًا عميقًا، وعلق عدم تصديقك، ثم فكر الآن في المثال التالي:

<meta http-equiv="Accept-CH" content="DPR, Viewport-Width, Width">
...
<picture>
    <source media="(min-width: 50em)" sizes="50vw" srcset="/image/thing">
    <img sizes="100vw" src="/image/thing-crop">
</picture>

صدق أو لا تصدق، يكفي المثال أعلاه توفير جميع الإمكانات نفسها المتوفرة في ترميز الصور الطويل أعلاه، كما هو واضح، فهي تتيح للمطوّرين التحكم بشكل كامل في كيفية جلب موارد الصور ومتى يتم جلبها. يظهر الرمز "magic" في السطر الأول الذي يفعِّل إعداد تقارير تلميحات العميل، ويطلب من المتصفِّح الإعلان عن نسبة وحدات البكسل للجهاز (DPR) وعرض إطار عرض التنسيق (Viewport-Width) وعرض العرض المقصود (Width) للموارد إلى الخادم.

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

يوفّر Chrome 46 توافقًا أصليًا مع تعديلات DPR وWidth وViewport-Width. يتم إيقاف التلميحات تلقائيًا، ويعمل <meta http-equiv="Accept-CH" content="..."> أعلاه كإشارة تفعيل تطلب من Chrome إلحاق العناوين المحددة بالطلبات الصادرة. بعد تنفيذ ذلك، لنفحص عناوين الطلب والاستجابة لنموذج طلب صورة:

مخطّط التفاوض على تلميحات العميل

يعلن Chrome عن دعمه لتنسيق WebP عبر عنوان قبول الطلب، كما يعلن متصفّح Edge الجديد عن دعمه لتنسيق JPEG XR عبر العنوان "قبول".

عناوين الطلبات الثلاثة التالية هي عناوين تلميحات العميل التي تعلن عن نسبة بكسل الجهاز لجهاز العميل (3x)، وعرض إطار عرض التنسيق (460 بكسل)، وعرض العرض المقصود للمورد (230 بكسل). يوفّر ذلك جميع المعلومات اللازمة للخادم لتحديد الخيار الأمثل للصورة استنادًا إلى مجموعة السياسات الخاصة به، وهي: مدى توفُّر الموارد التي تم إنشاؤها مسبقًا، وتكلفة إعادة ترميز أو تغيير حجم مورد، ورواج المورد، والحِمل الحالي على الخادم، وما إلى ذلك. في هذه الحالة بالذات، يستخدم الخادم تلميحَي DPR وWidth ويعرض مورد WebP كما هو موضّح في العناوين Content-Type وContent-DPR وVary.

ما مِن مزايا سحرية نقلنا اختيار الموارد من ترميز HTML إلى التفاوض على استجابة الطلب بين العميل والخادم. ونتيجةً لذلك، فإن ترميز HTML مرتبط فقط بمتطلبات العرض التقديمي، وهو أمر يمكننا الوثوق في كتابته من أي مصمم ومطور، في حين يتم تأجيل البحث في مساحة تحسين الصور لأجهزة الكمبيوتر ويتم الآن تشغيله آليًا على نطاق واسع. هل تتذكر المطوّر الذي يركّز على الأداء؟ وظيفتها الآن هي كتابة خدمة صور يمكنها الاستفادة من التلميحات المقدّمة وتقديم الرد المناسب: فيمكنها استخدام أي لغة أو خادم تحبه، أو السماح لخدمة خارجية أو شبكة توصيل محتوى (CDN) بالقيام بذلك نيابةً عنها.

<img src="/image/thing" sizes="50vw"
        alt="image thing displayed at 50% of viewport width">

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

التحكّم في اختيار الموارد من خلال مشغّل الخدمات

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

self.onfetch = function(event) {
    var req = event.request.clone();
    console.log("SW received request for: " + req.url)
    for (var entry of req.headers.entries()) {
    console.log("\t" + entry[0] +": " + entry[1])
    }
    ...
}
تلميحات العميل serviceWorker.

يمنحك ServiceWorker تحكمًا كاملاً من جهة العميل في اختيار الموارد. يعد ذلك أمرًا بالغ الأهمية. دع الأمر يتعمق، لأن الاحتمالات قريبة لانهائية:

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

يوفّر العنصر picture عناصر التحكّم اللازمة في توجيه الأعمال الفنية في ترميز HTML. توفّر تعديلات العميل تعليقات توضيحية حول طلبات الصور الناتجة التي تتيح التشغيل الآلي لاختيار الموارد. يوفر ServiceWorker إمكانات إدارة الطلبات والاستجابة للعميل. هذه هي شبكة الويب القابلة للتوسيع.

الأسئلة الشائعة حول تلميحات العميل

  1. أين تتوفّر النصائح الخاصة بالعميل؟ تم الشحن في Chrome 46. قيد البحث في Firefox وEdge

  2. لماذا تتطلب ميزة "تلميحات العميل" الموافقة؟ ونريد تقليل النفقات العامة للمواقع الإلكترونية التي لن تستخدم تلميحات العميل. لتفعيل إشارات العميل، يجب أن يوفّر الموقع الإلكتروني عنوان Accept-CH أو توجيه <meta http-equiv> مكافئ في ترميز الصفحة. ومع توفّر أي من هذين الخيارين، سيُلحق وكيل المستخدم التلميحات المناسبة بجميع طلبات الموارد الفرعية. وقد نوفِّر في المستقبل آلية إضافية للحفاظ على هذا الخيار المفضّل لأصل معيَّن، ما يتيح تقديم التلميحات نفسها في طلبات التنقّل.

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

  4. هل يتم توفير تلميحات العميل لموارد الصور فقط؟ تتمثل حالة الاستخدام الأساسية وراء تلميحات DPR وViewport-width والعرض في إتاحة اختيار الموارد لمواد عرض الصور. مع ذلك، يتم تقديم التلميحات نفسها لجميع الموارد الفرعية بغض النظر عن نوعها، فعلى سبيل المثال، تحصل طلبات CSS وJavaScript أيضًا على المعلومات نفسها ويمكن استخدامها لتحسين هذه الموارد أيضًا.

  5. لا تعرض بعض طلبات الصور معلومات "العرض"، فما السبب؟ قد لا يعرف المتصفّح عرض العرض المقصود لأنّ الموقع الإلكتروني يعتمد على الحجم الأساسي للصورة. ونتيجةً لذلك، يتم حذف تلميح العرض لهذه الطلبات، وللطلبات التي ليس لها قيمة "عرض العرض"، مثل مورد JavaScript. لتلقي تلميحات عن العرض، احرص على تحديد قيمة المقاسات في صورك.

  6. ماذا عن <insert my favorite hint>؟ يتيح ServiceWorker للمطوّرين اعتراض جميع الطلبات الصادرة وتعديلها (مثل إضافة رؤوس جديدة). على سبيل المثال، من السهل إضافة معلومات تستند إلى NetInfo للإشارة إلى نوع الاتصال الحالي. يُرجى الاطّلاع على "تقارير حول الإمكانات باستخدام ServiceWorker". يتم تنفيذ النصائح "الأصلية" التي يتم شحنها في Chrome (DPR والعرض وعرض الموارد) في المتصفح لأن التنفيذ المستند إلى SW تمامًا سيؤخر جميع طلبات الصور.

  7. أين يمكنني الحصول على مزيد من المعلومات، والاطّلاع على المزيد من العروض التوضيحية، وماذا عن ذلك؟ يمكنك الاطّلاع على مستند برنامج الشرح وعدم التردد في فتح مشكلة على GitHub إذا كانت لديك ملاحظات أو أسئلة أخرى.