- Cash adalah pustaka alternatif jQuery yang sangat kecil, menyediakan sintaks bergaya jQuery untuk memanipulasi DOM di browser modern IE11+
- Dengan memanfaatkan fitur browser modern, Cash mengurangi codebase dan memungkinkan penggunaan metode chaining yang familier dengan ukuran file jauh lebih kecil
- Cash tidak menargetkan kesetaraan fitur 100% dengan jQuery, tetapi mencakup sebagian besar kasus penggunaan sehari-hari, dan API yang diimplementasikan umumnya kompatibel dengan jQuery
- Ukurannya 6KB dalam kondisi minified & gzipped, 76,6% lebih kecil dibanding jQuery Slim 3.4.1 yang berukuran 24,4KB, dan dapat diperkecil lagi dengan partial builds
- Mendukung codebase TypeScript, tipe TypeScript yang dihasilkan dari kode, event namespaced, serta partial build yang memungkinkan pengecualian metode individual
Masalah yang Diselesaikan Cash
- Cash adalah alternatif jQuery untuk browser modern, menyediakan selector
$() bergaya jQuery dan metode collection yang dapat di-chain untuk manipulasi DOM
- Target dukungannya adalah browser IE11+
- Tujuannya bukan mengimplementasikan seluruh fitur jQuery apa adanya, tetapi fitur yang diimplementasikan Cash dirancang agar sebagian besar kompatibel dengan API jQuery
- Pengguna yang bermigrasi dari jQuery dapat melihat migration guide
Perbandingan Ukuran dan Fitur
- Dalam perbandingan ukuran file, Cash lebih kecil daripada Zepto 1.2.0 dan jQuery Slim 3.4.1
- Unminified: 36.5KB
- Minified: 16KB
- Minified & Gzipped: 6KB
- jQuery Slim 3.4.1 berukuran 24.4KB dalam kondisi minified & gzipped, sedangkan Cash memberikan pengurangan ukuran 76,6% dibandingkan itu
- Jika membutuhkan bundle yang lebih kecil, partial builds dapat digunakan
- Dari sisi perbandingan fitur, Cash menyediakan dukungan browser modern, pemeliharaan aktif, event namespaced, codebase TypeScript, serta tipe TypeScript yang dihasilkan dari kode
- Partial builds di Cash memungkinkan pengecualian metode individual, sedangkan Zepto dan jQuery Slim ditampilkan sebagai pengecualian pada level modul penuh
Cara Penggunaan
- Cash dapat dimuat dari jsDelivr dan langsung digunakan di browser
<script src="https://cdn.jsdelivr.net/npm/cash-dom/…;
<script>
$(function () {
$('html').addClass ( 'dom-loaded' );
$('<footer>Appended with Cash</footer>').appendTo ( document.body );
});
</script>
npm install --save cash-dom
import $ from "cash-dom";
$(function () {
$('html').addClass ( 'dom-loaded' );
$('<footer>Appended with Cash</footer>').appendTo ( document.body );
});
Struktur API
$() adalah metode selector inti Cash, yang mengembalikan collection node yang dapat dimanipulasi
- Jika sebuah fungsi diberikan, fungsi tersebut dijalankan saat DOM siap
$() dapat menerima selector, DOM node, nodeList, HTML string, Cash collection, atau callback document ready
- Cash secara garis besar menyediakan tiga jenis API
- Query selector
- Metode collection
- Metode pustaka pada objek global
$
Metode Collection
- Metode collection dipanggil dengan cara membuat collection melalui
$(), lalu menggunakan pola seperti $(element).addClass(className)
- Kategori yang tersedia terbagi menjadi attribute, collection, CSS, data, dimension, effect, event, form, manipulasi DOM, offset, dan traversal
- Metode utama mencakup antara lain
- Class/attribute:
addClass, removeClass, toggleClass, attr, prop, removeAttr
- Pemrosesan collection:
add, each, eq, filter, first, get, map, slice
- Manipulasi DOM:
append, prepend, before, after, html, text, clone, remove, replaceWith, wrap
- Event:
on, off, one, ready, trigger
- Traversal:
find, children, closest, parent, parents, siblings, next, prev
- Beberapa extra methods tersedia, tetapi secara default dinonaktifkan
$.fn adalah prototipe utama collection, dan dapat digunakan untuk menambahkan metode kustom ke semua collection seperti plugin
Metode Global Cash
- Objek global
$ mencakup metode pemeriksaan tipe dan utilitas
- Metode pemeriksaan tipe menyediakan
$.isArray, $.isFunction, $.isNumeric, $.isPlainObject, $.isWindow
- Utilitas mencakup
$.guid, $.each, $.extend, $.parseHTML, $.unique
$.extend memperluas objek target dengan properti dari objek sumber, dan juga mendukung deep extension
$.parseHTML mengembalikan collection dari string HTML, sedangkan $.unique mengembalikan array baru yang duplikatnya telah dihapus
Ekstensi dan Kontribusi
- Cash dapat diperluas dengan metode kustom, dan cara memperluasnya dirangkum di extending Cash
- Masalah atau permintaan fitur dapat dibuka sebagai issue di GitHub
- Alur kerja pull request adalah meng-clone repository, menginstal dependensi, menjalankan recompilation otomatis dengan
npm run dev, menjalankan pengujian dengan npm run test, lalu memperbarui README jika diperlukan
- Lisensinya adalah MIT
1 komentar
Opini Hacker News
Karena browser sekarang sudah semakin baik, untuk menyederhanakan manipulasi DOM sering kali cukup dengan alias dua baris berikut
dqs = document.querySelector.bind(document);dqsA = document.querySelectorAll.bind(document);Jadi bisa dipakai seperti
dqs('#country')alih-alihdocument.querySelector('#country'), dandqsA('.city')alih-alihdocument.querySelectorAll('.city')Sisanya cukup memakai fungsi native browser, dan biasanya diambil dari modul seperti
import { dqs, dqsA } from '/lib/js/dqs.js';https://github.com/no-gravity/dqs.js
querySelector/querySelectorAllitu sendiri terlihat berguna dan masuk akal, tetapi mengambilnya lewatimportterasa berlebihanItu cuma dua baris sederhana, tidak ada alasan menjadikannya dependency; cukup salin-tempel saja
Misalnya
$.fn.one()atau$.fn.on()untuk menangani banyak event lebih mudah dipakai lewat jQuery/Cash, dan kalau melihat implementasi internalnya, pekerjaannya cukup banyak: https://github.com/fabiospampinato/cash/blob/master/src/even...querySelectorAll()bukan live collection, jadi sering langsung diubah menjadi array seperti inidqsA = s => Array.from(document.querySelectorAll(s));Dengan begitu, method array seperti
.map()atau.filter()bisa langsung dipakai pada hasilnya, sehingga masih terasa mirip jQueryMisalnya saat pengujian, di Safari event
selectpada elemen tertentu sama sekali tidak muncul, dan di beberapa browser event tidak muncul ketika hanya caret yang berpindahMeski tidak membutuhkan fitur React seperti komponen, state, atau props, fungsi native browser saja belum cukup; nilai React DOM dalam menutupi perbedaan browser jadi terlihat
Setelah hampir semua polyfill disingkirkan, menurut saya keunggulan jQuery yang tetap bertahan adalah pemrosesan daftar otomatis
Kemampuan untuk membatalkan pilihan semua tombol di dalam form dengan satu panggilan masih sulit ditandingi di tempat lain, begitu juga query ke parent
Namun masalah terbesar dalam implementasinya adalah ketika daftar kosong, ia gagal secara diam-diam
Saya sudah terlalu sering memperbaiki bug seperti ini yang muncul saat pohon DOM kemudian direfaktor untuk keperluan layout, jadi kalau membuat ulang jQuery sekarang, default-nya akan melempar error pada himpunan kosong, lalu menyediakan chaining call atau flag agar gagal diam-diam hanya ketika memang tidak peduli
Dulu saya sempat menghabiskan beberapa jam melihat apakah Sizzle bisa dicabut dan diubah seperti ini, tetapi tidak melanjutkannya
Pada akhirnya jQuery juga terkait dengan perdebatan lama library vs framework, dan setelah sekian lama membuat single-page app dengan framework raksasa, rasanya lembah kekecewaan berikutnya sudah dekat lagi
Jika memerintahkan untuk menyembunyikan semua
.foo, kalau ada akan disembunyikan, kalau tidak ada tidak terjadi apa-apa; pendekatan fire and forget yang mirip CSSJika menulis
.foo { color: red; }tetapi tidak ada.foodi dokumen, tidak ada efek samping selain overhead kecildocument.querySelectorAll('input[type=checkbox]').forEach((i) => i.checked = false);Ini memanfaatkan
NodeListyang bisa diiterasi dan iterator helperBanyak query parent bisa ditangani dengan
element.closest()Kode berbasis jQuery menuntut semua developer mengetahui semua selector dalam proyek lalu memperbaruinya saat DOM berubah, yang jelas mustahil
Sepertinya memungkinkan untuk mengganti fungsi inisialisasi jQuery dengan implementasi sendiri yang memaksa pemeriksaan panjang daftar
Dalam situasi situs web arus utama secara harfiah menyebarkan JavaScript berukuran megabyte, saya tidak mengerti alasan menulis ulang seluruh library dengan fitur lebih sedikit hanya demi menghemat 50KB
Banyak tulisan menolak penggunaan jQuery karena ukuran paket dan batasan bandwidth, tetapi pada saat yang sama membela framework SPA yang memakai bandwidth jauh lebih besar
Itu benar-benar penalaran cargo cult yang tidak masuk akal
Dalam ketiga kasus, jawabannya sama: yang besar itu bukan saya, dan saya sedang melakukan hal lain yang lebih kecil
Jawaban lainnya: jika sesuatu yang terlalu besar adalah masalah, maka menjadi lebih kecil terdengar seperti solusi
Pada akhirnya, sepertinya pertanyaan yang ingin diajukan adalah mengapa developer menghabiskan waktu menulis ulang library, tetapi itu bukan hal yang begitu mengejutkan
Sebagian besar pemrograman adalah menulis ulang hal yang sudah ada, entah karena kebutuhan pekerjaan, karena perlu perilaku atau karakteristik performa yang sedikit berbeda, atau sekadar ingin mempelajari cara kerjanya
Jika mencari alternatif jQuery, saya sudah terlalu lama menunggu jQuery 4.0 dan akhirnya membuat sendiri sesuatu yang mirip jQuery dengan beberapa perbedaan penting
Untuk animasi, tween, dan timeline, alih-alih sistem kustom jQuery, ini memakai CSS murni; menangani elemen tunggal dan daftar secara transparan; serta cenderung ditulis secara inline
me()disebut mengembalikan 1 elemen, atau elemen pertama, ataunull, sedangkanany()disebut mengembalikan array atau array kosongNamun contoh di bawah seperti
any('button')?.forEach(...)danany('button')?.map(...)menyiratkan bahwa nilainya juga bisanullSaya bingung apakah
any()selalu mengembalikan array seperti penjelasan di atas, atau juga bisanullseperti pada contoh di bawahSaya terutama tertarik pada lokalitas perilaku
Saya penasaran bagaimana pengalaman memakai
currentScript.parentElementSaat saya menelitinya cepat-cepat bulan lalu, kesan saya mungkin tidak bisa diandalkan pada kasus-kasus pinggiran, tetapi saya tidak ingat persis kapan
Saya tidak mendalaminya, dan senang melihat ada yang membuatnya bekerja dengan baik
Dengan asumsi bukan
asyncataumodule, sepertinya meski memuat 3 skrip berurutan,currentScript.parentElementsemestinya tetap berfungsi di semua browserSvelteKit juga pernah membahas ini, dan akhirnya mengimplementasikan ID acak untuk menentukan elemen target: https://github.com/sveltejs/kit/issues/2221
Saat melihat panduan migrasinya, saya mempelajari beberapa fitur yang bisa dilakukan jQuery tetapi tidak bisa dilakukan Cash, yang sebelumnya tidak saya ketahui dan mungkin suatu saat layak dicoba
https://github.com/fabiospampinato/cash/blob/master/docs/mig...
Sebagai target tambahan, akan bagus kalau bisa memakai keajaiban template string TypeScript untuk menyimpulkan tipe elemen secara akurat
Misalnya,
$('div#name')bisa disimpulkan secara statis sebagaiHTMLDivElementtyped-query-selectorContoh penggunaan nyatanya ada di sini: https://github.com/GoogleChrome/lighthouse/blob/main/types/i...
Saya tidak tahu apakah itu mungkin di TypeScript, dan belum jelas bagi saya bagaimana caranya
Saya dengar jQuery 4 adalah alternatif jQuery untuk browser modern
Pada ekstensi browser yang sedang saya buat, awalnya saya memakai ini, tetapi akhirnya pindah ke library JSX
Begitu melewati ranah “aplikasi sederhana”, jQuery cepat berubah menjadi kode yang sulit dinalar, dan sebagai orang yang pernah membuat sendiri library yang terinspirasi jQuery, saya juga merasakannya begitu
Pada akhirnya, harus memakai alat yang sesuai dengan pekerjaan
[1]: https://github.com/aleclarson/dough
Kalau Anda bisa menangani jQuery dengan baik di aplikasi menengah-besar, silakan saja, tetapi itu bukan selera saya
Dulu, saat mencoba mengurangi JS, saya memakai https://github.com/filamentgroup/shoestring
Alasan utamanya karena ia menyediakan custom build yang hanya memasukkan hal-hal yang benar-benar dibutuhkan
Cash tampaknya punya fitur serupa, tetapi agak lebih tersembunyi di dokumentasinya: https://github.com/fabiospampinato/cash/blob/master/docs/par...
Kalau harus menggunakannya, mungkin saya akan mencoba yang itu lebih dulu
Meski begitu, saya masih berpikir memakai langsung apa yang disediakan browser modern adalah pilihan yang lebih baik
Pada praktiknya sudah cukup bagus, dan jQuery tidak lagi benar-benar diperlukan
Apalagi jika melihat bahwa bahkan alternatif jQuery yang kecil pun berukuran 6kB, sementara Preact, library mirip React, hanya setengah dari itu
Saya tidak yakin apakah ini membantu lebih dari sekadar memberi alias pada Web API yang sudah ada