Mengotomatiskan kompresi dan encoding

Menjadikan pembuatan sumber gambar berperforma tinggi bagian lancar dari proses pengembangan Anda.

Semua sintaks dalam materi ini—mulai dari pengkodean data gambar hingga yang mendukung gambar responsif—merupakan metode bagi mesin untuk berkomunikasi dengan mesin. Anda memiliki menemukan sejumlah cara agar {i>browser<i} klien mengkomunikasikan kebutuhannya ke server, dan server untuk memberikan tanggapan. Markup gambar responsif (khususnya srcset dan sizes) berhasil mendeskripsikan sejumlah informasi yang mengejutkan dengan relatif beberapa karakter. Baik atau buruk, kesingkatan itu memang sengaja dibuat: membuat sintaks ini tidak terlalu singkat, dan lebih mudah bagi developer untuk diurai, dapat membuatnya lebih sulit untuk diurai oleh browser. Makin rumit ditambahkan ke suatu {i>string<i}, maka potensi kesalahan pengurai, atau perbedaan perilaku yang tidak disengaja dari satu browser ke browser lainnya.

Jendela encoding gambar otomatis.

Namun, sifat yang sama yang dapat membuat subjek ini terasa sangat mengintimidasi juga dapat memberi Anda solusi: {i>syntax<i} dengan mudah dibaca oleh mesin adalah sintaksis yang lebih mudah ditulis oleh mesin. Anda hampir pasti telah menemukan banyak contoh otomatisasi encoding dan kompresi gambar sebagai pengguna web: gambar apa pun yang diupload ke web melalui platform media sosial, konten sistem pengelolaan (CMS), dan bahkan klien email hampir selalu melalui sistem yang mengubah ukuran, mengenkode ulang, dan mengompresinya.

Demikian pula, baik melalui plugin, library eksternal, alat proses build mandiri, atau penggunaan pembuatan skrip sisi klien yang bertanggung jawab, markup gambar responsif siap digunakan untuk otomatisasi.

Itulah dua permasalahan utama seputar otomatisasi performa gambar: mengelola pembuatan gambar—encodingnya, kompresi, dan sumber alternatif yang akan Anda gunakan untuk mengisi atribut srcset—dan membuat markup yang ditampilkan kepada pengguna. Dalam modul ini, Anda akan mempelajari beberapa pendekatan umum untuk mengelola gambar sebagai bagian dari alur kerja modern, baik sebagai otomatis pada proses pengembangan, melalui kerangka kerja atau sistem pengelolaan konten yang mendukung situs, atau hampir sepenuhnya diabstraksikan oleh jaringan penayangan konten khusus.

Mengotomatiskan kompresi dan encoding

Anda tidak akan menemukan diri Anda dalam posisi di mana Anda perlu meluangkan waktu untuk menentukan secara manual encoding dan level yang ideal kompresi untuk setiap gambar individual yang dimaksudkan untuk digunakan pada proyek—Anda juga tidak mau. Sebagai penting karena menjaga ukuran transfer gambar sekecil mungkin , akan menyesuaikan setelan kompresi dan penyimpanan ulang sumber alternatif untuk setiap aset gambar yang ditujukan untuk situs produksi, hambatan yang sangat besar dalam pekerjaan sehari-hari.

Seperti yang telah Anda pelajari saat membaca tentang berbagai format gambar dan jenis kompresi, pengkodean yang paling efisien untuk gambar akan selalu ditentukan oleh kontennya, dan seperti yang Anda pelajari di Gambar Responsif, ukuran alternatif yang Anda perlukan untuk sumber gambar adalah ditentukan oleh posisi gambar tersebut dalam tata letak halaman. Dalam alur kerja modern, Anda akan melakukan pendekatan terhadap keputusan ini secara holistik, bukan satu per satu—menentukan satu set {i>default<i} gambar yang logis, agar sesuai dengan konteks data tersebut dimaksudkan untuk digunakan.

Ketika memilih encoding untuk direktori gambar fotografi, AVIF adalah pemenang mutlak untuk kualitas dan ukuran transfer tetapi memiliki dukungan terbatas, WebP menyediakan penggantian modern yang dioptimalkan, dan JPEG adalah default yang paling andal. Alternatif yang dibutuhkan untuk menghasilkan gambar yang dimaksudkan untuk menempati {i>sidebar<i} di tata letak laman akan sangat bervariasi dari gambar yang dimaksudkan menempati seluruh area pandang browser di titik henti sementara tertinggi. Setelan kompresi akan mengharuskan Anda memperhatikan pemburaman dan artefak kompresi di beberapa file yang dihasilkan, sehingga memberikan lebih sedikit ruang untuk melakukan setiap byte yang memungkinkan dari setiap gambar sebagai imbalan atas alur kerja yang lebih fleksibel dan andal. Singkatnya, Anda akan mengikuti proses pengambilan keputusan yang sama seperti dari materi ini.

Untuk pemrosesan itu sendiri, ada sejumlah besar pustaka pemrosesan gambar {i>open source<i} yang menyediakan metode mengonversi, memodifikasi, dan mengedit gambar dalam beberapa kelompok, yang bersaing dalam hal kecepatan, efisiensi, dan keandalan. Pemrosesan ini memungkinkan Anda menerapkan setelan encoding dan kompresi ke seluruh direktori gambar sekaligus, tanpa membuka software pengeditan gambar, dan mempertahankan sumber gambar asli jika setelan itu memerlukannya. untuk disesuaikan dengan cepat. Iklan ini dimaksudkan untuk dijalankan dalam berbagai konteks, dari lingkungan pengembangan lokal Anda hingga server web itu sendiri—misalnya, ImageMin yang berfokus pada kompresi untuk Node.js dapat diperluas agar sesuai dengan aplikasi tertentu melalui array plugin, sedangkan ImageMagick lintas platform dan Sharp berbasis Node.js memiliki beragam fitur yang langsung bisa digunakan.

Library pemrosesan gambar ini memungkinkan developer membuat alat khusus untuk mengoptimalkan gambar dengan lancar sebagai bagian dari proses pengembangan standar—memastikan bahwa project Anda akan selalu merujuk pada image siap produksi sumber data dengan overhead yang seminimal mungkin.

Alur kerja dan alat pengembangan lokal

Task-runner dan pemaket seperti Grunt, Gulp, atau Webpack dapat digunakan untuk mengoptimalkan aset gambar beserta tugas umum lain yang terkait performa, seperti minifikasi CSS dan JavaScript. Kepada menggambarkan, mari kita ambil kasus penggunaan yang relatif sederhana: direktori dalam proyek Anda berisi selusin gambar fotografi, yang dimaksudkan untuk digunakan pada {i>website<i} yang berhubungan dengan publik.

Pertama-tama, Anda harus memastikan encoding yang konsisten dan efisien untuk gambar ini. Seperti yang telah Anda pelajari di modul sebelumnya, WebP adalah default yang efisien untuk gambar fotografi dalam hal kualitas dan ukuran file. WebP didukung dengan baik, tetapi tidak didukung secara universal, jadi Anda juga perlu menyertakan fallback dalam bentuk progressive JPEG. Lalu: agar dapat menggunakan atribut srcset untuk pengiriman aset ini secara efisien, Anda harus membuat beberapa ukuran alternatif untuk setiap encoding.

Meskipun ini akan menjadi tugas yang berulang dan memakan waktu jika dilakukan dengan perangkat lunak pengeditan gambar, pelari tugas seperti Gulp dirancang untuk mengotomatiskan pengulangan semacam ini. Class gulp-responsive , yang menggunakan Sharp, adalah salah satu dari banyak opsi yang semuanya mengikuti pola serupa: mengumpulkan semua file dalam direktori sumber, mengenkodenya ulang, dan mengompresinya berdasarkan "kualitas" standar yang sama singkat yang telah Anda pelajari di Format dan Kompresi Gambar. File yang dihasilkan kemudian {i>output<i} ke jalur yang Anda tentukan, siap direferensikan dalam atribut src dari elemen img yang ditampilkan kepada pengguna sekaligus membiarkan file asli Anda tetap utuh.

const { src, dest } = require('gulp');
const respimg = require('gulp-responsive');

exports.webp = function() {
  return src('./src-img/*')
    .pipe(respimg({
      '*': [{
        quality: 70,
        format: ['webp', 'jpeg'],
        progressive: true
      }]
  }))
  .pipe(dest('./img/'));
}

Dengan proses seperti ini, tidak ada kerugian yang akan terjadi pada lingkungan produksi jika seseorang dalam proyek secara tidak sengaja menambahkan foto yang dienkode sebagai PNG truecolor besar ke direktori yang berisi sumber gambar asli Anda—apa pun encoding gambar asli, tugas ini akan menghasilkan WebP yang efisien dan fallback progressive JPEG yang andal, serta tingkat kompresi yang dapat dengan mudah disesuaikan dengan cepat. Tentu saja, proses ini juga memastikan bahwa citra asli Anda file akan disimpan di dalam lingkungan pengembangan proyek, yang berarti bahwa pengaturan ini dapat disesuaikan kapan saja hanya dengan output otomatis yang ditimpa.

Untuk menghasilkan {i>output<i} beberapa file, Anda meneruskan beberapa objek konfigurasi—semuanya sama, terlepas dari penambahan kunci width dan nilai dalam piksel:

const { src, dest } = require('gulp');
const respimg = require('gulp-responsive');

exports.default = function() {
  return src('./src-img/*')
    .pipe(respimg({
    '*': [{
            width: 1000,
            format: ['jpeg', 'webp'],
            progressive: true,
            rename: { suffix: '-1000' }
            },
            {
            width: 800,
            format: ['jpeg', 'webp'],
            progressive: true,
            rename: { suffix: '-800' }
            },
            {
            width: 400,
            format: ['jpeg', 'webp'],
            progressive: true,
            rename: { suffix: '-400' },
        }]
        })
    )
    .pipe(dest('./img/'));
}

Dalam kasus contoh di atas, gambar asli (monarch.png) berukuran lebih dari 3,3 MB. File terbesar yang dibuat oleh tugas ini (monarch-1000.jpeg) berukuran sekitar 150 KB. Yang terkecil, monarch-400.web, hanya berukuran 32KB.

[10:30:54] Starting 'default'...
[10:30:54] gulp-responsive: monarch.png -> monarch-400.jpeg
[10:30:54] gulp-responsive: monarch.png -> monarch-800.jpeg
[10:30:54] gulp-responsive: monarch.png -> monarch-1000.jpeg
[10:30:54] gulp-responsive: monarch.png -> monarch-400.webp
[10:30:54] gulp-responsive: monarch.png -> monarch-800.webp
[10:30:54] gulp-responsive: monarch.png -> monarch-1000.webp
[10:30:54] gulp-responsive: Created 6 images (matched 1 of 1 image)
[10:30:54] Finished 'default' after 374 ms

Tentu saja, Anda ingin memeriksa hasil dengan cermat untuk menemukan artefak kompresi yang terlihat, atau mungkin meningkatkan kompresi untuk penghematan tambahan. Karena tugas ini tidak bersifat destruktif, setelan ini dapat diubah dengan mudah.

Dengan kata lain, sebagai ganti beberapa kilobita yang bisa Anda hilangkan dengan pengoptimalan mikro manual yang cermat, Anda mendapatkan proses yang tidak hanya efisien, tetapi juga tangguh—alat yang secara lancar menerapkan pengetahuan Anda tentang aset gambar berperforma tinggi ke keseluruhan proyek, tanpa intervensi manual apa pun.

Cara kerja markup gambar responsif

Mengisi atribut srcset biasanya menjadi proses manual yang mudah, karena atribut benar-benar hanya mengambil informasi tentang konfigurasi yang telah Anda lakukan saat membuat sumber. Pada tugas di atas, kita telah menetapkan nama file dan informasi lebar yang akan diikuti oleh atribut:

srcset="filename-1000.jpg 1000w, filename-800.jpg 800w, filename-400.jpg 400w"

Ingat bahwa konten atribut srcset bersifat deskriptif, bukan preskriptif. Tidak ada salahnya membebani srcset, asalkan rasio aspek setiap sumber konsisten. Atribut srcset dapat berisi URI dan lebar setiap potongan alternatif yang dihasilkan oleh server tanpa menyebabkan permintaan yang tidak perlu, dan sumber yang kami sediakan untuk gambar hasil render, maka browser akan semakin efisien dalam menyesuaikan permintaan.

Seperti yang telah dipelajari di Gambar Responsif, sebaiknya Anda memanfaatkan elemen <picture> untuk menangani WebP dengan lancar atau JPEG. Dalam hal ini, Anda akan menggunakan atribut type bersama dengan srcset.

<picture>
  <source type="image/webp" srcset="filename-1000.webp 1000w, filename-800.webp 800w, filename-400.webp 400w">
  <img srcset="filename-1000.jpg 1000w, filename-800.jpg 800w, filename-400.jpg 400w" sizes="…" alt="…">
</picture>

Seperti yang telah Anda pelajari, browser yang mendukung WebP akan mengenali konten atribut type, lalu memilih <source> atribut srcset elemen sebagai daftar kandidat gambar. Browser yang tidak mengenali image/webp sebagai media yang valid jenis akan mengabaikan <source> ini, dan sebagai gantinya menggunakan atribut srcset elemen <img> bagian dalam.

Ada satu pertimbangan lagi dalam hal dukungan browser: browser tanpa dukungan untuk markup gambar responsif akan masih memerlukan penggantian, atau gambar berisiko rusak terutama dalam konteks penjelajahan lama. Karena <picture>, <source>, dan srcset semua diabaikan di browser ini, kita akan ingin menentukan sumber default di bagian dalam <img> src.

Karena penskalaan gambar ke bawah secara visual lancar dan encoding JPEG didukung secara universal, JPEG terbesar adalah pilihan yang masuk akal.

<picture>
  <source type="image/webp" srcset="filename-1000.webp 1000w, filename-800.webp 800w, filename-400.webp 400w">
  <img src="filename-1000.jpg" srcset="filename-1000.jpg 1000w, filename-800.jpg 800w, filename-400.jpg 400w" sizes="…" alt="…">
</picture>

sizes bisa sedikit lebih sulit untuk ditangani. Seperti yang telah Anda pelajari, sizes harus bersifat kontekstual—Anda tidak dapat mengisi atribut tanpa mengetahui jumlah ruang yang ingin ditempati gambar dalam tata letak yang dirender. Sebagai permintaan yang paling efisien, atribut sizes yang akurat harus berada di markup kami pada saat permintaan tersebut dibuat oleh pengguna akhir, jauh sebelum gaya yang mengatur tata letak laman diminta. Menghilangkan sizes sepenuhnya tidak hanya melanggar spesifikasi HTML, tetapi juga menghasilkan perilaku default yang setara dengan sizes="100vw"—memberi tahu browser bahwa gambar ini hanya dibatasi oleh area pandang itu sendiri, sehingga menghasilkan sumber kandidat yang dipilih.

Seperti halnya pada tugas pengembangan web yang sangat memberatkan, sejumlah alat telah dibuat untuk menyederhanakan proses penulisan atribut sizes. respImageLint adalah cuplikan kode penting yang dimaksudkan untuk memeriksa akurasi atribut sizes Anda dan memberikan saran untuk peningkatan. Halaman ini berjalan sebagai bookmarklet—alat yang dijalankan di browser, sembari diarahkan ke halaman yang dirender sepenuhnya berisi gambar Anda yang kurang penting. Dalam konteks di mana browser memiliki pemahaman penuh tentang tata letak halaman, browser juga akan memiliki hampir piksel-sempurna kemampuan gambar untuk menempati ruang dalam tata letak itu pada setiap ukuran area pandang yang mungkin.

Laporan gambar responsif yang menunjukkan ketidakcocokan ukuran/lebar.

Alat untuk analisis lint atribut sizes tentu saja berguna, tetapi alat ini memiliki nilai lebih sebagai alat untuk menghasilkannya secara grosir. Seperti yang Anda ketahui, sintaksis srcset dan sizes dimaksudkan untuk mengoptimalkan permintaan aset gambar dengan cara yang lancar secara visual. Meskipun bukan sesuatu yang harus digunakan dalam produksi, nilai placeholder sizes default sebesar 100vw sangat wajar saat mengerjakan tata letak halaman di lingkungan pengembangan lokal Anda. Setelah gaya tata letak diterapkan, menjalankan respImageLint akan memberikan atribut sizes yang disesuaikan yang dapat Anda salin dan tempel ke markup, dengan tingkat detail yang jauh lebih besar dari yang ditulis dengan tangan:

Laporan gambar responsif dengan dimensi yang disarankan.

Meskipun permintaan gambar yang dimulai oleh markup yang dirender server terjadi terlalu cepat bagi JavaScript untuk menghasilkan atribut sizes sisi klien, alasan yang sama tidak berlaku jika permintaan tersebut dimulai dari sisi klien. Project Lazysizes, misalnya, memungkinkan Anda untuk menunda permintaan gambar sepenuhnya hingga tata letak dibuat, sehingga memungkinkan JavaScript membuat nilai sizes bagi kami—sebuah kemudahan besar bagi Anda, dan jaminan permintaan yang paling efisien untuk pengguna Anda. Namun, perlu diingat bahwa pendekatan ini berarti mengorbankan keandalan markup yang dirender oleh server dan kecepatan pengoptimalan yang dibangun ke dalam browser, dan memulai permintaan ini hanya setelah halaman dirender akan memiliki dampak negatif pada skor LCP Anda.

Tentu saja, jika Anda sudah bergantung pada kerangka kerja rendering sisi klien seperti React atau Vue, itu adalah utang yang sudah Anda menimbulkan biaya, dan dalam kasus tersebut, menggunakan Lazysizes berarti atribut sizes Anda dapat hampir sepenuhnya diabstraksi. Lebih baik lagi: karena sizes="auto" pada gambar yang dimuat lambat akan memperoleh konsensus dan implementasi native, Lazysizes akan secara efektif menjadi polyfill untuk perilaku browser yang baru distandardisasi.