Hari ini kami menerbitkan bagian kedua dari terjemahan materi, yang dikhususkan untuk penggunaan JS-modul dalam produksi.

→ Ngomong-ngomong, ini bagian
pertama artikel.
Impor dinamis
Salah satu kelemahan menggunakan ekspresi impor nyata untuk memisahkan kode dan memuat modul adalah bahwa tugas bekerja dengan browser yang tidak mendukung modul ada pada pengembang.
Dan jika Anda ingin menggunakan perintah
import()
dinamis
import()
untuk mengatur pemuatan kode malas, maka Anda, antara lain, harus berurusan dengan fakta bahwa beberapa browser, walaupun, yang paling pasti,
modul dukungan , masih
tidak mendukung perintah impor dinamis () (Tepi 16–18, Firefox 60–66, Safari 11, Chrome 61–63).
Untungnya, masalah ini akan membantu kita menyelesaikan
polyfill kecil (sekitar 400 byte) dan sangat cepat.
Menambahkan polyfill ini ke proyek web sangat sederhana. Anda hanya perlu mengimpor dan menginisialisasi di titik entri utama ke aplikasi (sebelum memanggil perintah
import()
dalam kode):
import dynamicImportPolyfill from 'dynamic-import-polyfill';
Dan hal terakhir yang perlu dilakukan agar skema ini bekerja, adalah memberi tahu Rollup bahwa ia perlu mengganti nama perintah
import()
dinamis yang muncul dalam kode menggunakan nama yang Anda
pilih (melalui opsi
output.dynamicImportFunction ). Sebuah polyfill yang mengimplementasikan fitur impor dinamis menggunakan nama
__import__
secara default, tetapi dapat
dikustomisasi .
Alasan Anda perlu mengganti nama
import()
adalah karena
import
adalah, dalam JavaScript, kata kunci. Ini berarti bahwa tidak mungkin, dengan cara polyfill, untuk mengatur penggantian perintah
import()
standar
import()
dengan perintah dengan nama yang sama. Jika Anda mencoba melakukan ini, kesalahan sintaksis akan terjadi.
Tetapi sangat bagus bahwa Rollup mengganti nama perintah selama pembangunan proyek, karena ini berarti Anda dapat menggunakan perintah standar dalam kode sumber. Selain itu, di masa mendatang, ketika polyfill tidak lagi diperlukan, kode sumber proyek tidak perlu ditulis ulang, mengubah untuk
import
apa yang sebelumnya disebut entah bagaimana berbeda.
Pemuatan JavaScript yang efisien
Setiap kali Anda menggunakan pemisahan kode, tidak ada salahnya mengatur preloading semua modul yang Anda tahu akan dimuat segera (misalnya, ini semua modul di pohon dependensi dari modul utama, yang merupakan titik masuk ke proyek).
Tetapi ketika kita memuat modul JavaScript nyata (melalui
<script type="module">
dan kemudian melalui perintah
import
sesuai), kita harus menggunakan atribut
modulepreload alih-alih
preload yang biasa, yang hanya ditujukan untuk skrip klasik.
<link rel="modulepreload" href="/modules/main.XXXX.mjs"> <link rel="modulepreload" href="/modules/npm.pkg-one.XXXX.mjs"> <link rel="modulepreload" href="/modules/npm.pkg-two.XXXX.mjs"> <link rel="modulepreload" href="/modules/npm.pkg-three.XXXX.mjs"> <!-- ... --> <script type="module" src="/modules/main.XXXX.mjs"></script>
Bahkan,
modulepreload
jelas lebih baik daripada mekanisme
preload
tradisional dalam preloading modul nyata. Faktanya adalah bahwa ketika Anda menggunakannya, bukan hanya file itu diunduh. Selain itu, segera, di luar utas utama, mulai parsing dan kompilasi skrip.
preload
reguler tidak dapat melakukan ini karena, selama preload, tidak tahu apakah file akan digunakan sebagai modul atau sebagai skrip biasa.
Ini berarti bahwa memuat modul menggunakan atribut
modulepreload
seringkali lebih cepat, dan ketika modul diinisialisasi, kecil kemungkinannya untuk membuat beban berlebihan pada utas utama, yang menyebabkan masalah antarmuka.
Membuat daftar modul untuk preloading
Fragmen input dalam objek
bundel Rollup berisi daftar lengkap impor di pohon dependensi statis mereka. Akibatnya, di kait Rollup
generateBundle , mudah untuk mendapatkan daftar file yang harus dimuat sebelumnya.
Meskipun plugin dapat ditemukan di npm untuk membuat daftar modulepreload, membuat daftar yang serupa untuk setiap titik input di pohon dependensi hanya memerlukan beberapa baris kode. Karena itu, saya lebih suka membuat daftar seperti itu secara manual, menggunakan sesuatu seperti kode ini:
{ generateBundle(options, bundle) {
Di sini, misalnya, adalah bagaimana saya membuat
daftar modulepreload untuk
philipwalton.com dan untuk
aplikasi demo saya, yang akan kita bahas di bawah ini.
Harap perhatikan bahwa meskipun atribut
modulepreload
jelas lebih baik daripada
preload
klasik untuk memuat skrip modul, ia memiliki dukungan browser terburuk (saat ini hanya Chrome yang mendukungnya). Jika sebagian besar lalu lintas Anda tidak berasal dari Chrome, maka dalam situasi Anda mungkin masuk akal untuk menggunakan
preload
reguler alih-alih
preload
.
Mengenai penggunaan
preload
, saya ingin memperingatkan Anda tentang sesuatu. Faktanya adalah bahwa ketika memuat skrip menggunakan
preload
, tidak seperti
modulepreload
, skrip ini tidak masuk ke peta modul browser. Ini berarti bahwa ada kemungkinan bahwa permintaan preload dapat dieksekusi lebih dari satu kali (misalnya, jika modul mengimpor file sebelum browser selesai melakukan preloading).
Mengapa menggunakan modul nyata dalam produksi?
Jika Anda sudah menggunakan bundler seperti
webpack , serta jika Anda sudah menggunakan pemisahan kode dan preloading file yang sesuai (mirip dengan apa yang saya katakan), maka Anda mungkin bertanya-tanya apakah Anda harus beralih ke strategi berfokus pada penggunaan modul nyata. Ada beberapa alasan yang membuat saya percaya bahwa Anda harus mempertimbangkan beralih ke modul. Selain itu, saya percaya bahwa mengubah proyek menjadi modul nyata lebih baik daripada menggunakan skrip klasik dengan kode mereka sendiri yang dirancang untuk memuat modul.
▍ Mengurangi jumlah total kode
Jika proyek menggunakan modul nyata, maka pengguna browser modern tidak perlu mengunduh beberapa kode tambahan yang dirancang untuk memuat modul atau untuk mengelola dependensi. Misalnya, saat menggunakan modul nyata, Anda tidak perlu memuat
mekanisme runtime dan manifes webpack .
▍ Peningkatan kode preload
Seperti yang disebutkan di bagian sebelumnya, menggunakan atribut
modulepreload
memungkinkan
modulepreload
untuk memuat kode dan
modulepreload
-
modulepreload
dan mengkompilasinya di luar utas utama. Yang lainnya, dibandingkan dengan atribut
preload
, tetap sama. Ini berarti bahwa berkat
modulepreload
halaman menjadi lebih cepat interaktif, dan yang mengurangi kemungkinan memblokir aliran utama selama interaksi pengguna.
Akibatnya, terlepas dari ukuran apa kode aplikasi dibagi menjadi beberapa fragmen, akan jauh lebih produktif untuk mengunduh fragmen ini menggunakan perintah impor dan atribut
modulepreload
daripada memuatnya menggunakan tag
script
biasa dan atribut
preload
biasa (terutama jika tag yang sesuai dihasilkan dinamis dan ditambahkan ke DOM saat runtime).
Dengan kata lain, bundel rollup dari beberapa kode proyek, yang terdiri dari 20 fragmen modul, akan memuat lebih cepat dari bundel proyek yang sama, terdiri dari 20 fragmen skrip klasik yang disiapkan oleh webpack (bukan karena menggunakan webpack, tetapi karena bahwa ini bukan modul nyata).
▍ Meningkatkan fokus kode di masa depan
Banyak fitur baru browser yang dibangun berdasarkan modul, dan tidak didasarkan pada skrip klasik. Ini berarti bahwa jika Anda berencana untuk menggunakan fitur-fitur ini, maka kode Anda harus disajikan dalam bentuk modul nyata. Seharusnya bukan sesuatu yang ditranskrip dalam ES5 dan dimuat dengan cara tag
script
klasik (ini adalah masalah yang saya tulis ketika saya mencoba menggunakan
API Penyimpanan KV eksperimental).
Berikut adalah beberapa fitur browser baru yang paling menarik yang berfokus secara eksklusif pada modul:
Dukungan Browser Legacy
Secara global,
lebih dari 83% browser mendukung modul JavaScript (termasuk impor dinamis), sebagai akibatnya, sebagian besar pengguna akan dapat bekerja dengan proyek yang beralih ke modul tanpa upaya khusus dari pihak pengembang proyek ini.
Dalam hal browser yang mendukung modul tetapi tidak mendukung impor dinamis, disarankan untuk menggunakan
dynamic-import-polyfill polyfill yang dijelaskan di atas. Karena sangat kecil dan, jika mungkin, menggunakan metode
import()
berbasis browser standar, penggunaan polyfill ini hampir tidak berpengaruh pada ukuran atau kinerja proyek.
Jika kita berbicara tentang browser yang sama sekali tidak mendukung modul, maka, untuk mengatur pekerjaan dengan mereka, Anda dapat menggunakan pola
modul / nomodule .
▍ Contoh pengoperasian
Karena selalu lebih mudah untuk berbicara tentang kompatibilitas lintas-browser daripada mencapainya, saya membuat
aplikasi demo yang menggunakan teknologi yang dibahas di atas.
Aplikasi ini berfungsi di peramban seperti Edge 18 dan Firefox ESR, yang tidak mendukung perintah
import()
dinamis
import()
. Selain itu, ini berfungsi di browser seperti Internet Explorer 11, yang tidak mendukung modul.
Untuk menunjukkan bahwa strategi yang dibahas di sini tidak hanya cocok untuk proyek-proyek sederhana, saya menggunakan banyak fitur dalam aplikasi ini yang dibutuhkan saat ini dalam proyek-proyek besar:
- Transformasi kode menggunakan Babel (termasuk JSX).
- Ketergantungan umumJS (mis. Bereaksi dan bereaksi).
- Dependensi CSS.
- Hashing Sumber Daya
- Pemisahan kode
- Impor dinamis (dengan fallback sebagai polyfill).
- Implementasi pola modul / nomodule.
Kode proyek dapat ditemukan di
GitHub (yaitu, Anda dapat melakukan fork repositori dan membangun proyek sendiri), versi demo dihosting di
Glitch , yang memungkinkan Anda untuk bereksperimen dengannya.
Hal terpenting dalam proyek demo adalah
konfigurasi Rollup , karena menentukan bagaimana modul yang dihasilkan dibuat.
Ringkasan
Saya harap materi ini meyakinkan Anda tidak hanya tentang kemungkinan penerapan modul JavaScript standar dalam produksi, tetapi juga bahwa itu benar-benar dapat meningkatkan waktu pemuatan situs dan kinerjanya.
Berikut ini adalah ikhtisar singkat tentang langkah-langkah yang perlu Anda ambil untuk mengimplementasikan modul-modul dalam proyek:
- Gunakan bundler, di antara format output yang didukung oleh modul ES2015.
- Secara agresif mendekati pemisahan kode (jika mungkin, sampai alokasi dependensi dari
node_modules
menjadi fragmen yang terpisah). - Preload semua modul yang ada di pohon dependensi statis Anda (menggunakan
modulepreload
). - Gunakan polyfill untuk browser yang tidak mendukung pernyataan
import()
dinamis import()
. - Gunakan pola modul / nomodule untuk mengatur pekerjaan dengan browser yang tidak mendukung modul.
Jika Anda sudah menggunakan Rollup untuk membangun proyek, saya ingin Anda mencoba apa yang saya bicarakan di sini dan pergi untuk menggunakan modul nyata dalam produksi (menggunakan pemisahan kode dan teknik impor dinamis). Jika Anda melakukannya,
beri tahu saya bagaimana kabar Anda. Saya tertarik mengetahui tentang masalah dan tentang kasus-kasus sukses memperkenalkan modul.
Sangat jelas bahwa modul adalah masa depan JavaScript. Saya ingin melihat, dan sebaiknya segera, bagaimana alat yang kami gunakan dan perpustakaan bantu mengadopsi teknologi ini. Saya harap materi ini setidaknya dapat membantu proses ini sedikit.
Pembaca yang budiman! Apakah Anda menggunakan modul JS dalam produksi?
