Friday, April 10, 2020

Kompres dan Tata Ulang Kode CSS, HTML dan JavaScript Kalian dengan Alat Ini

Saya membuat proyek baru berupa situs web berisi kumpulan alat untuk mengompres kode HTML, CSS dan JavaScript secara daring. Saat ini sudah tersedia alat pengompres kode HTML, CSS, JavaScript dan JSON. Untuk ke depannya mungkin akan Saya tambahkan alat-alat kompresi yang lain. Halaman web alat dapat kamu kunjungi melalui tautan https://minify.js.org

Selain alat pengompres, alat untuk menata ulang kode-kode yang sudah dikompres juga tersedia. Saat ini sudah tersedia alat penata kode HTML, CSS, JavaScript dan JSON. Halaman web alat dapat kamu kunjungi melalui tautan https://tidy.js.org

Berikut ini adalah kode-kode pihak ke tiga yang Saya gunakan untuk membuat alat-alat tersebut:

Sebelumnya Saya pernah membuat situs web kumpulan alat serupa pada repositori https://github.com/taufik-nurrohman/mini-web-tools. Tapi dengan adanya situs web yang baru, repositori tersebut kemungkinan besar akan Saya arsipkan. Silakan beri komentar dan saran mengenai alat-alat ini, simpan tautan ke penanda buku, dan bagikan ke teman-teman yang lain kalau kamu merasa bahwa alat-alat ini bermanfaat untuk kamu dan untuk mereka. Terima kasih ♥

Labels: , , , , , ,

Saturday, April 4, 2020

Pilih Mana: Memuat JSON Blogger dengan Metode Tradisional atau dengan Metode AJAX?

Menambahkan parameter alt dengan nilai json atau json-in-script pada URL umpan blog akan memberikan hasil keluaran data berupa JSON. Pengembang bisa memanfaatkan data tersebut untuk membuat gawai blog. Namun untuk bisa memproses data, kita perlu menemukan cara untuk menampung data tersebut ke dalam parameter fungsi:

function recentPosts(json) {
    // Ubah data `json` menjadi gawai di sini…
}

recentPosts( /* Masukan data JSON di sini… */ );

Metode Tradisional

Blogger memberikan akses kepada para pengembang untuk memproses data yang diberikan melalui parameter callback. Dengan menyatakan nama fungsi pada parameter tersebut, maka hasil keluaran JSON mentah yang diberikan akan dilengkapi dengan kode eksekusi fungsi yang membungkus data JSON tersebut. Sebenarnya tidak ada hal yang ajaib dalam sistem pemuatan data seperti itu. Tanpa parameter callback, hasil keluaran yang akan diberikan adalah seperti ini:

{
  "version": "1.0",
  "encoding": "UTF-8",
  "feed": { … }
}

Sedangkan ketika menggunakan parameter callback dengan nilai recentPosts, maka hasil keluaran yang akan diberikan adalah seperti ini:

recentPosts({
  "version": "1.0",
  "encoding": "UTF-8",
  "feed": { … }
});

Sehingga ketika umpan blog berhasil dimuat, maka data yang akan termuat bukan hanya terdiri dari JSON saja tetapi juga fungsi global yang memproses data JSON tersebut pada saat yang bersamaan ketika JSON termuat:

<!-- Tanpa eksekusi fungsi -->
<script src="/feeds/posts/summary?alt=json"></script>

<!-- Dengan eksekusi fungsi -->
<script src="/feeds/posts/summary?alt=json&amp;callback=recentPosts"></script>

Menerapkan metode seperti ini bukan berarti tidak memiliki kekurangan. Karena umpan blog perlu menerima nama fungsi yang bersifat global, maka kita harus mengaitkan fungsi gawai yang kita buat pada objek window. Satu-satunya cara yang bisa kita lakukan adalah dengan mendeklarasikan fungsi tersebut pada bagian terluar dari berkas JavaScript, atau dengan mendeklarasikan fungsi tersebut sebagai salah satu properti dari window jika fungsi tersebut berada di dalam fungsi-fungsi yang lain:

// Metode 1
function recentPosts(json) { … }

// Metode 2
window.recentPosts = function(json) { … };

// Metode 3
(function(w) {
    w.recentPosts = function(json) { … };
})(window);

// Metode 4
function start() {
    function createRecentPostsFunction() {
        function a() { … }
        function b() { … }
        function c() {
            window.recentPosts = function(json) { … };
        }
        a();
        b();
        c();
    }
    function hasRecentPostsFunction() {
        return 'recentPosts' in window && 'function' === typeof window.recentPosts;
    }
    if (!hasRecentPostsFunction()) {
        createRecentPostsFunction();
    }
}

start();

Karena JavaScript memungkinkan kita untuk menimpa fungsi yang telah dibuat sebelumnya dengan cara membuat fungsi yang baru (atau membuat variabel) menggunakan nama yang sama, maka akan sangat mudah bagi fungsi tersebut untuk mengalami konflik-konflik penamaan seperti ini:

<!-- Kode pihak ke 1 (kamu) -->
<script>
function recentPosts(json) { … }
</script>

<!-- Kode pihak ke 3 (orang lain) yang akan merusak fungsi `recentPosts()` -->
<script>
var recentPosts = null;
</script>

<!-- Di sini akan muncul pesan kesalahan “TypeError: recentPosts is not a function” -->
<script src="/feeds/posts/summary?alt=json&amp;callback=recentPosts"></script>

Ada dua cara yang dapat kamu lakukan untuk menghindari masalah tersebut. Cara yang pertama adalah dengan mendeklarasikan fungsi recentPosts sebagai konstanta agar nama fungsi tersebut tidak bisa digunakan lagi di tempat lain setelah konstanta tersebut dinyatakan:

<script>
const recentPosts = json => { … };
</script>

<!-- Akan muncul pesan kesalahan “SyntaxError: redeclaration of const recentPosts” -->
<script>
function recentPosts(json) { … };
</script>

<!-- Akan muncul pesan kesalahan “SyntaxError: redeclaration of const recentPosts” -->
<script>
let recentPosts = json => { … };
</script>

<!-- Akan muncul pesan kesalahan “SyntaxError: redeclaration of const recentPosts” -->
<script>
const recentPosts = json => { … };
</script>

Cara yang ke dua adalah dengan membuat nama fungsi yang tidak permanen dan bersifat acak. Cara di bawah ini memungkinkan kita untuk membuat fungsi global yang bisa berubah-ubah namanya setiap kali halaman dimuat, sehingga akan memperkecil kemungkinan pihak lain untuk mendeklarasikan fungsi gawai dengan nama yang sama:

let id = Math.floor(Math.random() * 1000),
    node = document.createElement('script');

window['recentPosts_' + id] = json => { … };

node.src = '/feeds/posts/summary?alt=json&callback=recentPosts_' + id;

document.head.appendChild(node);

Metode AJAX

Memuat data menggunakan AJAX relatif lebih praktis, walaupun dari segi sintaks mungkin akan terlihat rumit bagi orang-orang yang belum terbiasa. Kamu bisa menggunakan fungsi ini sebagai contekan selama kamu masih belum menguasai konsep AJAX. Dengan menggunakan AJAX, kamu tidak perlu menambahkan parameter callback karena data yang dimuat nantinya akan secara otomatis tertampung ke dalam parameter fungsi untuk menyatakan kesuksesan proses pemuatan data. Kamu bisa menggunakan XMLHttpRequest atau fetch. Pilih salah satu:

let xhr = new XMLHttpRequest;

// Buka tautan umpan dengan metode `GET`
xhr.open('GET', '/feeds/posts/summary?alt=json', true);

// Atur tipe respons sebagai JSON, bukan teks
xhr.responseType = 'json';

// Proses manipulasi data dilakukan di dalam acara `readystate`
xhr.addEventListener('readystate', function() {
    if (4 === this.readyState && 200 === this.status) {
        let json = this.response;
        // Ubah data `json` menjadi gawai mulai dari sini…
    }
}, false);

// Memulai permintaan data!
xhr.send();
// Memulai permintaan data!
fetch('/feeds/posts/summary?alt=json').then(response => {
    return response.json(); // Atur tipe respons sebagai JSON, bukan teks
}).then(json => {
    // Ubah data `json` menjadi gawai mulai dari sini…
});

Pakai jQuery juga bisa! Tapi akhir-akhir ini jQuery sudah ketinggalan zaman:

$.ajax({
    type: 'GET',
    url: '/feeds/posts/summary?alt=json',
    dataType: 'json'
}).done(function(json) {
    // Ubah data `json` menjadi gawai di sini…
});
$.get('/feeds/posts/summary?alt=json', function(json) {
    // Ubah data `json` menjadi gawai di sini…
}, 'json');

Mengeksekusi fungsi recentPosts() melalui respons AJAX dapat dilakukan dengan cara seperti ini:

xhr.addEventListener('readystate', function() {
    if (4 === this.readyState && 200 === this.status) {
        recentPosts(this.response);
    }
}, false);
fetch('/feeds/posts/summary?alt=json').then(response => response.json()).then(recentPosts);
$.ajax({
    type: 'GET',
    url: '/feeds/posts/summary?alt=json',
    dataType: 'json'
}).done(recentPosts);
$.get('/feeds/posts/summary?alt=json', recentPosts, 'json');

Kelebihan dari menggunakan metode AJAX adalah kamu tidak diharuskan untuk membuat fungsi gawai sebagai fungsi yang bersifat global, sehingga akan lebih ramah bagi lingkungan di luar gawai, serta dapat membebaskan fungsi tersebut dari kemungkinan-kemungkinan terjadinya konflik penamaan fungsi seperti yang telah Saya jelaskan sebelumnya pada metode pemuatan data umpan secara tradisional. Nama fungsi juga dapat dikompres dengan alat pengompres JavaScript tanpa memberikan pengaruh apa-apa pada hasil keluarannya:

(function() {
    function recentPosts(json) { … }
    fetch('/feeds/posts/summary?alt=json').then(response => response.json()).then(recentPosts);
})();

// Akan muncul pesan kesalahan “ReferenceError: recentPosts is not defined”
console.log(recentPosts);

Setiap metode tentu memiliki kekurangan dan kelebihannya masing-masing. Beberapa hal yang sudah Saya jabarkan di sini hanyalah sebagian kecilnya saja. Selebihnya mungkin dapat dijelaskan dengan contoh kasus. Jadi, mau pilih yang mana?

Labels: , , ,