Pramuat modul

Sérgio Gomes

Pengembangan berbasis modul menawarkan beberapa keuntungan nyata dalam hal kemampuan {i>cache<i}, membantu mengurangi jumlah byte yang perlu dikirimkan ke pengguna Anda. Perincian kode yang lebih baik juga membantu cerita pemuatan, dengan memungkinkan Anda memprioritaskan kode penting dalam aplikasi Anda.

Namun, dependensi modul menimbulkan masalah pemuatan, karena browser membutuhkan menunggu modul dimuat sebelum mengetahui dependensinya. Sekali jalan ini adalah dengan melakukan pramuat dependensi, sehingga browser mengetahui semua file sebelumnya dan dapat membuat koneksi tetap sibuk.

<link rel="preload"> adalah cara untuk meminta sumber daya secara deklaratif, sebelum browser membutuhkannya.

<head>
  <link rel="preload" as="style" href="critical-styles.css">
  <link rel="preload" as="font" crossorigin type="font/woff2" href="myfont.woff2">
</head>

Dukungan Browser

  • Chrome: 50.
  • Edge: ≤79.
  • Firefox: 85.
  • Safari: 11.1.

Sumber

Ini berfungsi sangat baik dengan sumber daya seperti font, yang sering kali tersembunyi di dalam file CSS, terkadang beberapa tingkatan. Dalam situasi tersebut, browser harus menunggu beberapa perjalanan bolak-balik sebelum mengetahui bahwa ia harus mengambil file {i>font<i} yang besar, ketika bisa menggunakan waktu tersebut untuk memulai download dan memanfaatkan seluruh {i>bandwidth<i} koneksi.

<link rel="preload"> dan header HTTP yang setara memberikan elemen cara memberi tahu browser secara langsung tentang file penting yang akan diperlukan sebagai bagian dari navigasi saat ini. Saat browser melihat pramuat, browser akan memulai download prioritas untuk resource, sehingga pada saat resource tersebut benar-benar dibutuhkan, sudah diambil atau sebagian berada di sana. Namun, ini tidak berfungsi untuk modul.

Di sinilah segalanya menjadi rumit. Ada beberapa mode kredensial untuk sumber daya, dan untuk mendapatkan hasil cache, mereka harus cocok, jika tidak, Anda akan dan mengambil resource dua kali. Tidak perlu dikatakan, pengambilan ganda itu buruk, karena itu membuang-buang {i>bandwidth<i} pengguna dan membuat mereka menunggu lebih lama, tanpa alasan yang jelas.

Untuk tag <script> dan <link>, Anda dapat menetapkan mode kredensial dengan crossorigin . Namun, ternyata <script type="module"> tanpa Atribut crossorigin menunjukkan mode kredensial omit, yang tidak ada untuk <link rel="preload">. Ini berarti Anda harus ubah atribut crossorigin di <script> dan <link> menjadi satu nilai-nilai lain, dan Anda mungkin tidak memiliki cara mudah untuk melakukannya jika apa yang Anda mencoba melakukan pramuat adalah dependensi dari modul lain.

Selain itu, mengambil file hanyalah langkah pertama dalam menjalankan kode. Pertama, browser harus mengurai dan mengompilasinya. Idealnya, ini juga harus terjadi sebelumnya, sehingga ketika modul diperlukan, kode akan siap dijalankan. Namun, V8 (mesin JavaScript Chrome) mengurai dan mengompilasi modul secara berbeda dari JavaScript lainnya. <link rel="preload"> tidak menyediakan cara apa pun untuk menunjukkan bahwa file yang dimuat adalah modul, sehingga semua {i>browser<i} adalah memuat file dan memasukkannya ke dalam {i>cache<i}. Setelah skrip dimuat menggunakan Tag <script type="module"> (atau dimuat oleh modul lain), browser akan mengurai dan mengompilasi kode sebagai modul JavaScript.

Singkatnya ya. Dengan memiliki jenis link spesifik untuk melakukan pramuat modul, kita dapat menulis HTML sederhana tanpa mengkhawatirkan mode kredensial apa yang kita gunakan. Tujuan secara {i>default<i}-nya bekerja.

<head>
  <link rel="modulepreload" href="super-critical-stuff.mjs">
</head>
[...]
<script type="module" src="super-critical-stuff.mjs">

Dan karena browser sekarang tahu bahwa apa yang Anda pramuat adalah modul, itu bisa jadi cerdas dan mengurai dan mengompilasi modul segera setelah selesai mengambil, daripada menunggu hingga mencoba dijalankan.

Dukungan Browser

  • Chrome: 66.
  • Edge: ≤79.
  • Firefox: 115.
  • Safari: 17.

Sumber

Namun, bagaimana dengan modul dependensi?

Lucu sekali! Memang ada sesuatu yang belum dibahas dalam artikel ini: rekursi.

Spesifikasi <link rel="modulepreload"> sebenarnya memungkinkan pemuatan secara opsional tidak hanya modul yang diminta, tetapi juga semua hierarki dependensinya. Browser tidak perlu melakukan ini, tetapi hal itu bisa terjadi.

Jadi, apa solusi lintas browser terbaik untuk melakukan pramuat modul dan dependensi, karena Anda memerlukan hierarki dependensi lengkap untuk menjalankan aplikasi?

Browser yang memilih untuk melakukan pramuat dependensi secara rekursif harus memiliki penghapusan duplikat yang kuat modul, jadi secara umum praktik terbaik adalah mendeklarasikan modul dan daftar datar dependensinya, dan percaya bahwa browser tidak mengambil modul yang sama dua kali.

<head>
  <!-- dog.js imports dog-head.js, which in turn imports
       dog-head-mouth.js, which imports dog-head-mouth-tongue.js. -->
  <link rel="modulepreload" href="dog-head-mouth-tongue.mjs">
  <link rel="modulepreload" href="dog-head-mouth.mjs">
  <link rel="modulepreload" href="dog-head.mjs">
  <link rel="modulepreload" href="dog.mjs">
</head>

Apakah modul pramuat membantu performa?

Pramuat dapat membantu memaksimalkan penggunaan {i>bandwidth<i}, dengan memberi tahu browser tentang apa perlu mengambil sehingga tidak macet dengan tidak ada tindakan apa pun selama perjalanan bolak-balik yang lama. Jika Anda bereksperimen dengan modul dan mengalami masalah performa karena hierarki dependensi, membuat daftar bawaan yang biasa akan sangat membantu.

Meskipun demikian, performa modul masih dalam proses, jadi pastikan Anda mengamati apa yang terjadi di aplikasi Anda dengan {i>Developer Tools<i}, dan sementara itu, pertimbangkan untuk membagi aplikasi Anda menjadi beberapa bagian. Ada banyak pekerjaan modul yang berkelanjutan terjadi di Chrome, sehingga kami semakin dekat untuk memberikan pemaket atas istirahat mereka!