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

Kara Erickson
Kara Erickson
Leena Sohoni
Leena Sohoni

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

बैकग्राउंड

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

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

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 फ़्रेमवर्क में से एक है. फ़िलहाल, डेवलपर इसका इस्तेमाल कर रहे हैं. इसका इस्तेमाल, मोबाइल पर HTTPArchive से क्रॉल किए गए 50 हज़ार से ज़्यादा ऑरिजिन करते हैं. साथ ही, NPM पर हर हफ़्ते लगभग तीन मिलियन बार डाउनलोड किया जाता है.

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

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

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

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

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

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

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

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

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

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

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

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

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

    • यह इमेज की fetchpriority को "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. बिना साइज़ वाली इमेज: अगर इमेज मार्कअप में चौड़ाई और ऊंचाई की जानकारी नहीं दी गई है, तो इमेज डायरेक्टिव गड़बड़ी का मैसेज दिखाता है. साइज़ नहीं डाली गई इमेज की वजह से लेआउट शिफ़्ट हो सकते हैं. इससे पेज की कुल लेआउट शिफ़्ट (CLS) मेट्रिक पर असर पड़ता है. ऐसा होने से रोकने के लिए, हमारा सुझाव है कि इमेज में width और height एट्रिब्यूट की वैल्यू सबमिट करें.

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

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

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

चुनौतियां

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

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

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

  1. सहायता से जुड़े संसाधनों के बारे में सलाह

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

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

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

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

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

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

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

असर

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

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

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

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

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

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

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

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

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

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

    फ़िलहाल, 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 को आज़माएं और अपने सुझाव/राय दें!

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