Meningkatkan performa Aplikasi HTML5

Pengantar

HTML5 memberi kita alat yang hebat untuk meningkatkan tampilan visual aplikasi web. Hal ini terutama berlaku di ranah animasi. Namun, dengan kekuatan baru ini, tantangan baru juga muncul. Sebenarnya tantangan ini bukanlah hal baru dan terkadang masuk akal untuk bertanya kepada tetangga meja kerja Anda yang ramah, pemrogram Flash, bagaimana dia telah mengatasi hal serupa di masa lalu.

Bagaimanapun, ketika Anda bekerja di animasi, menjadi sangat penting bagi pengguna untuk menganggap animasi ini halus. Yang perlu kita sadari adalah bahwa kehalusan dalam animasi tidak bisa benar-benar dihasilkan hanya dengan meningkatkan frame per detik di luar ambang batas kognitif. Sayangnya, otak kita lebih pintar dari itu. Apa yang akan Anda pelajari adalah bahwa sebenarnya 30 frame animasi per detik (fps) jauh lebih baik dari 60 fps dengan hanya beberapa frame yang jatuh di tengah. Orang-orang tidak suka dengan perilaku kasar.

Artikel ini akan mencoba memberikan berbagai alat dan teknik untuk meningkatkan pengalaman aplikasi Anda.

Strategi

Kami tidak ingin menghilangkan keinginan Anda untuk membuat aplikasi visual yang mengagumkan dan memukau dengan HTML5.

Kemudian ketika Anda melihat bahwa kinerja bisa menjadi sedikit lebih baik, kembali ke sini dan baca bagaimana Anda bisa memperbaiki elemen-elemen aplikasi Anda. Tentu saja, hal itu dapat membantu melakukan beberapa hal dengan benar, tetapi jangan pernah menghambat Anda untuk menjadi produktif.

Fidelitas visual++ dengan HTML5

Akselerasi Hardware

Akselerasi perangkat keras merupakan tonggak pencapaian penting untuk kinerja render secara keseluruhan dalam browser. Skema umumnya adalah melimpahkan tugas yang biasanya dihitung oleh CPU utama ke unit pemrosesan grafis (GPU) di adaptor grafis komputer Anda. Hal ini dapat menghasilkan peningkatan performa yang besar dan juga dapat mengurangi konsumsi resource pada perangkat seluler.

Aspek dokumen Anda ini dapat dipercepat oleh GPU

  • Pengomposisian tata letak umum
  • Transisi CSS3
  • Transformasi 3D CSS3
  • Gambar Kanvas
  • Gambar 3D WebGL

Meskipun akselerasi kanvas dan WebGL adalah fitur dengan tujuan khusus yang mungkin tidak berlaku untuk aplikasi tertentu Anda, tiga aspek pertama tersebut dapat membantu mempercepat setiap aplikasi.

Apa yang bisa dipercepat?

Akselerasi GPU bekerja dengan mengalihkan tugas yang terdefinisi dengan baik dan spesifik ke hardware dengan tujuan khusus. Skema umumnya adalah dokumen Anda dibagi menjadi beberapa "lapisan" yang tidak sama dengan aspek halaman yang dipercepat. Lapisan ini dirender menggunakan pipeline render tradisional. GPU kemudian digunakan untuk menggabungkan lapisan ke satu halaman yang menerapkan "efek" yang dapat dipercepat dengan cepat. Hasil yang mungkin terjadi adalah objek yang dianimasikan di layar tidak memerlukan satu "tata letak ulang" halaman saat animasi terjadi.

Yang perlu Anda hilangkan adalah Anda harus memudahkan mesin rendering untuk mengidentifikasi kapan ia bisa menerapkan keajaiban akselerasi GPU-nya. Perhatikan contoh berikut:

Meskipun ini bekerja, browser tidak benar-benar tahu bahwa Anda melakukan sesuatu yang seharusnya dianggap sebagai animasi yang mulus oleh manusia. Pertimbangkan apa yang terjadi ketika Anda memperoleh tampilan visual yang sama menggunakan transisi CSS3:

Cara browser menerapkan animasi ini sepenuhnya disembunyikan dari developer. Hal ini pada akhirnya berarti browser dapat menerapkan trik seperti akselerasi GPU untuk mencapai sasaran yang ditentukan.

Ada dua tanda command line yang berguna bagi Chrome untuk membantu men-debug akselerasi GPU:

  1. --show-composited-layer-borders menampilkan batas merah di sekitar elemen yang dimanipulasi di level GPU. Cocok untuk mengonfirmasi bahwa manipulasi Anda terjadi di dalam lapisan GPU.
  2. --show-paint-rects semua perubahan non-GPU digambar dan tindakan ini akan menampilkan batas terang di sekitar semua area yang di-rekonstruksi. Anda dapat melihat cara browser mengoptimalkan area paint.

Safari memiliki tanda runtime serupa yang dijelaskan di sini.

Transisi CSS3

Transisi CSS membuat animasi gaya menjadi mudah bagi semua orang, tetapi juga merupakan fitur performa yang cerdas. Karena transisi CSS dikelola oleh browser, maka ketelitian animasinya bisa sangat meningkat, dan dalam banyak kasus, akselerasi perangkat keras menjadi lebih cepat. Saat ini WebKit (Chrome, Safari, iOS) memiliki transformasi CSS dengan akselerasi hardware, tetapi juga segera hadir di browser dan platform lain.

Anda dapat menggunakan peristiwa transitionEnd untuk menuliskan skrip ini ke dalam kombinasi yang efektif, meskipun saat ini, merekam semua peristiwa akhir transisi yang didukung berarti menonton webkitTransitionEnd transitionend oTransitionEnd.

Banyak library kini memperkenalkan API animasi yang memanfaatkan transisi jika ada dan kembali ke animasi gaya DOM standar. scripty2, transisi YUI, jQuery animate enhanced.

Terjemahan CSS3

Saya yakin Anda pernah menganimasikan posisi x/y dari suatu elemen di seluruh laman sebelumnya. Anda mungkin memanipulasi properti kiri dan atas gaya inline. Dengan transformasi 2D, kita dapat menggunakan fungsi translate() untuk mereplikasi perilaku ini.

Kita dapat menggabungkan ini dengan animasi DOM untuk menggunakan hal terbaik

<div style="position:relative; height:120px;" class="hwaccel">

  <div style="padding:5px; width:100px; height:100px; background:papayaWhip;
              position:absolute;" id="box">
  </div>
</div>

<script>
document.querySelector('#box').addEventListener('click', moveIt, false);

function moveIt(evt) {
  var elem = evt.target;

  if (Modernizr.csstransforms && Modernizr.csstransitions) {
    // vendor prefixes omitted here for brevity
    elem.style.transition = 'all 3s ease-out';
    elem.style.transform = 'translateX(600px)';

  } else {
    // if an older browser, fall back to jQuery animate
    jQuery(elem).animate({ 'left': '600px'}, 3000);
  }
}
</script>

Kita menggunakan Modernizr untuk pengujian fitur untuk Transformasi 2D CSS dan Transisi CSS, jika demikian kita akan menggunakan terjemahan untuk menggeser posisi. Jika ini dianimasikan menggunakan transisi, ada kemungkinan besar browser dapat mempercepatnya dengan perangkat keras. Untuk memberikan dorongan lain pada browser ke arah yang benar, kita akan menggunakan "butir CSS ajaib" dari atas.

Jika browser kita kurang mampu, kita akan kembali ke jQuery untuk memindahkan elemen kita. Anda dapat menggunakan plugin polyfill jQuery Transform oleh Louis-Remi Babe untuk membuat semuanya menjadi otomatis.

window.requestAnimationFrame

requestAnimationFrame diperkenalkan oleh Mozilla dan diiterasi oleh WebKit dengan tujuan memberi Anda API native untuk menjalankan animasi, baik berbasis DOM/CSS atau di <canvas> atau WebGL. Browser dapat mengoptimalkan beberapa animasi serentak menjadi satu siklus perubahan posisi/geometri dan penggambaran ulang, sehingga menghasilkan animasi dengan fidelitas yang lebih tinggi. Misalnya, animasi berbasis JS yang disinkronkan dengan transisi CSS atau SVG SMIL. Selain itu, jika Anda menjalankan loop animasi pada tab yang tidak terlihat, browser tidak akan membiarkannya berjalan, yang berarti lebih sedikit penggunaan CPU, GPU, dan memori, sehingga menyebabkan masa pakai baterai yang lebih lama.

Untuk detail selengkapnya tentang cara dan alasan menggunakan requestAnimationFrame, lihat artikel Paul Irish requestAnimationFrame untuk animasi cerdas.

Pembuatan profil

Setelah Anda menemukan bahwa kecepatan aplikasi dapat ditingkatkan, sekarang saatnya mendalami pembuatan profil untuk mengetahui bagian dalam pengoptimalan yang dapat menghasilkan manfaat terbesar. Pengoptimalan sering kali akan berdampak negatif pada pemeliharaan kode sumber Anda dan, dengan demikian, hanya boleh diterapkan jika diperlukan. Pembuatan profil memberi tahu Anda bagian kode mana yang akan menghasilkan manfaat terbesar jika performanya ditingkatkan.

Pembuatan Profil JavaScript

Profiler JavaScript memberi Anda ringkasan tentang performa aplikasi pada level fungsi JavaScript dengan mengukur waktu yang diperlukan untuk mengeksekusi setiap fungsi individual dari awal hingga akhir.

Waktu eksekusi kotor suatu fungsi adalah waktu keseluruhan yang diperlukan untuk mengeksekusinya dari atas ke bawah. Waktu eksekusi bersih adalah waktu eksekusi kotor dikurangi waktu yang diperlukan untuk menjalankan fungsi yang dipanggil dari fungsi.

Beberapa fungsi lebih sering dipanggil daripada yang lain. Profiler biasanya memberi Anda waktu yang diperlukan untuk menjalankan semua pemanggilan, serta waktu eksekusi rata-rata, minimum, dan maksimum.

Untuk mengetahui detail selengkapnya, lihat dokumentasi Chrome Dev Tools tentang pembuatan profil.

DOM

Performa JavaScript memiliki pengaruh yang kuat terhadap seberapa dinamis dan responsif aplikasi Anda akan terasa. Penting untuk dipahami bahwa, meskipun profiler JavaScript mengukur waktu eksekusi JavaScript, profiler tersebut juga secara tidak langsung mengukur waktu yang dihabiskan untuk melakukan operasi DOM. Operasi DOM ini sering kali menjadi inti dari masalah performa Anda.

function drawArray(array) {
  for(var i = 0; i < array.length; i++) {
    document.getElementById('test').innerHTML += array[i]; // No good :(
  }
}

Mis. dalam kode di atas hampir tidak ada waktu yang dihabiskan untuk mengeksekusi JavaScript yang sebenarnya. Sangat mungkin fungsi drawArray akan muncul di profil Anda karena berinteraksi dengan DOM dengan cara yang sangat sia-sia.

Tips dan Trik

Fungsi Anonim

Fungsi anonim tidak mudah dibuat profil karena pada dasarnya tidak memiliki nama yang akan ditampilkan di profiler. Ada dua cara untuk mengatasi hal ini:

$('.stuff').each(function() { ... });

tulis ulang menjadi:

$('.stuff').each(function workOnStuff() { ... });

Tidak diketahui bahwa JavaScript mendukung penamaan ekspresi fungsi. Tindakan ini akan membuatnya muncul dengan sempurna di profiler. Ada satu masalah dengan solusi ini: Ekspresi bernama sebenarnya menempatkan nama fungsi ke dalam cakupan leksikal saat ini. Ini mungkin mengacaukan simbol lain, jadi berhati-hatilah.

Membuat profil fungsi panjang

Bayangkan Anda memiliki fungsi yang panjang dan Anda menduga bahwa sebagian kecil dari fungsi tersebut mungkin menjadi penyebab masalah performa Anda. Ada dua cara untuk mengetahui bagian mana yang bermasalah:

  1. Metode yang benar: Faktorkan ulang kode Anda agar tidak menyertakan fungsi yang panjang.
  2. Metode evil get-things-done: tambahkan pernyataan dalam bentuk fungsi panggilan mandiri bernama ke kode Anda. Jika Anda cukup berhati-hati, tindakan ini tidak akan mengubah semantik dan membuat bagian-bagian dari fungsi Anda muncul sebagai fungsi tersendiri di profiler: js function myLongFunction() { ... (function doAPartOfTheWork() { ... })(); ... } Jangan lupa menghapus fungsi tambahan ini setelah pembuatan profil selesai; atau bahkan gunakan sebagai titik awal untuk memfaktorkan ulang kode Anda.

Pembuatan Profil DOM

Alat pengembangan Chrome Web Inspector terbaru berisi "Tampilan Linimasa" baru yang menunjukkan linimasa tindakan tingkat rendah yang dilakukan oleh browser. Anda dapat menggunakan informasi ini untuk mengoptimalkan operasi DOM Anda. Anda harus berupaya mengurangi jumlah "tindakan" yang harus dilakukan browser selagi kode dieksekusi.

Tampilan {i>timeline<i} dapat menghasilkan informasi yang sangat banyak. Oleh karena itu, Anda harus mencoba membuat kasus pengujian minimal yang dapat dijalankan secara independen.

Pembuatan Profil DOM

Gambar di atas menunjukkan output tampilan linimasa untuk skrip yang sangat sederhana. Panel kiri menunjukkan operasi yang dilakukan oleh browser dalam urutan kronis, sedangkan linimasa di panel kanan menunjukkan waktu sebenarnya yang dihabiskan oleh setiap operasi.

Info selengkapnya tentang tampilan linimasa. Alat alternatif untuk pembuatan profil di Internet Explorer adalah DynaTrace Ajax Edition.

Strategi Pembuatan Profil

Pilih aspek tertentu

Jika Anda ingin membuat profil aplikasi, cobalah untuk menyoroti aspek fungsinya yang mungkin memicu kelambatan sedekat mungkin. Kemudian, coba jalankan profil yang hanya menjalankan bagian kode yang relevan dengan aspek aplikasi Anda ini. Hal ini akan membuat data pembuatan profil lebih mudah ditafsirkan karena tidak dicampur dengan jalur kode yang tidak terkait dengan masalah Anda yang sebenarnya. Contoh yang baik untuk aspek individual dari aplikasi Anda dapat berupa:

  1. Waktu mulai (mengaktifkan profiler, memuat ulang aplikasi, menunggu hingga inisialisasi selesai, menghentikan profiler.
  2. Mengklik tombol dan animasi berikutnya (start profiler, tombol klik, menunggu hingga animasi selesai, menghentikan profiler).
Pembuatan Profil GUI

Mengeksekusi hanya pada bagian aplikasi yang tepat mungkin lebih sulit dalam program GUI dibandingkan saat Anda mengoptimalkan, misalnya, pelacak sinar pada mesin 3D Anda. Saat Anda, misalnya, ingin membuat profil hal-hal yang terjadi saat Anda mengklik tombol, Anda mungkin memicu peristiwa pengarahan mouse yang tidak terkait sepanjang proses yang membuat hasil Anda kurang konklusif. Hindari hal tersebut :)

Antarmuka Programatik

Ada juga antarmuka programatik untuk mengaktifkan debugger. Hal ini memungkinkan kontrol yang akurat atas kapan pembuatan profil dimulai dan kapan profil berakhir.

Mulai pembuatan profil dengan:

console.profile()

Hentikan pembuatan profil dengan:

console.profileEnd()

Pengulangan

Ketika melakukan pembuatan profil, pastikan Anda benar-benar dapat mereproduksi hasil. Dengan begitu, Anda akan dapat mengetahui apakah pengoptimalan Anda benar-benar memberikan hasil lebih baik. Selain itu, pembuatan profil tingkat fungsi dilakukan dalam konteks seluruh komputer Anda. Ini bukan ilmu pasti. Profil individu yang berjalan dapat dipengaruhi oleh banyak hal lain yang terjadi di komputer Anda:

  1. Timer tidak terkait di aplikasi Anda sendiri yang terpicu saat Anda mengukur sesuatu yang lain.
  2. Pembersih sampah sedang melakukan pekerjaannya.
  3. Tab lain di browser Anda yang melakukan kerja keras di thread pengoperasian yang sama.
  4. Program lain di komputer Anda menghabiskan CPU sehingga membuat aplikasi lebih lambat.
  5. Perubahan tiba-tiba pada medan gravitasi bumi.

Masuk akal juga untuk mengeksekusi jalur kode yang sama beberapa kali dalam satu sesi pembuatan profil. Dengan cara ini Anda mengurangi pengaruh faktor-faktor di atas dan bagian-bagian yang lambat dapat terlihat lebih jelas.

Ukur, tingkatkan, ukur

Ketika mengidentifikasi titik yang lambat dalam program, coba pikirkan cara untuk meningkatkan perilaku eksekusi. Setelah Anda mengubah kode, buat profil lagi. Jika Anda puas dengan hasilnya, lanjutkan, jika Anda tidak melihat peningkatan, Anda mungkin harus membatalkan perubahan dan tidak membiarkannya dalam "karena itu tidak akan berdampak buruk".

Strategi Pengoptimalan

Meminimalkan interaksi DOM

Tema umum untuk meningkatkan kecepatan aplikasi klien web adalah meminimalkan interaksi DOM. Meskipun kecepatan mesin JavaScript telah meningkat secara urutan, mengakses DOM belum menjadi lebih cepat pada laju yang sama. Hal ini juga karena alasan praktis yang tidak akan pernah terjadi (hal-hal seperti tata letak dan menggambar hal-hal di layar memang membutuhkan waktu).

Node DOM Cache

Setiap kali Anda mengambil simpul atau daftar simpul dari DOM, cobalah untuk memikirkan apakah Anda mungkin dapat menggunakannya kembali dalam komputasi berikutnya (atau bahkan hanya iterasi loop berikutnya). Selama Anda tidak benar-benar menambahkan atau menghapus node di area yang relevan, hal ini sering kali terjadi.

Sebelum:

function getElements() {
  return $('.my-class');
}

Sesudah:

var cachedElements;
function getElements() {
  if (cachedElements) {
    return cachedElements;
  }
  cachedElements = $('.my-class');
  return cachedElements;
}

Nilai Atribut Cache

Dengan cara yang sama Anda meng-cache node DOM, Anda juga dapat meng-cache nilai atribut. Bayangkan Anda menganimasikan atribut gaya node. Jika mengetahui bahwa Anda (seperti dalam bagian kode tersebut) adalah satu-satunya yang akan menyentuh atribut tersebut, Anda dapat meng-cache nilai terakhir pada setiap iterasi sehingga Anda tidak perlu membacanya berulang kali.

Sebelum:

setInterval(function() {
  var ele = $('#element');
  var left = parseInt(ele.css('left'), 10);
  ele.css('left', (left + 5) + 'px');
}, 1000 / 30);

Sesudah: js var ele = $('#element'); var left = parseInt(ele.css('left'), 10); setInterval(function() { left += 5; ele.css('left', left + 'px'); }, 1000 / 30);

Memindahkan Manipulasi DOM dari Loop

Pengulangan sering kali menjadi titik panas untuk pengoptimalan. Coba pikirkan cara untuk memisahkan pemrosesan angka yang sebenarnya untuk bekerja dengan DOM. Sering kali penghitungan dapat dilakukan, lalu setelah selesai, menerapkan semua hasil sekaligus.

Sebelum:

document.getElementById('target').innerHTML = '';
for(var i = 0; i < array.length; i++) {
  var val = doSomething(array[i]);
  document.getElementById('target').innerHTML += val;
}

Sesudah:

var stringBuilder = [];
for(var i = 0; i < array.length; i++) {
  var val = doSomething(array[i]);
  stringBuilder.push(val);
}
document.getElementById('target').innerHTML = stringBuilder.join('');

Menggambar Ulang dan Mengubah posisi/{i>Reflow<i}

Seperti yang telah dibahas sebelumnya, mengakses DOM relatif lambat. Menjadi sangat lambat saat kode Anda membaca nilai yang harus dihitung ulang karena kode Anda baru saja memodifikasi sesuatu yang terkait dalam DOM. Dengan demikian, harus dihindari untuk menggabungkan akses membaca dan menulis ke DOM. Idealnya, kode Anda harus selalu dikelompokkan dalam dua fase:

  • Fase 1: Membaca nilai DOM yang diperlukan untuk kode Anda
  • Tahap 2: Mengubah DOM

Cobalah untuk tidak memprogram pola seperti:

  • Fase 1: Membaca nilai DOM
  • Tahap 2: Mengubah DOM
  • Tahap 3: Baca selengkapnya
  • Fase 4: Ubah DOM di tempat lain.

Sebelum:

function paintSlow() {
  var left1 = $('#thing1').css('left');
  $('#otherThing1').css('left', left);
  var left2 = $('#thing2').css('left');
  $('#otherThing2').css('left', left);
}

Sesudah:

function paintFast() {
  var left1 = $('#thing1').css('left');
  var left2 = $('#thing2').css('left');
  $('#otherThing1').css('left', left);
  $('#otherThing2').css('left', left);
}

Saran ini harus dipertimbangkan untuk tindakan yang terjadi dalam satu konteks eksekusi JavaScript. (misalnya, dalam pengendali peristiwa, dalam pengendali interval, atau saat menangani respons ajax.)

Mengeksekusi fungsi paintSlow() dari atas akan membuat gambar ini:

paintSlow()

Beralih ke implementasi yang lebih cepat akan menghasilkan gambar ini:

Penerapan yang lebih cepat

Gambar-gambar ini menunjukkan bahwa penataan ulang cara kode Anda mengakses DOM bisa sangat meningkatkan performa render. Dalam hal ini, kode awal harus menghitung ulang gaya dan tata letak laman dua kali untuk membuat hasil yang sama. Pengoptimalan yang serupa dapat diterapkan pada semua kode "dunia nyata" dan memberikan beberapa hasil yang sangat signifikan.

Baca selengkapnya: Rendering: repaint, reflow/relayout, restyle oleh Stoyan Stefanov

Menggambar Ulang dan Event Loop

Eksekusi JavaScript di browser mengikuti model "Event Loop". Secara default, browser dalam status "tidak ada aktivitas". Status ini dapat terganggu oleh peristiwa dari interaksi pengguna atau hal-hal seperti timer JavaScript atau callback Ajax. Setiap kali JavaScript berjalan pada titik gangguan tersebut, browser biasanya akan menunggu hingga selesai hingga menggambar ulang layar (Mungkin ada pengecualian untuk JavaScript yang berjalan sangat lama atau dalam kasus seperti kotak peringatan yang secara efektif mengganggu eksekusi JavaScript).

Konsekuensi

  1. Jika siklus animasi JavaScript Anda memerlukan waktu lebih dari 1/30 detik untuk dijalankan, Anda tidak akan dapat membuat animasi yang mulus karena browser tidak akan di-repaint selama eksekusi JS. Jika berharap dapat menangani peristiwa pengguna juga, Anda harus jauh lebih cepat.
  2. Kadang-kadang berguna untuk menunda beberapa tindakan JavaScript hingga beberapa saat kemudian. Misalnya, setTimeout(function() { ... }, 0) Hal ini secara efektif memberi tahu browser untuk mengeksekusi callback segera setelah loop peristiwa tidak ada aktivitas lagi (secara efektif beberapa browser akan menunggu setidaknya 10 md). Perlu diketahui bahwa tindakan ini akan menghasilkan dua siklus eksekusi JavaScript yang waktunya berdekatan. Keduanya dapat memicu pengecatan ulang layar yang mungkin menggandakan waktu keseluruhan yang dihabiskan untuk mengecat. Apakah ini benar-benar memicu dua paint bergantung pada heuristik di browser.

Versi reguler:

function paintFast() {
  var height1 = $('#thing1').css('height');
  var height2 = $('#thing2').css('height');
  $('#otherThing1').css('height', '20px');
  $('#otherThing2').css('height', '20px');
}
Menggambar Ulang dan Event Loop

Mari tambahkan beberapa penundaan:

function paintALittleLater() {
  var height1 = $('#thing1').css('height');
  var height2 = $('#thing2').css('height');
  $('#otherThing1').css('height', '20px');
  setTimeout(function() {
    $('#otherThing2').css('height', '20px');
  }, 10)
}
Penundaan

Versi yang tertunda menunjukkan bahwa browser melakukan penggambaran dua kali meskipun dua perubahan pada halaman hanya 1/100 dari bagian detik.

Inisialisasi Lambat

Pengguna menginginkan aplikasi web yang dimuat dengan cepat dan terasa responsif. Namun, pengguna memiliki ambang batas yang berbeda untuk hal yang mereka anggap lambat bergantung pada tindakan yang mereka lakukan. Misalnya, aplikasi tidak boleh melakukan banyak komputasi pada peristiwa pengarahan mouse karena hal ini dapat menciptakan pengalaman pengguna yang buruk saat pengguna terus menggerakkan mouse. Namun, pengguna terbiasa menerima sedikit penundaan setelah mereka mengklik tombol.

Karena itu, mungkin masuk akal untuk memindahkan kode inisialisasi Anda agar dieksekusi selambat mungkin (mis., saat pengguna mengklik tombol yang mengaktifkan komponen tertentu dari aplikasi Anda).

Sebelum: js var things = $('.ele > .other * div.className'); $('#button').click(function() { things.show() });

Sesudah: js $('#button').click(function() { $('.ele > .other * div.className').show() });

Delegasi Acara

Menyebarkan pengendali peristiwa di seluruh halaman mungkin memerlukan waktu yang relatif lama dan juga bisa merepotkan setelah elemen diganti secara dinamis, yang kemudian memerlukan penyertaan kembali pengendali peristiwa ke elemen baru.

Solusi dalam kasus ini adalah menggunakan teknik yang disebut delegasi peristiwa. Alih-alih melampirkan pengendali peristiwa individual ke elemen, sifat gelembung dari banyak peristiwa browser digunakan dengan benar-benar melampirkan pengendali peristiwa ke node induk dan memeriksa node target peristiwa untuk melihat apakah peristiwa tersebut menarik.

Dalam jQuery, hal ini dapat dengan mudah dinyatakan sebagai:

$('#parentNode').delegate('.button', 'click', function() { ... });

Kapan sebaiknya tidak menggunakan delegasi acara

Terkadang hal yang sebaliknya bisa terjadi: Anda menggunakan delegasi acara dan mengalami masalah performa. Pada dasarnya delegasi peristiwa memungkinkan waktu inisialisasi kompleksitas konstanta. Namun, harga pemeriksaan apakah suatu peristiwa menarik harus dibayar untuk setiap panggilan peristiwa tersebut. Cara ini mungkin mahal, terutama untuk peristiwa yang sering terjadi seperti "mouseover" atau bahkan "mousemove".

Masalah Umum dan Solusinya

Pekerjaan yang saya lakukan di $(document).ready memakan waktu lama

Saran pribadi Malte: Jangan pernah melakukan apa pun di $(document).ready. Coba kirimkan dokumen Anda dalam bentuk akhirnya. Oke, Anda diizinkan untuk mendaftarkan pemroses peristiwa, tetapi hanya menggunakan pemilih ID dan/atau menggunakan delegasi peristiwa. Untuk peristiwa mahal seperti "mousemove", tunda pendaftaran hingga diperlukan (peristiwa pengarahan mouse pada elemen yang relevan).

Dan jika Anda benar-benar perlu melakukan sesuatu, seperti membuat permintaan Ajax untuk mendapatkan data aktual, lalu tampilkan animasi yang bagus; Anda mungkin ingin menyertakan animasi sebagai URI data jika itu adalah GIF animasi atau yang serupa.

Karena saya menambahkan film Flash ke halaman, semuanya sangat lambat

Menambahkan Flash ke halaman akan selalu sedikit memperlambat rendering karena tata letak akhir jendela harus "dinegosiasikan" antara browser dan plugin Flash. Jika Anda tidak dapat sepenuhnya menghindari penempatan Flash di halaman, pastikan Anda menyetel parameter Flash "wmode" ke nilai "window" (yang merupakan default). Tindakan ini akan menonaktifkan kemampuan untuk menggabungkan elemen HTML dan Flash (Anda tidak akan dapat melihat elemen HTML yang berada di atas film Flash dan film Flash Anda tidak dapat transparan). Hal ini mungkin menjadi ketidaknyamanan, tetapi akan meningkatkan performa Anda secara drastis. Misalnya, lihat cara youtube.com mencegah penempatan lapisan di atas pemutar film utama dengan cermat.

Saya menyimpan sesuatu ke localStorage, sekarang aplikasi saya tersendat

Menulis ke localStorage adalah operasi sinkron yang melibatkan pengerjaan hard disk Anda. Anda tidak ingin melakukan operasi sinkron "berjalan lama" saat melakukan animasi. Pindahkan akses ke localStorage ke suatu tempat dalam kode tempat Anda yakin bahwa pengguna sedang tidak ada aktivitas dan tidak ada animasi yang aktif.

Pembuatan profil menunjuk ke pemilih jQuery yang sangat lambat

Pertama, Anda ingin memastikan bahwa pemilih dapat dijalankan melalui document.querySelectorAll. Anda dapat mengujinya di konsol JavaScript. Jika ada pengecualian, tulis ulang pemilih Anda agar tidak menggunakan ekstensi khusus framework JavaScript. Hal ini akan mempercepat pemilih di browser modern sebesar urutan magnitudonya.

Jika tidak membantu atau jika Anda juga ingin cepat menggunakan browser modern, ikuti panduan ini:

  • Jelaskan sedetail mungkin di sisi kanan pemilih.
  • Gunakan nama tag yang tidak sering digunakan sebagai bagian pemilih paling kanan.
  • Jika tidak ada yang membantu, pertimbangkan untuk menulis ulang semuanya agar Anda dapat menggunakan pemilih ID

Semua manipulasi DOM ini membutuhkan waktu lama

Sekumpulan penyisipan, penghapusan, dan pembaruan simpul DOM bisa sangat lambat. Umumnya, hal ini dapat dioptimalkan dengan membuat string html yang besar dan menggunakan domNode.innerHTML = newHTML untuk menggantikan konten lama. Perhatikan bahwa hal ini mungkin sangat buruk dalam hal pemeliharaan dan dapat membuat link memori di IE, jadi berhati-hatilah.

Masalah umum lainnya adalah kode inisialisasi Anda mungkin menghasilkan banyak HTML. Misalnya, plugin jQuery yang mengubah kotak pilihan menjadi sekumpulan div karena desain inilah yang diinginkan orang jika mengabaikan praktik terbaik UX. Jika Anda ingin halaman cepat, jangan pernah melakukannya. Sebagai gantinya, kirim semua markup dari sisi server dalam bentuk akhirnya. Sekali lagi, ini memiliki banyak masalah, jadi pikirkan dengan keras apakah kecepatan sepadan dengan komprominya.

Alat

  1. JSPerf - Cuplikan kecil tolok ukur pada JavaScript
  2. Firebug - Untuk pembuatan profil di Firefox
  3. Google Chrome Developer Tools (Tersedia sebagai WebInspector di Safari)
  4. DOM Monster - Untuk mengoptimalkan performa DOM
  5. DynaTrace Ajax Edition - Untuk pengoptimalan paint dan pembuatan profil di Internet Explorer

Bacaan lebih lanjut

  1. Kecepatan Google
  2. Paul Irish tentang Performa jQuery
  3. Performa JavaScript Ekstrem (Slide Slide)