ऐंगुलर इमेज डायरेक्टिव के साथ इमेज ऑप्टिमाइज़ करना

Kara Erickson
Kara Erickson
Leena Sohoni
Leena Sohoni

मई 2022 में, Aurora और Angular टीमों ने एलान किया था कि वे Angular के लिए इमेज डायरेक्टिव पर साथ मिलकर काम करेंगी. निर्देश को हाल ही में, Angular v14.2 के हिस्से के तौर पर डेवलपर की झलक के लिए रिलीज़ किया गया था. इस पोस्ट में बताया गया है कि नया इमेज डायरेक्टिव NgOptimizedImage, Angular में इमेज ऑप्टिमाइज़ेशन की सुविधा कैसे देता है.

बैकग्राउंड

इमेज, वेब पर उपयोगकर्ता अनुभव का एक सामान्य और अहम हिस्सा हैं. 99.9% वेब पेज, एक या उससे ज़्यादा इमेज के लिए अनुरोध जनरेट करते हैं. पेज के वज़न में इमेज का भी सबसे ज़्यादा योगदान है. इसका मतलब है कि हर पेज के लिए 982 किलोबाइट का मीडियन.

इमेज की संख्या और साइज़ बढ़ने की वजह से, वेब पेजों की परफ़ॉर्मेंस पर असर पड़ सकता है. साथ ही, वेबसाइट की परफ़ॉर्मेंस से जुड़ी जानकारी वाली मेट्रिक पर भी असर पड़ सकता है. साल 2021 में, 79.4% डेस्कटॉप पेजों में इस्तेमाल की गई इमेज, सबसे बड़े एलिमेंट को रेंडर करने में लगने वाले समय (एलसीपी) का हिस्सा थी. इसलिए, हम सभी के लिए ऑप्टिमाइज़ की गई इमेज का इस्तेमाल करना एक लगातार कोशिश बन गई है.

Aurora टीम डेवलपर की सामान्य चुनौतियों का हल देने के लिए फ़्रेमवर्क की क्षमता का इस्तेमाल करने में भरोसा रखती है. इमेज ऑप्टिमाइज़ेशन के क्षेत्र में उनकी पहली कोशिश, Next.js इमेज कॉम्पोनेंट थी. उन्होंने इस कॉम्पोनेंट को टेस्ट किया, जिससे पता चलता है कि इमेज ऑप्टिमाइज़ेशन के डेवलपर अनुभव (DX) को बेहतर बनाने से, फ़्रेमवर्क का इस्तेमाल करने वाले ज़्यादा ऐप्लिकेशन की परफ़ॉर्मेंस बेहतर हो सकती है या नहीं.

Next.js का इस्तेमाल करने वाले Leboncoin के नतीजों का पहला सेट उत्साह बढ़ाने वाला था. Leboncoin ने next/image का इस्तेमाल शुरू करने के बाद, एलसीपी में काफ़ी सुधार देखा. एलसीपी 2.4 सेकंड से घटकर 1.7 सेकंड हो गया. कम्यूनिटी में next/image को अपनाने के बाद, Next.js के उन ऑरिजिन की संख्या में बढ़ोतरी हुई जो एलसीपी थ्रेशोल्ड को पूरा करते हैं. जल्द ही, अन्य फ़्रेमवर्क में मिलती-जुलती सुविधाओं के लिए अनुरोध मिलने लगे. इनमें से एक Angular था.

इसलिए, Aurora ने इन फ़्रेमवर्क के लिए इमेज कॉम्पोनेंट के प्रोटोटाइप बनाने के लिए, Angular और Nuxt से सलाह ली. Nuxt इमेज कॉम्पोनेंट पिछले साल रिलीज़ किया गया था. Angular में इमेज ऑप्टिमाइज़ेशन के डिफ़ॉल्ट विकल्पों को जोड़ने के लिए, Angular इमेज डायरेक्टिव (NgOptimizedImage) रिलीज़ किया गया है.

अवसर

Angular आज के डेवलपर के इस्तेमाल किए जाने वाले सबसे बड़े JavaScript फ़्रेमवर्क में से एक है. इसका इस्तेमाल 50 हज़ार से ज़्यादा ऑरिजिन को मोबाइल पर HTTPArchive के ज़रिए क्रॉल किया जाता है. साथ ही, यह एनपीएम पर हर हफ़्ते करीब 30 लाख डाउनलोड करता है.

पिछले एक साल में Angular वेबसाइटों के लिए एलसीपी.

वेबसाइट की परफ़ॉर्मेंस की अहम जानकारी देने वाली मेट्रिक के स्कोर को देखते हुए, एलसीपी के "अच्छे" थ्रेशोल्ड को पूरा करने वाले Angular ऑरिजिन के प्रतिशत में अब भी सुधार की ज़रूरत है. जून 2022 में, सिर्फ़ 18.74% Angular साइटों को मोबाइल पर अच्छा एलसीपी मिला. मोबाइल और डेस्कटॉप पर 70% से ज़्यादा वेब पेजों के लिए, इमेज एलसीपी एलिमेंट होती हैं. इसलिए, Angular वेबसाइटों पर एलसीपी की परफ़ॉर्मेंस खराब होने की मुख्य वजहों में, ऑप्टिमाइज़ नहीं की गई एलसीपी इमेज भी हो सकती हैं.

इन संख्याओं को बेहतर बनाने के लिए, Angular इमेज डायरेक्टिव को डिज़ाइन किया गया था.

NgOptimizedImage डायरेक्टिव के लिए एमवीपी

Angular इमेज डायरेक्टिव का MVP, उन इमेज कॉम्पोनेंट के लेसन पर आधारित है जो Aurora ने आज तक तैयार किए हैं. साथ ही, यह भी Angular के क्लाइंट-साइड रेंडरिंग अनुभव के हिसाब से डिज़ाइन किया गया है. इमेज ऑप्टिमाइज़ेशन से जुड़ी कई समस्याओं को इनमें से किसी एक तरीके से हल किया गया है:

  • मज़बूत डिफ़ॉल्ट सेटिंग जोड़ी जा रही हैं.
  • सबसे सही तरीकों का पालन हो रहा है या नहीं, यह पक्का करने के लिए गड़बड़ियां या चेतावनियां दिखाना.

डिज़ाइन की हाइलाइट यहां दी गई हैं:

  1. स्मार्ट लेज़ी लोडिंग

    पेज लोड होने पर उपयोगकर्ता को न दिखने वाली इमेज (उदाहरण के लिए, फ़ोल्ड के नीचे मौजूद इमेज या छिपी हुई कैरसेल इमेज) को लेज़ी-लोड किया जाना चाहिए. लेज़ी लोडिंग से ब्राउज़र के रिसॉर्स को, ज़रूरी टेक्स्ट, मीडिया या स्क्रिप्ट लोड करने में मदद मिलती है. ज़्यादातर इमेज ज़रूरी नहीं होतीं और इन्हें लेज़ी लोड किया जाना चाहिए. हालांकि, 2021 में सिर्फ़ 7.8% पेजों ने नेटिव लेज़ी लोडिंग का इस्तेमाल किया.

    Angular इमेज डायरेक्टिव, डिफ़ॉल्ट रूप से ज़रूरी नहीं वाली इमेज को धीरे-धीरे लोड करता है. साथ ही, सिर्फ़ priority के तौर पर खास तौर पर मार्क की गई इमेज को तुरंत लोड करता है. इससे यह पक्का होता है कि ज़्यादातर इमेज, लोड होने में कम समय लेती हैं.

  2. ज़रूरी इमेज को प्राथमिकता देना

    संसाधन के सुझाव जोड़ना (उदाहरण के लिए, preload या preconnect), अहम इमेज लोड होने को प्राथमिकता देने के लिए, सुझाया गया सबसे सही तरीका है. हालांकि, ज़्यादातर ऐप्लिकेशन इनका इस्तेमाल नहीं कर रहे हैं. 2021 के वेब अल्मनैक के मुताबिक, सिर्फ़ 12.7% मोबाइल पेज, पहले से कनेक्ट करने के संकेत का इस्तेमाल करते हैं. साथ ही, सिर्फ़ 22.1% मोबाइल पेज, पहले से लोड करने के संकेत का इस्तेमाल करते हैं.

    जब इमेज को प्राथमिकता के तौर पर मार्क किया जाता है, तो इमेज डायरेक्टिव दो मोर्चों पर काम करता है.

    • यह इमेज की फ़ेचप्राथमिकता "high" पर सेट करता है, ताकि ब्राउज़र यह जान सके कि इमेज को ज़्यादा प्राथमिकता से डाउनलोड किया जाना चाहिए.
    • डेवलपमेंट मोड में, रनटाइम की जांच से यह पुष्टि होती है कि इमेज के ऑरिजिन के हिसाब से preconnect संसाधन का हिंट शामिल किया गया है.

    डेवलपमेंट मोड में, डायरेक्टिव PerformanceObserver API का इस्तेमाल भी करता है. इससे यह पुष्टि की जाती है कि LCP इमेज को उम्मीद के मुताबिक priority के तौर पर मार्क किया गया है. अगर इसे priority के तौर पर मार्क नहीं किया गया है, तो एक गड़बड़ी दिखती है और डेवलपर को एलसीपी इमेज में priority एट्रिब्यूट जोड़ने का निर्देश दिया जाता है.

    ऑटोमेशन और कंफ़ॉर्मैंस के कॉम्बिनेशन से यह पक्का होता है कि एलसीपी इमेज में preconnect संकेत है, fetchpriority एट्रिब्यूट की वैल्यू high है, और यह लेज़ी लोड नहीं होगी.

  3. लोकप्रिय इमेज टूल के लिए ऑप्टिमाइज़ किया गया कॉन्फ़िगरेशन

    हमारा सुझाव है कि Angular ऐप्लिकेशन इमेज सीडीएन का इस्तेमाल करें. ये अक्सर डिफ़ॉल्ट रूप से ऑप्टिमाइज़ेशन सेवाएं उपलब्ध कराते हैं.

    यह डायरेक्टिव, ऐप्लिकेशन में इमेज सीडीएन को कॉन्फ़िगर करने के लिए, डेवलपर को बेहतर अनुभव (DX) देकर, इमेज सीडीएन का इस्तेमाल करने के लिए बढ़ावा देता है. यह लोडर एपीआई के साथ काम करता है. इसकी मदद से, कॉन्फ़िगरेशन में सीडीएन प्रोवाइडर और अपना बेस यूआरएल तय किया जा सकता है. कॉन्फ़िगर करने के बाद, आपको मार्कअप में सिर्फ़ एसेट का नाम तय करना होगा. उदाहरण के लिए,

    // in module providers:
    provideImgixLoader('https://mysite.net/assets/')
    
    // in markup
    <img ngSrc="image.png" >
    <img ngSrc="image2.png" >
    

    यह इन इमेज टैग को शामिल करने के बराबर है. इससे, डेवलपर को हर इमेज के लिए कम मार्कअप शामिल करना पड़ता है.

    <img src="https://mysite.net/assets/image.png">
    <img src="https://mysite.net/assets/image2.png">
    

    इमेज डायरेक्टिव, सबसे लोकप्रिय इमेज सीडीएन के लिए ऑप्टिमाइज़ किए गए कॉन्फ़िगरेशन के साथ, पहले से मौजूद लोडर उपलब्ध कराता है. ये लोडर, इमेज के यूआरएल को अपने-आप फ़ॉर्मैट करेंगे. इससे यह पक्का किया जा सकेगा कि हर सीडीएन के लिए, सुझाए गए इमेज फ़ॉर्मैट और कंप्रेस करने की सेटिंग का इस्तेमाल किया जा रहा है.

  4. पहले से मौजूद गड़बड़ियां और चेतावनियां

    ऊपर दिए गए, पहले से मौजूद ऑप्टिमाइज़ेशन के अलावा, डायरेक्टिव में पहले से मौजूद जांच भी होती हैं. इनसे यह पक्का किया जाता है कि डेवलपर ने इमेज मार्कअप में सुझाए गए सबसे सही तरीकों का पालन किया है या नहीं. इमेज डायरेक्टिव, इन चीज़ों की जांच करता है.

    1. बिना साइज़ वाली इमेज: अगर इमेज मार्कअप में चौड़ाई और ऊंचाई की जानकारी नहीं दी गई है, तो इमेज डायरेक्टिव गड़बड़ी का मैसेज दिखाता है. साइज़ नहीं डाली गई इमेज की वजह से लेआउट शिफ़्ट हो सकते हैं. इससे पेज की कुल लेआउट शिफ़्ट (सीएलएस) मेट्रिक पर असर पड़ता है. हमारा सुझाव है कि इससे बचने के लिए, इमेज में width और height एट्रिब्यूट होने चाहिए.

    2. अस्पेक्ट रेशियो: इमेज डायरेक्टिव, डेवलपर को गड़बड़ी का मैसेज दिखाता है. इससे उन्हें पता चलता है कि एचटीएमएल में तय किया गया width:height का आसपेक्ट रेशियो, रेंडर की गई इमेज के असल आसपेक्ट रेशियो के करीब है या नहीं. इस वजह से, इमेज स्क्रीन पर खराब दिख सकती है. ऐसा तब हो सकता है, जब

      1. आपने गलती से गलत डाइमेंशन (चौड़ाई या ऊंचाई) तय किए हैं या
      2. अगर आपने अपनी सीएसएस में एक डाइमेंशन को प्रतिशत के हिसाब से तय किया है, लेकिन दूसरे डाइमेंशन को नहीं (उदाहरण के लिए, इमेज के दोनों डाइमेंशन में बढ़ोतरी हो, यह पक्का करने के लिए width: 100% को height: auto की ज़रूरत है).
    3. बहुत बड़ी इमेज: अगर इमेज में srcset एट्रिब्यूट की वैल्यू नहीं दी गई है और इंट्रिंसिक इमेज, रेंडर की गई इमेज से काफ़ी बड़ी है, तो डायरेक्टिव एक चेतावनी दिखाएगा. इसमें srcset और sizes एट्रिब्यूट का इस्तेमाल करने का सुझाव दिया जाएगा.

    4. इमेज की सघनता: अगर आप ऐसी इमेज को srcset में शामिल करने की कोशिश करते हैं जिसकी पिक्सल सघनता 3x से ज़्यादा हो, तो निर्देश वाला गड़बड़ी का मैसेज दिखाएगा. आम तौर पर, 2x से ज़्यादा के डिस्क्रिप्टर इस्तेमाल करने का सुझाव नहीं दिया जाता. ऐसा करने पर, हाई रिज़ॉल्यूशन वाले मोबाइल डिवाइसों को बड़ी इमेज डाउनलोड करने के लिए मजबूर किया जाता है. इतना ही नहीं, मानवीय आंख दो गुना से ज़्यादा का अंतर नहीं बता सकती.

चुनौतियां

NgOptimizedImage को डिज़ाइन करते समय, क्लाइंट-साइड फ़्रेमवर्क में काम करने के लिए, इमेज ऑप्टिमाइज़ेशन की रणनीतियों को अडैप्ट करना एक मुख्य चुनौती थी. Next.js पर रेंडरिंग का डिफ़ॉल्ट तरीका, सर्वर साइड रेंडरिंग (एसएसआर) या स्टैटिक साइट जनरेशन (एसएसजी) है. वहीं, Angular पर क्लाइंट साइड रेंडरिंग (सीएसआर) का इस्तेमाल किया जाता है. हालांकि, Angular एक एसएसआर लाइब्रेरी के साथ काम करता है, जो कोणीय/यूनिवर्सल के तौर पर काम करती है. हालांकि, ज़्यादातर Angular ऐप्लिकेशन (~60%) में सीएसआर का इस्तेमाल किया जाता है.

इमेज डायरेक्टिव को पूरी तरह से सीएसआर के लिए बनाया गया है, ताकि इसे Angular ऐप्लिकेशन में इस्तेमाल के सामान्य उदाहरण के साथ अलाइन किया जा सके. इससे कुछ और शर्तें जुड़ गईं और टीम को सीएसआर ऐप्लिकेशन के लिए खास ऑप्टिमाइज़ेशन बनाने के तरीके पर फिर से विचार करना पड़ा.

हमें कुछ समस्याएं आ रही हैं, जिनके बारे में यहां बताया गया है:

  1. सहायता के लिए, संसाधन से जुड़े संकेत

    ज़रूरी ऐसेट को पहले से लोड करने से, ब्राउज़र को उन्हें जल्दी खोजने में मदद मिलती है. हालांकि, Angular ऐप्लिकेशन में संसाधन के संकेत शामिल करना मुश्किल है, क्योंकि:

    मैन्युअल तरीके से जोड़ना: डेवलपर के लिए, preload संसाधन के सुझाव को मैन्युअल तरीके से जोड़ना मुश्किल होता है. Angular, पूरे प्रोजेक्ट या वेबसाइट के सभी रूट के लिए, एक शेयर की गई index.html फ़ाइल का इस्तेमाल करता है. इसलिए, दस्तावेज़ का <head> हर रूट के लिए एक जैसा होता है (कम से कम दिखाए जाने के समय). <head> में कोई preload हिंट जोड़ने का मतलब है कि संसाधन सभी रास्तों के लिए पहले से लोड हो जाएगा. भले ही, वहां इसकी ज़रूरत न हो. इसलिए, preload के सुझावों को मैन्युअल तरीके से जोड़ने का सुझाव नहीं दिया जाता.

    रेंडर के दौरान अपने-आप जुड़ना: सीएसआर ऐप्लिकेशन में रेंडर के दौरान, दस्तावेज़ के हेडर में प्रीलोड के संकेत जोड़ने के लिए फ़्रेमवर्क का इस्तेमाल करने से कोई मदद नहीं मिलती. JavaScript के डाउनलोड और लागू होने के बाद रेंडरिंग होती है. इसलिए, <head> को रेंडर होने में बहुत देर होगी, क्योंकि इसकी कोई वैल्यू नहीं होगी.

    डायरेक्टिव के पहले वर्शन के लिए, preconnect और fetchpriority के सुझावों के कॉम्बिनेशन का इस्तेमाल करके, इमेज को प्राथमिकता दी जाती है. इसके लिए, preload का इस्तेमाल नहीं किया जाता. हालांकि, फ़िलहाल Aurora, Angular CLI टीम के साथ मिलकर काम कर रहा है, ताकि बिल्ड के समय संसाधन के सुझाव अपने-आप इंजेक्ट हो सकें—बने रहें!

  2. सर्वर पर इमेज का साइज़ और फ़ॉर्मैट ऑप्टिमाइज़ करना

    आम तौर पर, ऐंग्युलर ऐप्लिकेशन को क्लाइंट-साइड से रेंडर किया जाता है. इसलिए, अनुरोध के समय फ़ाइल सिस्टम में मौजूद इमेज को कंप्रेस नहीं किया जा सकता. इन्हें सामान्य तरीके से दिखाया जाता है. इसलिए, इमेज को कंप्रेस करने और उन्हें मांग पर WebP या AVIF जैसे मॉडर्न फ़ॉर्मैट में बदलने का सुझाव दिया जाता है.

    यह डायरेक्टिव, इमेज सीडीएन के इस्तेमाल को लागू नहीं करता. हालांकि, हमारा सुझाव है कि इन्हें डायरेक्टिव के साथ इस्तेमाल करें. साथ ही, इसके साथ पहले से मौजूद लोडर यह पक्का करते हैं कि सही कॉन्फ़िगरेशन विकल्पों का इस्तेमाल किया जा रहा हो.

असर

इस डेमो में दिखाया गया है कि Angular इमेज डायरेक्टिव, इमेज की परफ़ॉर्मेंस पर क्या असर डाल सकता है. यह दो वेबसाइटों की तुलना करता है:

वेबसाइट एक: इसमें Imgix CDN के ज़रिए दिखाई गई इमेज वाले नेटिव <img> एलिमेंट का इस्तेमाल किया जाता है (डिफ़ॉल्ट कॉन्फ़िगरेशन विकल्पों के साथ).

दूसरी वेबसाइट: सभी इमेज के लिए, इमेज डायरेक्टिव का इस्तेमाल करें. इसमें, डायरेक्टिव की चेतावनियों या गड़बड़ियों से सीधे तौर पर सुझाए गए ऑप्टिमाइज़ेशन भी शामिल हैं.

फ़िल्मस्ट्रिप की तुलना: नेटिव इमेज टैग वाली वेबसाइट एक बनाम ऐंगलर इमेज डायरेक्टिव वाली वेबसाइट दो.

टीम ने पार्टनर के साथ मिलकर, असली एंटरप्राइज़ Angular ऐप्लिकेशन पर इमेज डायरेक्टिव की परफ़ॉर्मेंस के असर की पुष्टि की.

इनमें से एक पार्टनर Land's End था. उम्मीद थी कि उनकी साइट, उन नतीजों के लिए एक अच्छा टेस्ट केस होगी जो असल ऐप्लिकेशन को दिख सकते हैं.

इमेज डायरेक्टिव का इस्तेमाल करने से पहले और बाद में, उनके क्यूए (क्वालिटी जांच) एनवायरमेंट पर लाइटहाउस लैब टेस्टिंग की गई. डेस्कटॉप पर, उनका मीडियन एलसीपी 12.0 सेकंड से घटकर 3.0 सेकंड हो गया. इसका मतलब है कि एलसीपी में 75% की बढ़ोतरी हुई. मोबाइल पर, मीडियन एलसीपी 20.2 सेकंड से घटकर 12.0 सेकंड हो गया (40.6% की बढ़ोतरी).

आने वाले समय का रोडमैप

यह ऐंग्युलर इमेज डायरेक्टिव के लिए डिज़ाइन का सिर्फ़ पहला हिस्सा है. आने वाले समय में, इसमें और भी कई सुविधाएं जोड़ी जाएंगी. जैसे:

  • रिस्पॉन्सिव इमेज के लिए बेहतर सुविधा:

    फ़िलहाल, NgOptimizedImage में srcset का इस्तेमाल किया जा सकता है. हालांकि, हर इमेज के लिए, srcset और sizes एट्रिब्यूट को मैन्युअल तौर पर देना होगा. आने वाले समय में, डायरेक्टिव srcset और sizes एट्रिब्यूट को अपने-आप जनरेट कर सकता है.

  • संसाधनों के लिए अपने-आप निर्देश डालना

    एलसीपी की अहम इमेज के लिए, प्रीकनेक्ट और प्रीलोड टैग जनरेट करने के लिए, Angular CLI के साथ इंटिग्रेट किया जा सकता है.

  • Angular SSR के लिए सहायता

    एमवीपी वर्शन को Angular CSR की सीमाओं को ध्यान में रखकर डिज़ाइन किया गया है. हालांकि, Angular SSR (angular/universal) के लिए इमेज ऑप्टिमाइज़ेशन के समाधानों को एक्सप्लोर करना भी ज़रूरी होगा.

  • डेवलपर के अनुभव को बेहतर बनाना

    NgOptimizedImage के लिए ज़रूरी है कि हर इमेज के लिए width और height एट्रिब्यूट की वैल्यू दी गई हो. हालांकि, कुछ डेवलपर के लिए हर इमेज के लिए ये जानकारी देना मुश्किल हो सकता है. अगले वर्शन में, डेवलपर के अनुभव को बेहतर बनाने के लिए ये काम किए जा सकते हैं:

    1. एक और मोड के साथ काम करना, जो "fill" Next.js में इमेज लेआउट के विकल्प जैसा हो. इस मोड में, चौड़ाई/ऊंचाई की जानकारी देने की ज़रूरत नहीं होती.
    2. सीएलआई इंटिग्रेशन का इस्तेमाल करके, लोकल इमेज की चौड़ाई और ऊंचाई अपने-आप सेट करने के लिए, इमेज के असल डाइमेंशन का पता लगाना.

नतीजा

Angular इमेज डायरेक्टिव, डेवलपर के लिए अलग-अलग चरणों में उपलब्ध होगा. यह v14.2.0 में डेवलपर के लिए उपलब्ध प्रीव्यू वर्शन से शुरू होगा. NgOptimizedImage को आज़माएं और अपने सुझाव/राय दें!

इस सुविधा को बनाने में योगदान देने के लिए, केटी हेंपेनियस और ऐलेक्स कैसल का विशेष धन्यवाद.