4 poin oleh GN⁺ 2024-11-04 | 1 komentar | Bagikan ke WhatsApp
  • 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>
  • Paket npm tersedia dengan nama cash-dom
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

 
GN⁺ 2024-11-04
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-alih document.querySelector('#country'), dan dqsA('.city') alih-alih document.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

    • Dua baris yang melakukan binding querySelector/querySelectorAll itu sendiri terlihat berguna dan masuk akal, tetapi mengambilnya lewat import terasa berlebihan
      Itu cuma dua baris sederhana, tidak ada alasan menjadikannya dependency; cukup salin-tempel saja
    • Tidak semua fungsi utilitas hanya satu baris
      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 ini
      dqsA = s => Array.from(document.querySelectorAll(s));
      Dengan begitu, method array seperti .map() atau .filter() bisa langsung dipakai pada hasilnya, sehingga masih terasa mirip jQuery
    • Baru-baru ini saya mencoba menghapus dependency React, tetapi dalam penanganan event, perbedaan antar-browser ternyata masih cukup besar
      Misalnya saat pengujian, di Safari event select pada elemen tertentu sama sekali tidak muncul, dan di beberapa browser event tidak muncul ketika hanya caret yang berpindah
      Meski tidak membutuhkan fitur React seperti komponen, state, atau props, fungsi native browser saja belum cukup; nilai React DOM dalam menutupi perbedaan browser jadi terlihat
    • Terlihat mirip bling.js: https://gist.github.com/paulirish/12fb951a8b893a454b32
  • 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

    • Daya tarik jQuery bagi banyak orang adalah tidak perlu mengkhawatirkan apakah selector tertentu benar-benar cocok dengan elemen nyata
      Jika memerintahkan untuk menyembunyikan semua .foo, kalau ada akan disembunyikan, kalau tidak ada tidak terjadi apa-apa; pendekatan fire and forget yang mirip CSS
      Jika menulis .foo { color: red; } tetapi tidak ada .foo di dokumen, tidak ada efek samping selain overhead kecil
    • Di browser modern, mengubah semua item hasil query juga bisa dilakukan cukup rapi dalam satu baris
      document.querySelectorAll('input[type=checkbox]').forEach((i) => i.checked = false);
      Ini memanfaatkan NodeList yang bisa diiterasi dan iterator helper
      Banyak query parent bisa ditangani dengan element.closest()
    • Saya sepenuhnya setuju bahwa default seharusnya ketat
      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

    • Terlepas dari paket ini sendiri, saya selalu bingung melihat logika seperti ini dalam pembahasan jQuery
      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
    • Logika itu terdengar seperti “restoran cepat saji arus utama menjual makanan 1600 kalori, jadi kenapa membuat salad untuk makan siang” atau “utang negara hampir 35 triliun dolar, jadi kenapa membandingkan suku bunga KPR”
      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
    • Alih-alih bertanya “kenapa repot-repot?”, jika kita menerima dependency kecil, dependency itu sendiri juga bisa menjadi lebih kecil
    • Situs web arus utama lebih mirip sampah untuk mengantarkan iklan, dan tidak boleh dijadikan standar untuk pekerjaan yang harus kita lakukan
    • Masih ada orang yang berusaha mengirim seluruh JavaScript dalam ukuran di bawah 50KB
  • 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

    • Dokumentasinya saling bertentangan
      me() disebut mengembalikan 1 elemen, atau elemen pertama, atau null, sedangkan any() disebut mengembalikan array atau array kosong
      Namun contoh di bawah seperti any('button')?.forEach(...) dan any('button')?.map(...) menyiratkan bahwa nilainya juga bisa null
      Saya bingung apakah any() selalu mengembalikan array seperti penjelasan di atas, atau juga bisa null seperti pada contoh di bawah
    • Bagus
      Saya terutama tertarik pada lokalitas perilaku
      Saya penasaran bagaimana pengalaman memakai currentScript.parentElement
      Saat 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 async atau module, sepertinya meski memuat 3 skrip berurutan, currentScript.parentElement semestinya tetap berfungsi di semua browser
      SvelteKit 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 sebagai HTMLDivElement

    • Paket itu disebut typed-query-selector
      Contoh penggunaan nyatanya ada di sini: https://github.com/GoogleChrome/lighthouse/blob/main/types/i...
    • Elixir dan beberapa bahasa lain bisa melakukan hal seperti itu dengan pattern matching dan sistem tipe, tetapi banyak bahasa tidak bisa
      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