تحسين رمز HTML


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

كيف تعمل§

محلل§

يعتمد المصغر في جوهره على محلل HTML بواسطة John Resig . كان المحلل اللغوي لجون قادرًا على التعامل مع المستندات المعقدة تمامًا ، ولكنه في بعض الأحيان يقطع بعض الهياكل الأكثر غموضاً. على سبيل المثال ، لم يتم فهم إعلانات النمط على الإطلاق. عندما يحتوي اسم السمة على أحرف مثل "-" (على سبيل المثال كما في "http-equiv") ، يفشل المحلل اللغوي. كانت هناك أيضًا بعض أوجه القصور في التعبيرات العادية لمطابقة التعليقات وأقسام CDATA: لم يتم احتساب الخطوط الجديدة داخلها ، لذلك لم تتم مطابقة التعليقات متعددة الأسطر ببساطة. تم تجريد أقسام CDATA والتعليقات داخل العناصر مع نموذج محتوى CDATA (مثل SCRIPT و STYLE) دون سبب واضح.
تم إصلاح كل هذه الآن .

مصغر§

Minifier عبارة عن "غلاف" صغير جدًا أعلى المحلل اللغوي. حتى الآن ، يبلغ حوالي 250 خطًا فقط. يأخذ سلسلة الإدخال وكائن التكوين ؛ تمرير سلسلة الإدخال هذه إلى المحلل اللغوي ، وبناء المخرجات النهائية وفقًا للخيارات المحددة.
على سبيل المثال ، يمكننا إخبارها بإزالة التعليقات :
var input = '<!-- foo --><div>baz</div><!-- bar\n\n moo -->'; minify(input, { removeComments: true }); // '<div>baz</div>' أو لطي الصفات المنطقية :
var input = '<input disabled="disabled">'; minify(input, { collapseBooleanAttributes: true }); // '<input disabled>'

حزمة اختبار§

كان أحد أهدافي لهذا المشروع الصغير هو امتلاك مجموعة اختبار قوية. يتم اختبار وحدة تصغير HTML بالكامل مع 100 اختبار في الوقت الحالي . هذا له فوائد قليلة: يمكن لأي شخص تغيير الأشياء أو تعديلها أو إضافتها دون القلق من كسر الوظائف الحالية. يستغرق الأمر حرفًا ثوانٍ لمعرفة ما إذا كان النص البرمجي يعمل في مستعرض معين (أو حتى في تطبيق غير مستعرض ، مثل node.js على خادم) - ببساطة عن طريق تشغيل مجموعة اختبار. أخيرًا ، يمكن أن تكون الاختبارات بمثابة وثائق لكيفية معالجة المصغر لبعض حالات الحافة.

الوبر§

أثناء العمل على minifier ، أدركت أن الجزء الأكثر إهدارًا في كثير من الأحيان من الترميز ليس المساحة البيضاء أو التعليقات أو السمات المنطقية ، ولكن الأنماط المضمنة أو النصوص البرمجية أو العناصر أو العروض التقديمية أو الموقوفة. لا يمكن تجريد أي منها بسهولة ، حيث يمكن أن يؤثر ذلك على حالة المستند وهو أمر مزعج للغاية. ولكن ما يمكن فعله هو الإبلاغ عن هذه الأحداث للمستخدم. HTMLLint هو نص أصغر ، وظيفته هي بالضبط - لتسجيل أي عناصر / سمات عرضية موقوفة أو عرضية تمت مواجهتها أثناء التحليل. بالإضافة إلى ذلك ، يكتشف سمات الحدث (مثل onclick و onmouseover وما إلى ذلك). الأساس المنطقي لذلك هو أن نقل محتويات سمات الحدث إلى البرنامج النصي الخارجي يسمح بالاستفادة من التخزين المؤقت للموارد .

خيارات§

قبل أن نبدأ ، من المهم أن نفهم أن أداة التصغير تقوم بتحليل المستندات بتنسيق HTML ، وليس XHTML . يسمح هذا باستخدام عمليات التحسين مثل "إزالة العلامات الاختيارية وعلامات الاقتباس" و "طي السمات المنطقية" وما إلى ذلك. لاحظ أنه لا يوجد أي خيار تقريبًا يؤثر على صحة المستند ، وفقًا لـ HTML 4.01. قد تتم إضافة دعم XHTML في المستقبل ، ولكن بالنظر إلى أنه في سياق موقع pubilc على الويب ، فإنه في الغالب لا معنى له في الوقت الحالي ، أرى سببًا بسيطًا للقيام بذلك. إلى جانب ذلك ، لا يؤدي تصغير مستندات XHTML (نظرًا لأنها تُعرض للعملاء في الواقع بشكل صحيح ، باستخدام "application / xhtml + xml") إلى تقليل الحجم بقدر ما لو كانت HTML.
فيما يلي قائمة بالخيارات الحالية في المصغر. إنه بعيد عن أن يكون شاملاً ، ومن المرجح أن يمتد في المستقبل. دعونا ننظر إلى كل واحد منهم بسرعة:

إزالة التعليقات§

var input = '<!-- some comment --><p>blah</p>'; var output = minify(input, { removeComments: true }); output; // '<p>blah</p>' يجب أن يكون هذا الشخص ذا توضيح. تمرير الحقيقة removeCommentsيخبر المصغر بتجريد تعليقات HTML. لاحظ أن التعليقات داخل العناصر التي تحتوي على نموذج محتوى CDATA ، مثل SCRIPT و STYLE ، يتم تركها كما هي (ولكن انظر الخيار التالي).
var input = '<script type="text/javascript"><!-- some comment --></script>'; var output = minify(input, { removeComments: true }); output; // '<script type="text/javascript"><!-- some comment --></script>'

إزالة التعليقات من البرامج النصية والأنماط§

عند تمكين هذا الخيار ، يتم تجريد تعليقات HTML في البرامج النصية والأنماط أيضًا:
var input = '<script type="text/javascript"><!--\n alert(1) --></script>'; var output = minify(input, { removeCommentsFromCDATA: true }); output; // '<script type="text/javascript">alert(1)</script>' تجدر الإشارة إلى أن هناك اختلافًا طفيفًا في طريقة التعامل مع تعليقات HTML داخل عناصر SCRIPT و STYLE. في البرامج النصية ، محدد بداية التعليق ("<! - <span> </span> -") يطلب من المحلل اللغوي تجاهل كل شيء حتى السطر الجديد:
<!-- alert(1); // alert never happens! <!-- alert(2); // but this one does! // "<!--" acts as a single-line JS comment ("//"). في الأنماط ، ومع ذلك ، "<! -- "يتم تجاهلها ببساطة عندما تكون موجودة في بداية الإدخال (لم أختبر ما يحدث في أجزاء أخرى من ورقة الأنماط). على عكس سلوك البرنامج النصي ، أي شيء يتبع" <! -- " لا تزال موجودة :
<!-- body { color: red; } --> /* treated as: body { color: red; } */ شرح لماذا قد ترغب في إزالة التعليقات.

إزالة أقسام CDATA§

يزيل هذا الخيار أقسام CDATA من عناصر البرنامج النصي والنمط:
var input = '<script>/* <![CDATA[ \n\n */alert(1)/* ]]> */</script>'; var output = minify(input, { removeCDATASectionsFromCDATA: true }); output; // '<script>alert(1)</script>' شرح لماذا قد ترغب في القيام بذلك.

تصغير المسافة البيضاء§

يؤدي هذا الخيار إلى تصغير المساحة البيضاء التي تساهم في عقد النص في شجرة المستندات. فمثلا:
var input = '<div> <p> foo </p> </div>'; var output = minify(input, { collapseWhitespace: true }); output; // '<div><p>foo</p></div>' لا يؤثر على مساحة بيضاء كبيرة. على سبيل المثال في محتويات عناصر مثل SCRIPT أو STYLE أو PRE أو TEXTAREA.
var input = '<script> alert("foo bar")</script>'; var output = minify(input, { collapseWhitespace: true }); output; // '<script>alert("foo bar")</script>' input = '<textarea> x x x </textarea>'; output = minify(input, { collapseWhitespace: true }); output; // '<textarea> x x x </textarea>' الآن ، تجدر الإشارة إلى أن هذا التعديل يمكن أن يكون له آثار جانبية ، ويغير تمثيل المستند بشكل كبير.
على سبيل المثال ، <span>foo</span> <span>bar</span>عادة ما يتم عرض علامة مثل "foo bar" في المتصفحات ، مع حرف مسافة بين كلمتين. يتم تمثيل المسافة البيضاء في الترميز كعقدة نصية في شجرة المستندات. قيمة عقدة النص هذه عبارة عن مسافة بيضاء (على سبيل المثال U+0020) ، وطالما أن عنصرين متجاورين على مستوى مضمن - كما هو الحال في هذا المثال - فإن هذه المساحة البيضاء هي التي تساهم في وجود فجوة بين "foo" و "bar" . بمجرد إزالة تلك المساحة البيضاء (أي تغيير الترميز إلى <span>foo</span><span>bar</span>) ، يتغير التمثيل من "شريط foo" إلى "foobar".
هناك طريقتان للتعامل مع هذه المشكلة.
الأول هو عدم الاعتماد على مثل هذه المساحة البيضاء لتمثيل المستند ، وبدلاً من ذلك يكون لعناصر النمط هوامش وحشوات حسب الحاجة. في المثال السابق ، يمكن أن يكون هذا: <span class="foo">foo</span><span>bar</span>(حيث سيتم الإعلان عن فئة foo باستخدام ، على سبيل المثال margin-right: 0.25em;). في البداية ، قد يبدو هذا مثل المبالغة. بعد كل شيء ، يبدو أن إضافة فئة تهزم الغرض ، مما يؤدي إلى إنتاج أكبر ، مقارنةً بإصدار يحتوي على مسافة بيضاء واحدة فقط. ومع ذلك ، اعتمادًا على السياق ، يمكن أن ينتج عن إعطاء عناصر قليلة فئة لأغراض التصميم ، ثم تجريد المساحة البيضاء من المستند بالكامل ، إخراجًا أصغر.
الخيار الثاني هو عدم إزالة أحرف المسافة البيضاء مطلقًا ، وبدلاً من ذلك يمكنك دائمًا تصغيرها إلى حرف مسافة واحدة . تم تحديد HTML 4.01 بالفعل للقيام بذلك ، لذلك ليس هناك ضرر في القيام بذلك مقدمًا. ولهذا السبب ، يجب عرض القصاصين التاليين بشكل متطابق:
<span>foo</span> <span>bar</span> و:
<span>foo</span> <span>bar</span> ... مع مسافة واحدة بين "foo" و "bar". لاحظ كيف أنه في الحالة الأولى ، هناك سلسلة كاملة من أحرف المسافات البيضاء (بما في ذلك فواصل الأسطر).
لم تتم إضافة هذا الخيار الثاني - الانهيار إلى مسافة بيضاء واحدة - إلى المصغر.
هناك تأثير آخر يمكن ملاحظته لإزالة الفضاء الأبيض على مستند يتعلق بخاصية CSS للفضاء الأبيض . كما ذكرت سابقًا ، بشكل افتراضي ، تنقسم التتابعات المجاورة للمسافة البيضاء في معظم العناصر إلى حرف مسافة واحدة. لكن white-spaceالملكية تغير كل شيء. تؤدي بعض قيمه إلى انهيار سلوك مختلف. white-space: pre، على سبيل المثال ، يجعل المسافة البيضاء تظهر تمامًا كما تحدث في الترميز.
ونتيجة لذلك ، مقتطف مثل هذا:
<span style="white-space:pre;"> foo bar</span> تقدم تمامًا كما هي ، وتصبح:
foo bar اعتبارًا من الآن ، لا يحترم أداة التصغير قيم الحفاظ على المساحة البيضاء (مثل "pre" و "pre-wrap"). حتى أنه لا يفهمهم. لسوء الحظ ، فإن أنماط عناصر الحوسبة وتحديد قيم الفضاء الأبيض ستكون معقدة للغاية وغير عملية [1] . على الجانب المشرق ، يبدو أن خاصية المساحة البيضاء لا تُستخدم كثيرًا. في المستقبل ، يجب أن يكون من الممكن إضافة خيار لمصغر لتحديد طريقة لمنع عناصر معينة من طي محتواها. يمكن أن تستند التصفية إلى فئة ، أو محدد بسيط ، أو ربما حتى من خلال تحليل سمة نمط العنصر.

تصغير السمات المنطقية§

يحتوي HTML 4.01 على ما يسمى بالسمات المنطقية - "مختارة" ، "معطلة" ، "محددة" ، إلخ. قد تظهر هذه في نموذج مصغر (مطوي) ، حيث يتم تحديد قيمة السمة بشكل كامل. على سبيل المثال ، بدلاً من الكتابة <input disabled="disabled">، يمكننا ببساطة الكتابة <input disabled>.
يحتوي Minifier على خيار لأداء هذا التحسين ، يسمى collapseBooleanAttributes:
var input = '<input value="foo" readonly="readonly">'; var output = minify(input, { collapseBooleanAttributes: true }); output; // '<input value="foo" readonly>' هناك تحذير محتمل هنا هو أنه إذا استهدفت العناصر حسب اسم السمة وقيمتها ، فقد تنكسر الأشياء بعد تطبيق هذا التحسين. من المؤكد أن هذا النوع من الحالات يبدو غير واقعي إلى حد ما ، ولكن إليك مثال على ذلك. إذا كان لدينا هذه القواعد:
input[disabled] { color: red } input[disabled="disabled"] { color: green } input:disabled { color: blue } والترميز مثل <input disabled="disabled">، ثم بعد تحويلها إلى <input disabled>القاعدة الثانية input[disabled="disabled"]- سيتوقف عن مطابقة عنصر. ومع ذلك ، سيظل الأول والثالث يعملان كما هو متوقع. لا أستطيع أن أتخيل لماذا يستخدم شخص ما هذا الإصدار الثاني ، وربما لن تتعثر على الإطلاق في مشكلات مثل هذه ، ولكن من الجيد أن تكون على دراية بها.

إزالة علامات الاقتباس من السمة§

بشكل افتراضي ، يتطلب SGML (الذي نشأ منه HTML) تحديد جميع قيم السمات إما باستخدام علامات اقتباس مزدوجة أو مفردة. ولكن في حالات معينة - عندما تحتوي قيم السمات على مجموعة معينة من الأحرف - يمكن حذف علامات الاقتباس تمامًا . لاحظ أن مواصفات HTML توصي باستخدام علامات الاقتباس دائمًا . هناك أيضًا تفسير مثير للاهتمام لماذا يعتبر الاقتباس دائمًا فكرة جيدة من قبل Jukka Korpela (على الرغم من عدم وجود أي من المخاطر التي يتحدث عنها هنا). من فضلك ، استخدم هذا التحسين بعناية.
الخيار ذو الصلة هو removeAttributeQuotes، ويخبر المصغر بحذف عروض الأسعار عندما يكون ذلك آمنًا:
var input = '<p class="foo-bar" id="moo" title="blah blah">foo</p>'; var output = minify(input, { removeAttributeQuotes: true }); output; // '<p class=foo-bar id=moo title="blah blah">foo</p>'

إزالة السمات الزائدة§

تحتوي بعض السمات في HTML 4.01 على قيم افتراضية. على سبيل المثال ، يتم تعيين سمة نوع الإدخال افتراضيًا على "text" وطريقة النموذج — على "get". عند تمكين الخيار المقابل في minifier ( removeRedundantAttributes) ، يتم تجريد أزواج قيمة اسم السمة الافتراضية هذه من الإخراج.
هناك أيضًا عدد قليل من التكرارات الأخرى التي يتم الاعتناء بها كجزء من هذا التحسين.
أحدها هو إزالة سمة اللغة المهملة على عناصر SCRIPT. كان من بين الروائح الترميزية التي ذكرتها مؤخرًا . آخر هو التعايش بين سمات "الاسم" و "معرف" على المؤلفين . وأخيرًا ، تسميات "جافا سكريبت" الزائدة في معالجات الأحداث .

استخدم نوع قصير§

هذا التحسين هو الوحيد الذي يؤثر على صحة الوثيقة . هذا إذا تم تعريف المستند على أنه HTML5 (مثل HTML 4.01). عند useShortDoctypeتمكين الخيار ، يتم استبدال نوع المستند الحالي بإصداره القصير (HTML5) - <!DOCTYPE html>. كما ذكرنا من قبل ، فإن هذا الاستبدال آمن بشكل عام ، ولكن يجب أن تقرر بنفسك ما إذا كان هذا أمرًا يستحق القيام به.

أزل السمات الفارغة (أو الفارغة)§

الخيار المقابل هو removeEmptyAttributes، وعندما يتم تمكينه ، تتم إزالة جميع السمات ذات القيم الفارغة ببساطة من الإخراج. يتضمن هذا القيم الفارغة أيضًا - تلك التي تتكون من مسافة بيضاء فقط.
var input = '<p id="" STYLE=" " title="\n" >foo</p>'; var ouptut = minify(input, { removeEmptyAttributes: true }); output; // <p>foo</p> لاحظ أنه لا تتم إزالة جميع السمات "الفارغة". على سبيل المثال ، كلتا السمتين "src" و "alt" مطلوبة في عناصر IMG ، لذلك لا يمكننا إزالتها ، حتى إذا كانت فارغة. في الوقت الحالي ، تعتبر السمات الأساسية فقط (id ، الفئة ، النمط ، العنوان) ، i18n (lang ، dir) والحدث (onclick ، ​​ondblclick ، ​​إلخ.) "آمنة" للإزالة.
التحذير هنا هو أنه ، على غرار خيار "طي السمات المنطقية" ، يمكن أن يؤثر هذا التغيير على نمط معين أو سلوك البرنامج النصي . على سبيل المثال ، قد ترغب في استهداف جميع العناصر بسمة class- *[class] { ... }. سينطبق هذا على العناصر ذات الصفوف الفارغة ، مثل <p class="">bar</p>، ولكن من الواضح أنها لا تنطبق على العناصر التي لا تحتوي على - <p>bar</p>.
قد لا تكون هذه مشكلة كبيرة ، ولكن ضعها في الاعتبار.

إزالة العلامات الاختيارية§

يُسمح بإلغاء علاماتها في بعض عناصر HTML 4.01. العلامات الاختيارية هي إما نهاية واحدة (على سبيل المثال </td>) أو كلاهما - علامات البداية والنهاية (مثل <tbody>و </tbody>). لاحظ أن وسم البداية لا يمكن أن يكون اختياريًا على الإطلاق.
الخيار المقابل في minifier هو removeOptionalTags. في الوقت الحالي ، تقوم فقط بإزالة علامات النهاية لعناصر HTML و HEAD و BODY و THEAD و TBODY و TFOOT. لا أفهم تمامًا عملية إنشاء شجرة المستندات من الترميز "غير المغلق" ، لذلك لست متأكدًا من الوقت الآمن لحذف علامات مثل </p>.
على سبيل المثال ، يمكنني أن أرى كيف يمكن أن تؤدي إزالة BODY start tag إلى آثار جانبية . لنفترض أن لدينا ترميزًا مثل هذا (مع نوع HTML 4.01 المحذوف ، للإيجاز):
<head> <title>x</title> </head> <body><script type="text/javascript"></script> <p>x</p> <script type="text/javascript"> document.write(document.body.childNodes[0].nodeName); </script> </body> ونفس الترميز مع إزالة علامات HEAD و BODY:
<title>x</title> <script type="text/javascript"></script> <p>x</p> <script type="text/javascript"> document.write(document.body.childNodes[0].nodeName); </script> لاحظ أن الإصدار الثاني هو مستند صالح تمامًا. لقد تم حذف علامات البداية والنهاية لعناصر HEAD و BODY. الآن ما يبدو أنه يحدث هنا ، في النسخة الثانية ، هو:
يبدأ المتصفح في التحليل ، ويواجه علامة TITLE ، ونظرًا لعدم بدء علامات HTML و HEAD ، ينشئ كلا العنصرين ضمنيًا (أولاً ، HTML ، ثم HEAD كطفل مباشر). ثم تستمر في التحليل حتى تصل إلى عنصر P ، والذي ، وفقًا لـ DTD ، لا يمكن أن يكون طفلًا لرأس. وبالتالي ، يضطر المتصفح إلى إغلاق عنصر الرأس ضمنيًا ، وبدء عنصر BODY ، ومواصلة التحليل. يصبح عنصر P الطفل الأول في BODY ، ويصبح عنصر SCRIPT الطفل الأخير في الرأس.
الآن ، إذا أردنا عرض هذين المستندين ، فإن الأول سيحذر "SCRIPT" والثاني - "P". يتم ذلك في الإصدار الأصلي ، يتم تعريف عنصر SCRIPT بشكل صريح ليكون تابعًا للجسم ، وفي النسخة المعدلة - تابع لـ HEAD (بسبب طريقة عمل التحليل). وبالتالي فإن سلوك وثيقتين ليس متطابقًا. لدينا مشكلة".
تمامًا مثل "gotchas" السابقة ، لست متأكدًا من مدى احتمالية ظهور هذا النوع من السيناريو في الحياة الواقعية. من ما يمكنني رؤيته ، فإن العنصر الآخر الوحيد (إلى جانب SCRIPT) ، المسموح به كطفل لكلا من - الرأس والجسم ، هو الكائن. أما بالنسبة للمستقبل ، فيجب أن يكون من الممكن جعل شريط المصغر علامات اختيارية أخرى أيضًا. ولكن فقط في سيناريوهات آمنة.
من الجدير بالذكر أيضًا أن العناصر غير المغلقة يمكن أن تؤدي إلى أوقات تحليل أبطأ قليلاً . للأسف ، لا توجد معايير مرجعية واسعة النطاق تم إجراؤها حول هذا الموضوع ، ويبدو أن النتائج تختلف باختلاف المتصفحات.

إزالة العناصر الفارغة§

ربما يكون هذا التحسين واحدًا من أكثرها تدخلاً ، ولهذا السبب يتم تعطيله افتراضيًا. فكر في الأمر على أنه إضافة تجريبية ، واستخدمه بعناية كبيرة. هناك العشرات من حالات الاستخدام الصالحة لحدوث عناصر فارغة في مستند. يمكن استخدامها كعناصر نائبة للمحتوى الذي تم إدراجه لاحقًا مع البرمجة النصية ؛ أو لأغراض العرض ، مثل تنفيذ الزوايا الدائرية ، والظلال ، وتطهير العوامة ، وما إلى ذلك. هناك على الأرجح حالات أخرى ، لا يمكنني التفكير فيها في الوقت الحالي.
عند تمكينه ، يقوم المصغر ببساطة بإزالة جميع العناصر ذات المحتويات الفارغة (ولكن ليس العناصر ذات نموذج المحتوى الفارغ ، مثل IMG أو LINK أو BR).
فمثلا:
var input = '<p></p>'; var output = minify(input, { removeEmptyElements: true }); output; // '' input = '<div>blah<span></span></div>'; var output = minify(input, { removeEmptyElements: true }); output; // '<div>blah</div>'; هناك أشياء قليلة يجب أن تكون على علم بها. بادئ ذي بدء ، لا تتم إزالة العناصر التي تحتوي على عناصر فارغة أخرى فقط . فمثلا:
var input = '<div><div><div></div></div></div>'; var output = minify(input, { removeEmptyElements: true }); output; // '<div><div></div></div>' لاحظ كيف تتم إزالة عنصر DIV الداخلي فقط - العنصر الذي يحتوي على محتويات فارغة فعلية.
ثانيًا ، تعتبر السلسلة الفارغة فقط محتوى فارغًا. هذا لا لا تتضمن مسافات، أسطر، أو غيرها من الأشخاص الفضاء البيضاء:
var input = '<p> </p>'; // note one space character in between var output = minify(input, { removeEmptyElements: true }); output; // '<p> </p>' لاحظ أيضًا أنه يتم تحليل التعليقات ككيانات منفصلة ، وبالتالي لا تؤثر على "فراغ" العناصر:
var input = '<p><!-- comment --></p>'; var output = minify(input, { removeEmptyElements: true }); output; // '' كما هو الحال مع التحسينات الأخرى ، من المحتمل إزالة بعض هذه القيود في المستقبل.

التحقق من صحة الإدخال من خلال HTML lint§

يقوم هذا الخيار ببساطة بتبديل اللف. يمكنك إنشاء كائن HTMLLint جديد وتمريره إلى المصغر. أثناء التصغير ، يسجل كائن الوبر بصمت كل الأنشطة "المشبوهة". يكشف populateالأسلوب الذي يقبل العنصر ويدرج سجله في هذا العنصر:
var lint = new HTMLLint(); minify(' some input... ', { lint: lint }); lint.populate(document.getElementById('someElement'));

الاختبار الميداني§

فكيف يقف المصغر ضد ترميز الحياة الحقيقية؟ دعونا نلقي نظرة على نتائج التصغير لبعض مواقع الويب الشائعة (لاحظ أنه عند استخدام gzip'ing للوثائق ، تم استخدام المستوى السادس من الضغط (افتراضي) ):

أمازون . كوم§

الحجم الأصلي: 217 كيلو بايت (35.8 كيلو بايت مضغوط)
الحجم المصغر: 206.6 كيلو بايت (34.3 كيلو بايت مضغوط)
التوفير: 10.4 كيلو بايت (1.5 كيلو بايت مضغوط)
يؤدي تصغير الصفحة الرئيسية لموقع amazon.com إلى توفير حوالي 10 كيلوبايت بمستند غير مضغوط ، وفقط 1.5 كيلوبايت مع ملف مضغوط. المثير للاهتمام هو أن 217KB الهائل هو في الواقع نتيجة لنسخ من الأنماط والنصوص المضمنة المنتشرة في جميع أنحاء المستند. سيكون استبدال تلك البرامج النصية الخارجية هو أفضل التحسين. سيساعدك أيضًا التخلص من سمات الأنماط العرضية.

يسو . كوم§

الحجم الأصلي: 82 كيلو بايت
(18.2 كيلو بايت مضغوط) الحجم المصغر: 74.9 كيلو بايت (17.2 كيلو بايت مضغوط)
التوفير: 7 كيلو بايت (1 كيلو بايت مضغوط)
على موقع digg.com ، يكون التخفيض أصغر قليلاً - 7 كيلو بايت (1 كيلو بايت مضغوط). الترميز ليس فوضويًا كما هو الحال في الأمازون ، ولكنه لا يزال يحتوي على روائح: النصوص المضمنة (والتعليقات غير الضرورية فيها) ، والسمات التي تم تجاهلها ، والمرساة التي تم فصلها بدون كتابة نصية ، وما إلى ذلك.

أجاكسان . كوم§

الحجم الأصلي: 177.6 كيلوبايت (32.4 كيلوبايت مضغوط)
الحجم المصغر: 157.3 كيلوبايت (29.7 كيلوبايت مضغوط)
التوفير: 20.3 كيلوبايت (2.7 كيلوبايت مضغوط)
عند تجربة الصفحة الرئيسية لموقع ajaxian.com ، نرى اختلافًا يبلغ 20 كيلوبايت تقريبًا - حتى تقليل الحجم بشكل أفضل. ومرة أخرى ، تظهر المستندات المضغوطة وفورات فقط 2.7 كيلو بايت. بالحديث عن الضغط ، أجاكسان . يخدم كوم بلا خجل مستندها 177 كيلو بايت غير مضغوط. هناك أيضًا بعض الترميز الزائد ، مثل سمات غير ضرورية ، ونبذات النمط المفرط ، والكثير من التعليقات ، وعدد قليل من النصوص البرمجية المضمنة. إن إزالة كل هذه ، وتشغيل الضغط سيكون التحسين الأمثل.

Linkedin.com§

الحجم الأصلي: 128.8 كيلو بايت (19.8 كيلو بايت مضغوط)
الحجم المصغر: 89.4 كيلو بايت (17.1 كيلو بايت مضغوط)
التوفير: 39.4 كيلو بايت (2.7 كيلو بايت مضغوط)
مفاجآت linkin.com مع توفير حوالي 40 كيلوبايت (!) بعد التقليل. بالنظر إلى المصدر ، نرى أن العدد الكبير يفسر بالكمية الزائدة من المسافات البيضاء. هذا مثال جيد على كيف يمكن للمسافة البيضاء المستخدمة بلا مبالاة أن تضيف إلى عدد ضخم مثل هذا. ومرة أخرى ، gzip ينقذ اليوم. يؤدي تصغير المستند المضغوط إلى تقليله بمقدار 2.7 كيلوبايت فقط.

مواصفات لغة ECMAScript§

الحجم الأصلي: 703 كيلو بايت (122.5 كيلو بايت مضغوط)
الحجم المصغر: 572 كيلو بايت (106.4 كيلو بايت مضغوط)
التوفير: 131 كيلو بايت ( 16 كيلو بايت مضغوط)
المستندات الثابتة الكبيرة هي المكان الذي يضيء فيه تصغير HTML حقًا ، وإصدار HTML من مواصفات لغة ECMAScript (الطبعة الثالثة) هي عرض واضح لها. يؤدي تصغير المستند إلى توفير 131 كيلو بايت (!) لمستند غير مضغوط ، و 16 كيلو بايت للمستند المضغوط. نظرًا لأنه يتم عرض المستند بشكل ثابت ، فليس هناك أي سبب لعدم تطبيق التصغير هنا.

التكلفة والفوائد§

من الواضح جدًا أن أفضل المرشحين لتصغير HTML هو مستندات ثابتة كبيرة . أو مجرد مستندات ثابتة - الأسئلة الشائعة والمقالات المستقلة ، وما إلى ذلك. أي شيء لا يمكن ضغطه (على سبيل المثال إذا لم يكن هناك حقوق وصول كافية ، لتمكين gzip على الخادم) سوف يستفيد من التصغير أيضًا. حتى عند تقديم محتوى مضغوط ، من الجدير بالذكر أنه ليس كل شخص يحصل على مضغوط . لذا يمكن للعملاء الذين يتم إرسال محتوى مضغوط أن يتلقوا ملفًا بحجم 2-3 كيلوبايت ، في حين أن أولئك الذين يتلقون محتوى غير مضغوط يمكن أن ينتهي بهم الأمر بملفات تصل إلى 10-20 كيلوبايت أصغر من الملفات الأصلية.
إحدى أكبر المشاكل التي أراها ، عندما يتعلق الأمر بالتصغير الديناميكي ، هي إمكانية الخطأ . إن جوهر المشكلة هو أن التصغير يعتمد على التحليل ، وأن تحليل HTML هو عمل صعب للغاية . على الرغم من أن المصغر يطبق مجموعة صارمة من القواعد — إزالة علامات الاقتباس والعلامات الاختيارية فقط عندما يكون ذلك آمنًا تمامًا للقيام بذلك ، فإن حرفًا واحدًا في غير موضعه في علامة البداية يمكن أن يعيق المحلل ويسبب الخراب في المستند بأكمله. يكون هذا ملائمًا بشكل خاص عند تضمين محتوى من إنشاء المستخدمين.
كمثال ، عادة ما تفهم المتصفحات علامات النهاية الفارغة (المسموح بها في HTML) - <p> test </>ولكن المحلل اللغوي ، الذي يعتمد عليه المصغر ، سيختنق على الفور هنا ويتوقف. مثال آخر هو السمات التي تحتوي على أحرف "غريبة" - (اقتباس لاحقة بعد سمة). يسر العديد من المتصفحات تحليل هذا العنصر ، متجاهلين الاقتباس اللاحق. ولكن المحلل اللغوي ، مرة أخرى ، يقصر وينقذ.<a href="http://example.com""> test </a>
من الممكن بالتأكيد ترويض الأخطاء وإخراج مستند أصلي غير مضغوط. لكن هذا ينقلنا إلى جانب سلبي آخر - الوقت المنقضي في التصغير . حتى عندما لا تكون الأخطاء مشكلة ، هناك زيادة فعلية في تحليل شجرة المستندات ومعالجتها. تصغير الصفحة الرئيسية من الأمازون . كوم في webkit ليلا سريع جدا ، على سبيل المثال ، يستغرق بالضبط 1 ثانية. يتم استهلاك معظم هذا الوقت عن طريق التحليل. ثانية واحدة هي الكثير. سيكون الوقت المقبول للتصغير في الوقت الفعلي حوالي 50-100 مللي ثانية. يمكن تخفيف هذه المشكلة عن طريق تحسين المحلل اللغوي ، أو تنفيذ البرنامج النصي في بيئة أسرع (الإصدار 8 على الخادم؟).
الغريب ، تمكنت Opera 10.50 beta (على نظام التشغيل Mac OS X) من التغلب على WebKit وأكملت هذه المهمة أسرع مرتين تقريبًا (~ 500 مللي ثانية). لسوء الحظ ، يعاني هذا الإصدار من بعض الأخطاء في مطابقة التعبير العادي ، ويفشل نصف مجموعة الاختبار. نأمل أن يتم حل هذه القضايا في المراجعات اللاحقة.
ملاحظة أخرى مثيرة للأداء كانت مع محرك V8 . عند الاختبار باستخدام الإصدار 1.3.x ، الوقت المستغرق لتقليل الأمازون . كانت الصفحة الرئيسية com 0.6 ثانية. ومع ذلك ، فإن الإصدار 2.1.2.6 (أحدث طعن حالي) قام بنفس المهمة في ثانيتين طويلتين بشكل مؤلم.

مستقبل§

أستطيع أن أفكر في أشياء أخرى كثيرة لتحسين في minifier. لسوء الحظ ، ليس لدي الكثير من الوقت للعمل عليه. المشروع مرخص بموجب MIT ، وهو مجاني للاستخدام / التعديل من قبل أي شخص مهتم. يجب أن تجعل مجموعة الاختبار التعاون سهلاً. توجد قائمة مهام قصيرة في أسفل صفحة المشروع. من بين أمور أخرى ، يسرد بعض الأخطاء المعروفة.
كما هو الحال دائمًا ، يتم الترحيب بشدة بأي أسئلة أو تصحيحات أو اقتراحات.
استمتع.
1. يمكن أن يكون الإعلان "مسافة بيضاء: قبل" جزءًا من قاعدة من داخل ورقة أنماط خارجية. يتطلب الحصول على نمط محسوب تنزيل وتحليل كل ورقة أنماط مرتبطة بالوثيقة (أو استيرادها من داخل ورقة أنماط أخرى).