تعديلات جزئية تعريفية

تاريخ النشر: 19 مايو 2026

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

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

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

لقد كان فريق Chrome يدرس هذه المشكلة ويعمل على تطوير إضافات جديدة إلى منصة الويب تحت اسم التحديثات الجزئية التعريفية.

تسهّل مجموعتان جديدتان من واجهات برمجة التطبيقات عرض HTML بطريقة أقل تسلسلاً، سواء كان ذلك خارج الترتيب في مستند HTML نفسه أو من خلال طرق أسهل لإدراج HTML بشكل ديناميكي في المستندات الحالية باستخدام واجهات برمجة تطبيقات JavaScript الجديدة. يمكن للمطوّرين اختبارها بدءًا من الإصدار 148 من Chrome باستخدام العلامة chrome://flags/#enable-experimental-web-platform-features. تتوفّر أيضًا أدوات Polyfill لتتيح لك استخدام واجهات برمجة التطبيقات الجديدة هذه على الفور، حتى في المتصفّحات التي لا تتوافق معها بعد.

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

البث خارج الترتيب

تتضمّن المجموعة الأولى من التغييرات واجهات برمجة تطبيقات جديدة لبث المحتوى خارج الترتيب باستخدام عنصر <template> HTML وعناصر نائبة لتعليمات المعالجة. على سبيل المثال:

<div>
  <?marker name="placeholder">
</div>

...

<template for="placeholder">
  Here is some <em>HTML content</em>!
</template>

تتوفّر تعليمات المعالجة في XML منذ فترة طويلة، ولكن تم التعامل معها كتعليقات في HTML وتم تجاهلها. تغيّر واجهة برمجة التطبيقات الجديدة هذه الوضع وتضيف تعليمات المعالجة إلى HTML. عندما يرى المتصفّح تعليمات المعالجة <?marker name="placeholder">، لا ينفّذ أي إجراء على الفور، كما كان الحال من قبل، ولكن يمكن الرجوع إليها لاحقًا.

يبحث عنصر <template> عن تعليمات المعالجة المقابلة باستخدام السمة name ويستبدل المحتوى. في هذه الحالة، بعد التحليل، يصبح عنصر DOM على النحو التالي:

<div>
  Here is some <em>HTML content</em>!
</div>

بالإضافة إلى السمة <?marker> الخاصة بعمليات الاستبدال، هناك أيضًا علامتان لتحديد النطاق، وهما <?start> و<?end>، تسمحان بعرض محتوى العنصر النائب المؤقت قبل معالجة النموذج:

<div>
  <?start name="another-placeholder">
  Loading…
  <?end>
</div>

...

<template for="another-placeholder">
  Here is some <em>HTML content</em>!
</template>

في هذه الحالة، يظهر Loading… إلى أن يتم عرض <template>، ثم يتم استبداله بالمحتوى الجديد.

يمكن أيضًا تضمين تعليمات المعالجة في النماذج للسماح بتعديلات متعددة:

<ul id="results">
  <?start name="results">
  Loading…
  <?end>
</ul>

...

<template for="results">
  <li>Result One</li>
  <?marker name="results">
</template>
...

<template for="results">
  <li>Result Two</li>
  <?marker name="results">
</template>
...

يؤدي ذلك إلى ظهور رمز HTML التالي بعد تحليله:

<ul id="results">
  <li>Result One</li>
  <li>Result Two</li>
  <?marker name="results">
</ul>

مع تعليمات المعالجة النهائية في النهاية في حال تمت إضافة المزيد من <template for="results"> إلى المستند لاحقًا.

عرض توضيحي

في هذا الفيديو، يتم تنفيذ تطبيق أساسي لألبوم صور باستخدام HTML المتدفّق:

عرض توضيحي لألبوم صور تم تنفيذه باستخدام البث خارج الترتيب (المصدر)

يتم بث كلّ من الحالة والصور إلى HTML بعد التنسيق الأولي.

حالات الاستخدام

هناك العديد من حالات استخدام HTML التي يتم فيها تطبيق التصحيحات بترتيب غير صحيح عند دمجها مع HTML المتدفّق:

  • تصميم الجزيرة نمط شائع رائج في أُطر عمل مثل Astro وهو بنية الجزر حيث يتم ترطيب المكوّنات بشكل مستقل فوق HTML ثابت. تتيح واجهة برمجة التطبيقات <template for> إمكانية التعامل مع المحتوى الثابت بطريقة مشابهة مباشرةً في HTML. يمكن أن تستخدم أُطر عمل JavaScript هذه الميزة أيضًا لإنشاء جُزر أكثر تفاعلية أو للتعامل مع المكوّنات.
  • تسليم المحتوى عندما يكون جاهزًا بفضل بنية الجزر هذه، يمكن بث المحتوى عندما يكون جاهزًا بدلاً من تأخيره بسبب المحتوى الذي يتطلّب معالجة إضافية، مثل البحث في قاعدة البيانات. في حين أنّ العديد من المنصات تسمح ببث HTML، فإنّ طبيعة HTML المتسلسلة تعني أنّه غالبًا ما يتم حجب المحتوى أو اللجوء إلى عمليات معقدة في JavaScript DOM. يمكنك الآن عرض المحتوى الثابت أثناء الانتظار، ثمّ إدراج المحتوى الأكثر تكلفة في نهاية بث HTML.
  • يمكن عرض HTML بالترتيب الأمثل لتحسين أداء تحميل الصفحة. يمكنك أيضًا تغيير الترتيب حتى عندما يكون جاهزًا. على سبيل المثال، القوائم الضخمة هي ميزة شائعة للتنقّل تحتوي على الكثير من HTML الذي لن يراه المستخدم إلى أن تصبح الصفحة تفاعلية. يمكن تسليم هذا الجزء الكبير من HTML لاحقًا في مستند HTML لتحديد أولوية HTML الأكثر أهمية واللازم لتحميل الصفحة الأوّلي. لم يعُد الترتيب عائقًا عند استخدام HTML.

هذه مجرد بعض حالات الاستخدام، ويسرّنا أن نرى ما سيستخدمه المطوّرون في واجهة برمجة التطبيقات الجديدة هذه.

القيود والجوانب الدقيقة

تتضمّن واجهة برمجة التطبيقات بعض القيود والتفاصيل الدقيقة التي يجب الانتباه إليها:

  • لا يمكن <template for> تعديل تعليمات المعالجة إلا ضمن العنصر الرئيسي نفسه لأسباب أمنية. تؤدي إضافة <template for> مباشرةً إلى العنصر <body> إلى منحه إذن الوصول إلى المستند بأكمله (بما في ذلك <head>).
  • إنّ تعليمات المعالجة <?end> اختيارية، وفي حال عدم توفّرها، سيتم استبدال المحتوى بين العنصر <?start> ونهاية العنصر الحاوي.
  • يمكن أن يؤدي نقل تعليمات المعالجة بعد بدء بث <template for> إلى عواقب غير متوقّعة، حيث يستمر بث المحتوى الجديد إلى الموقع القديم.
  • يُرجى العِلم أنّه عند إدراج <template for> بشكل ديناميكي باستخدام طريقة مثل setHTML أو innerHTML، يكون "العنصر الرئيسي" للنموذج عند تحليله جزء مستند وسيطًا. هذا يعني أنّ إدراج HTML باستخدام هذه الطرق لا يمكنه تعديل نموذج العناصر في المستند (DOM) الحالي، ويتم التصحيح "في المكان" داخل الجزء. ومع ذلك، عند البث باستخدام طرق مثل streamHTMLUnsafe (التي سنتناولها قريبًا)، لا يوجد جزء وسيط، لذا يمكن للنماذج استبدال المحتوى الحالي.

الإضافات المحتملة في المستقبل

تشمل بعض الإضافات المستقبلية المحتملة التي يتمّ النظر فيها ما يلي:

  • عمليات تضمين من جهة العميل: مثلاً: <template for="footer" patchsrc="/partials/footer.html">
  • التجميع: من جهة العميل، يمكن أيضًا توسيع نطاق عمليات تضمين الأجزاء للتعامل مع التجميع لضمان حدوث تحديثات متعددة في الوقت نفسه.
  • منع الكتابة فوق المحتوى الذي لن يتغيّر: ويمكن تحقيق ذلك باستخدام رقم مراجعة المحتوى أو نظام تحديد الإصدارات. سيسمح ذلك بالحفاظ على الحالة بين تغييرات المسار أو التحديثات الأخرى بدلاً من إعادة ضبط المحتوى.
  • التحضير أثناء الترقيع على سبيل المثال، <template for=icon safe><svg id="from-untrusted-source">...</svg></template>

Polyfill

لقد أصدر فريق Chrome template-for-polyfill متاحًا على npm للسماح للمواقع الإلكترونية باستخدام هذه الوظيفة الجديدة على الفور حتى قبل أن تصبح متاحة في المتصفّحات الأخرى.

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

تجديد طرق إدراج HTML وبث المحتوى

لا يمكن تسليم كل المحتوى بتنسيق HTML. يتضمّن الجزء الثاني من عمل Chrome في هذا المجال تسهيل تعديل المحتوى من خلال JavaScript.

تتوفّر حاليًا عدة طرق لإدخال رمز HTML بشكل ديناميكي في مستند حالي باستخدام JavaScript:

  • setHTML
  • setHTMLUnsafe
  • طرق الضبط innerHTML وouterHTML
  • createContextualFragment
  • insertAdjacentHTML

ومع ذلك، تعمل جميعها بطرق مختلفة قليلاً مع بعض الفروق الدقيقة والاختلافات التي قد لا يضعها المطوّرون في اعتبارهم دائمًا:

  • هل سيتم استبدال المحتوى الحالي بالمحتوى الجديد أو إضافته إليه؟
  • هل يتم تنظيف تنسيق HTML الذي قد يكون خطيرًا من خلال إلغاء العلامات <script>، مثلاً؟
  • إذا لم يكن كذلك، هل يجب تشغيل <script>؟
  • كيف تعمل مع TrustedTypes؟

لم يتمكّن سوى عدد قليل من المطوّرين من إلقاء نظرة على واجهات برمجة التطبيقات هذه والإجابة عن هذه الأسئلة بثقة لكل منها.

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

مجموعة جديدة من واجهات برمجة التطبيقات الثابتة والبث

اقترح Chrome مجموعة من واجهات برمجة التطبيقات والإضافات الجديدة إلى setHTML وsetHTMLUnsafe الحالية التي تعمل على حلّ هذه المشكلة، بالإضافة إلى توفير وظيفة البث:

تتوفّر طرق لضبط المحتوى أو استبداله، بالإضافة إلى طرق لإدراج المحتوى قبل أو بعد رمز HTML الحالي. لكل طريقة مكافئات في مجموعة البث:

الإجراء ثابت البث
ضبط محتوى HTML للعنصر setHTML(html, options); streamHTML(options);
استبدال العنصر بأكمله باستخدام رمز HTML هذا replaceWithHTML(html, options); streamReplaceWithHTML(options);
أضِف رمز HTML قبل العنصر beforeHTML(html, options); streamBeforeHTML(options);
إضافة رمز HTML كعنصر ثانوي أول للعنصر prependHTML(html, options); streamPrependHTML(options);
إضافة رمز HTML كعنصر ثانوي أخير للعنصر appendHTML(html, options); streamAppendHTML(options);
أضِف رمز HTML بعد العنصر afterHTML(html, options); streamAfterHTML(options);
طرق الإدراج والبث الجديدة

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

تتلقّى الإصدارات الثابتة رمز HTML جديدًا كمعلَمة سلسلة DOM، بالإضافة إلى خيارات اختيارية:

const newHTML = "<p>This is a new paragraph</p>";
const contentElement = document.querySelector('#content-to-update');

contentElement.setHTML(newHTML);

تعمل إصدارات البث مع Streams API، مثل getWriter():

const contentElement = document.querySelector('#content-to-update');
const writer = contentElement.streamHTMLUnsafe().getWriter();

// Example stream of updating content
while (true) {
 await writer.write(`<p>${++i}</p>`);
 await new Promise((resolve) => setTimeout(resolve, 1000));
}

writer.close();

أو بدلاً من ذلك، من استجابة جلب، باستخدام سلاسل الأنابيب:

const contentElement = document.querySelector('#content-to-update');

const response = await fetch('/api/content.html');

response.body
  .pipeThrough(new TextDecoderStream())
  .pipeTo(contentElement.streamHTMLUnsafe());

نحن نخطّط أيضًا لإضافة طريقة سهلة يمكنك من خلالها البث مباشرةً بدون الحاجة إلى الخطوة الوسيطة TextDecoderStream().

تتيح لك الوسيطة options تحديد sanitizer مخصّص يكون تلقائيًا default، ما يعني إعدادات أداة التنظيف التلقائية. ويتم استخدامها على النحو التالي:

const newHTML = "<p>This is a new paragraph</p>";
const contentElement = document.querySelector('#content-to-update');

// Only allows basic formatting
const basicFormattingSanitzer = new Sanitizer({ elements: ["em", "i", "b", "strong"] });

contentElement.setHTML(newHTML, {sanitizer: basicFormattingSanitzer});

الطرق "غير الآمنة"

تتوفّر أيضًا إصدارات "غير آمنة" من كل واجهة من واجهات برمجة التطبيقات:

الإجراء ثابت البث
ضبط محتوى HTML للعنصر setHTMLUnsafe(html,options); streamHTMLUnsafe(options);
استبدال العنصر بأكمله باستخدام رمز HTML هذا replaceWithHTMLUnsafe(html, options); streamReplaceWithHTMLUnsafe(options);
أضِف رمز HTML قبل العنصر beforeHTMLUnsafe(html, options); streamBeforeHTMLUnsafe(options);
إضافة رمز HTML كعنصر ثانوي أول للعنصر prependHTMLUnsafe(html, options); streamPrependHTMLUnsafe(options);
إضافة رمز HTML كعنصر ثانوي أخير للعنصر appendHTMLUnsafe(html, options); streamAppendHTMLUnsafe(options);
أضِف رمز HTML بعد العنصر afterHTMLUnsafe(html, options); streamAfterHTMLUnsafe(options);
طرق الإدراج والبث "غير الآمنة"

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

على غرار setHTML، فإنّ setHTMLUnsafe هي طريقة حالية، ولكن تمت إضافة مَعلمة الخيارات runScripts إليها للسماح باستخدامها مع تنفيذ النص البرمجي:

const newHTML = `<p>This is a new paragraph</p>
                 <script src=script.js></script>`;
const contentElement = document.querySelector('#content-to-update');

contentElement.setHTMLUnsafe(newHTML, {runScripts: true});

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

ويعتمد مدى "عدم الأمان" على مدى موثوقية البيانات التي يتم إدخالها. تعمل جميع الطرق الثابتة Unsafe مع كل من DOM String أو TrustedHTML كمعلمات html، كما تسمح باستخدام أدوات التنظيف. مع ذلك، فإنّ الغرض من runScript هو السماح بتنفيذ النصوص البرمجية، ولهذا السبب لا يتم استخدام أي أداة تنظيف تلقائيًا.

حالات الاستخدام

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

تشمل حالات الاستخدام ما يلي:

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

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

القيود والجوانب الدقيقة

تتضمّن واجهات برمجة التطبيقات الجديدة أيضًا بعض القيود والتفاصيل الدقيقة التي يجب الانتباه إليها:

  • يتطلّب دمج البث مع Trusted Types API استخدام طريقة createParserOptions جديدة تتيح إدخال أداة تنظيف إلى أي عملية إعداد HTML. مزيد من التفاصيل حول دمج Trusted Types
  • على غرار <template for>، يمكن أن يؤدي نقل العناصر التي يتم بثها إلى حدوث عواقب غير متوقعة أو أخطاء في البث.
  • تعمل streamHTMLUnsafe بشكل مشابه للمحلّل الرئيسي من نواحٍ عديدة، بما في ذلك معالجة تعليمات <template for> عند إضافتها إلى المستند الرئيسي وتأجيل نصوص defer البرمجية إلى نهاية البث.

Polyfill

لقد أصدر فريق Chrome html-setters-polyfill متاحًا على npm للسماح للمواقع الإلكترونية باستخدام هذه الوظيفة الجديدة على الفور حتى قبل أن تصبح متاحة في المتصفّحات الأخرى.

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

بالإضافة إلى ذلك، يعتمد ضبط المحتوى الآمن على setHTML وSanitizer API غير المتوافقَين مع Safari.

استخدام كليهما معًا

على الرغم من أنّ هاتين واجهتَي برمجة تطبيقات منفصلتَين، فإنّ القوة الحقيقية تكمن في دمجهما. من خلال بث عناصر <template for> جديدة إلى HTML، يمكنك تعديل أجزاء مختلفة من المحتوى بشكل ديناميكي بدون الحاجة إلى استهداف كل جزء بشكل مباشر باستخدام مراجع JavaScript منفصلة إلى DOM.

يمكن تنفيذ عملية تحميل أساسية لصفحة بأسلوب SPA من خلال تحميل صفحة مخطط تتضمّن تعليمات معالجة، ثم بث نماذج كل صفحة جديدة إلى أسفل HTML لتضمينها في تعليمات المعالجة هذه.

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