تحسين تحميل WebFont وعرضه

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

لحلّ مشكلة الملفات الكبيرة التي تحتوي على جميع الصيغ، تم تصميم قاعدة CSS‏ @font-face خصيصًا للسماح لك بتقسيم مجموعة الخطوط إلى مجموعة من الموارد. على سبيل المثال، مجموعات فرعية من الأحرف اليونيكود ونُسخ مختلفة من الأنماط

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

السلوك التلقائي

إنّ تحميل الخطوط بشكلٍ بطيء له تأثير خفيّ مهمّ قد يؤدّي إلى تأخير عرض النص. على المتصفّح إنشاء شجرة العرض، التي تعتمد على شجرَتَي DOM وCSSOM، قبل أن يعرف موارد الخطوط التي يحتاجها لعرض النص. ونتيجةً لذلك، يتأخّر طلب الخطوط بعد مرور وقت طويل على طلب الموارد المهمة الأخرى، وقد يتم حظر المتصفّح من عرض النص إلى أن يتم جلب المورد.

مسار العرض الحرج للخط

  1. يطلب المتصفّح مستند HTML.
  2. يبدأ المتصفّح في تحليل استجابة HTML وإنشاء نموذج DOM.
  3. يرصد المتصفّح ملفات CSS وJS والموارد الأخرى ويرسل الطلبات.
  4. ينشئ المتصفّح CSSOM بعد استلام كل محتوى CSS ويدمجه مع شجرة DOM لإنشاء شجرة العرض.
    • يتم إرسال طلبات الخطوط بعد أن تشير شجرة العرض إلى أنواع الخطوط المطلوبة لعرض النص المحدّد على الصفحة.
  5. ينفِّذ المتصفّح التنسيق ويعرض المحتوى على الشاشة.
    • إذا لم يكن الخط متاحًا بعد، قد لا يعرض المتصفّح أيّ بكسل من النص.
    • بعد توفّر الخط، يرسم المتصفّح وحدات بكسل النص.

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

من خلال تحميل WebFonts مسبقًا واستخدام font-display للتحكّم في سلوك المتصفّحات مع الخطوط غير المتوفّرة، يمكنك منع ظهور صفحات فارغة وتغيُّرات في التنسيق بسبب تحميل الخطوط.

تحميل موارد WebFont مُسبقًا

إذا كان من المرجّح أن تحتاج صفحتك إلى WebFont معيّن مستضاف على عنوان URL معروف مسبقًا، يمكنك الاستفادة من ميزة منح الأولوية للموارد. سيؤدي استخدام <link rel="preload"> إلى بدء طلب الحصول على WebFont في وقت مبكر من مسار المعالجة المُهمّ، بدون الحاجة إلى الانتظار إلى أن يتم إنشاء CSSOM.

تخصيص وقت تأخير عرض النص

على الرغم من أنّ التحميل المُسبَق يزيد من احتمال توفّر WebFont عند عرض محتوى الصفحة، فإنه لا يقدّم أيّ ضمانات. لا يزال عليك مراعاة سلوك المتصفّحات عند عرض نص يستخدم font-family غير متوفّر بعد.

في المقالة تجنُّب استخدام نص غير مرئي أثناء تحميل الخطوط، يمكنك ملاحظة أنّ سلوك المتصفّح التلقائي غير متّسق. ومع ذلك، يمكنك إخبار المتصفّحات الحديثة بالطريقة التي تريدها أن تتصرّف بها باستخدام علامة font-display.

توافق المتصفّح

  • Chrome: 60
  • ‫Edge: 79
  • Firefox: 58.
  • ‫Safari: 11.1

المصدر

على غرار سلوكيات وقت الاستراحة الحالية للخطوط التي تنفذها بعض المتصفّحات، قسّمfont-display مدة تنزيل الخط إلى ثلاث فترات رئيسية:

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

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

للعمل مع سمة font-display، أضِفها إلى قواعد @font-face:

@font-face {
  font-family: 'Awesome Font';
  font-style: normal;
  font-weight: 400;
  font-display: auto; /* or block, swap, fallback, optional */
  src: local('Awesome Font'),
       url('/fonts/awesome-l.woff2') format('woff2'), /* will be preloaded */
       url('/fonts/awesome-l.woff') format('woff'),
       url('/fonts/awesome-l.ttf') format('truetype'),
       url('/fonts/awesome-l.eot') format('embedded-opentype');
  unicode-range: U+000-5FF; /* Latin glyphs */
}

يتيح المتغيّر font-display حاليًا النطاق التالي من القيم:

  • auto
  • block
  • swap
  • fallback
  • optional

لمزيد من المعلومات عن التحميل المُسبَق للخطوط والسمة font-display، اطّلِع على المشاركات التالية:

Font Loading API

عند استخدام <link rel="preload"> وCSS font-display معًا، يمكنك التحكّم بشكل كبير في تحميل الخطوط وعرضها، بدون إضافة الكثير من النفقات العامة. ولكن إذا كنت بحاجة إلى تخصيصات إضافية، وكنت على استعداد لتحمل النفقات العامة الناتجة عن تشغيل JavaScript، يتوفّر خيار آخر.

توفّر واجهة برمجة التطبيقات Font Loading API واجهة برمجة نصية لتحديد وتعديل خطوط CSS، وتتبُّع مستوى تقدّم تنزيلها، وإلغاء سلوك التحميل البطيء التلقائي. على سبيل المثال، إذا كنت متأكدًا من أنّه يجب استخدام نوع خط معيّن، يمكنك تحديده وإخبار المتصفّح ببدء جلب فوري لمصدر الخط:

توافق المتصفّح

  • Chrome: 35
  • ‫Edge: 79
  • Firefox: 41.
  • Safari: 10

المصدر

var font = new FontFace("Awesome Font", "url(/fonts/awesome.woff2)", {
  style: 'normal', unicodeRange: 'U+000-5FF', weight: '400'
});

// don't wait for the render tree, initiate an immediate fetch!
font.load().then(function() {
  // apply the font (which may re-render text and cause a page reflow)
  // after the font has finished downloading
  document.fonts.add(font);
  document.body.style.fontFamily = "Awesome Font, serif";

  // OR... by default the content is hidden,
  // and it's rendered after the font is available
  var content = document.getElementById("content");
  content.style.visibility = "visible";

  // OR... apply your own render strategy here...
});

بالإضافة إلى ذلك، بما أنّه يمكنك التحقّق من حالة الخط (من خلال طريقة check()) وتتبّع مستوى تقدّم عملية تنزيله، يمكنك أيضًا تحديد استراتيجية مخصّصة لعرض النص على صفحاتك:

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

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

يجب الاحتفاظ بذاكرة التخزين المؤقت بشكل صحيح.

تكون ملفات خطوط الخطوط عادةً ملفات ثابتة لا يتم تعديلها بشكل متكرّر. ونتيجةً لذلك، تكون هذه الموارد مناسبة بشكل مثالي لوقت انتهاء صلاحية طويل للحد الأقصى للعمر. احرص على تحديد كل من عنوان ETag الشَرطي، وسياسة Cache-Control المثلى لجميع موارد الخطوط.

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

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

قائمة التحقّق من تحميل خطوط الويب

  • تخصيص تحميل الخطوط وعرضها باستخدام <link rel="preload"> أو font-display أو Font Loading API: قد يؤدي سلوك التحميل الكسول التلقائي إلى تأخير عرض النص. تتيح لك ميزات منصّة الويب هذه تجاوز هذا السلوك لخطوط معيّنة، وتحديد استراتيجيات عرض مخصّصة ومهلة للمحتوى المختلف على الصفحة.
  • تحديد سياسات إعادة التحقّق والتخزين المؤقت الأمثل: الخطوط هي موارد ثابتة يتم تعديلها بمعدل منخفض. تأكَّد من أنّ خوادمك توفّر طابعًا زمنيًا لعمر أقصى طويل وعلامة مميّزة لإعادة إثبات الصلاحية للسماح بإعادة استخدام الخط بفعالية بين الصفحات المختلفة. في حال استخدام worker، تكون استراتيجية "الخزينة أولاً" مناسبة.

الاختبار الآلي لسلوك تحميل WebFont باستخدام Lighthouse

يمكن أن يساعدك Lighthouse في تنفيذ عملية التأكّد من اتّباع أفضل الممارسات لتحسين خطوط الويب بشكل آلي.

يمكن أن تساعدك عمليات التدقيق التالية في التأكّد من أنّ صفحاتك تستمر في اتّباع أفضل الممارسات لتحسين خطوط الويب بمرور الوقت: