5 poin oleh GN⁺ 2023-11-12 | 1 komentar | Bagikan ke WhatsApp
  • Jika Anda bisa menggunakan developer tools browser pada tingkat menengah ke atas, conditional breakpoint dapat diperluas dari sekadar kondisi berhenti menjadi alat untuk logging, tracing, mengubah state, dan mengukur waktu
  • Jika Console API seperti console.log, console.count, console.trace, dan console.time dimasukkan ke breakpoint atau Watch Pane, Anda dapat merekam alur dan state tanpa menghentikan eksekusi
  • Dengan menggabungkan jumlah argumen fungsi, waktu, nilai CSS terhitung, jumlah eksekusi, sampling acak, dan boolean global, Anda bisa mengontrol momen berhenti dengan jauh lebih presisi
  • monitor, debug, copy, $0, getEventListeners, dan monitorEvents di Chrome membantu menangani pemanggilan fungsi, DOM, event, dan pekerjaan clipboard dengan cepat dari konsol
  • Pada layar yang DOM-nya terus berubah karena JS atau event pengguna, pause JS, setTimeout(debugger), snapshot DOM, dan pemantauan fokus sangat berguna khususnya untuk debugging HTML/CSS

Memperluas conditional breakpoint menjadi alat debugging

  • Conditional breakpoint dapat berisi bukan hanya kondisi true/false, tetapi juga ekspresi JavaScript yang memiliki efek samping

  • Dengan memanfaatkannya, breakpoint biasa bisa dipakai seperti alat logging, tracing, perubahan state, dan pengukuran waktu

  • Logpoint dan tracepoint

    • Jika Anda memanggil console.log di conditional breakpoint, itu akan bertindak seperti logpoint yang meninggalkan nilai di konsol tanpa menghentikan eksekusi
    • Dengan console.count, Anda juga bisa menghitung berapa kali baris tersebut dieksekusi
    • Per pembaruan Mei 2020, browser utama mendukung logpoint/tracepoint secara langsung
  • Menggunakan Console API di Watch Pane

    • Anda juga bisa memasukkan ekspresi seperti console.log ke Watch Pane
    • Setiap kali aplikasi berhenti di debugger, Anda bisa mengambil snapshot localStorage dengan console.table(localStorage)
    • Jika breakpoint perubahan DOM dipakai bersama ekspresi Watch, Anda bisa menyimpan snapshot setelah perubahan subtree DOM ke dalam array
    (window.doms = window.doms || []).push(document.documentElement.outerHTML)
    
    • Breakpoint perubahan DOM tidak bisa dibuat agar tidak menghentikan eksekusi
  • Melacak call stack

    • Saat ada fungsi untuk menampilkan loading spinner dan fungsi untuk menyembunyikannya, dan Anda mencari masalah ketika hanya pemanggilan tampil yang tersisa, Anda bisa menaruh console.trace di conditional breakpoint
    • Dengan mengeklik pemanggil pada stack trace terakhir dari fungsi tampil, Anda bisa pindah ke lokasi pemanggilan tersebut
  • Mengubah perilaku program saat berjalan

    • Dengan menimpa argumen fungsi di ekspresi conditional breakpoint, Anda bisa langsung mengubah perilaku program di dalam browser
    • Misalnya, Anda bisa mengubah nilai id pada fungsi getPerson
    • Ekspresi seperti id=1 akan dievaluasi sebagai true sehingga debugger berhenti; jika tidak ingin berhenti, Anda bisa menambahkan , false
  • Pengukuran performa cepat

    • Karena waktu evaluasi conditional breakpoint ikut tercampur, ini tidak cocok untuk profiling performa yang presisi
    • Saat Anda butuh pengukuran cepat, Anda bisa menaruh console.time('label') pada kondisi di titik awal dan console.timeEnd('label') pada kondisi di titik akhir untuk mencatat waktu eksekusi ke konsol

Membuat kondisi breakpoint lebih presisi

  • Memanfaatkan jumlah argumen fungsi

    • Jika Anda ingin berhenti hanya saat fungsi saat ini dipanggil dengan 3 argumen, Anda bisa memakai kondisi berikut
    arguments.callee.length === 3
    
    • Ini berguna pada fungsi overload yang memiliki argumen opsional
    • Jika Anda ingin berhenti hanya ketika jumlah argumen yang didefinisikan berbeda dari jumlah argumen yang benar-benar dikirim, gunakan kondisi berikut
    (arguments.callee.length) != arguments.length
    
    • Ini membantu menemukan bug di lokasi pemanggilan fungsi
  • Kondisi berbasis waktu

    • Jika Anda tidak ingin berhenti sebelum 5 detik berlalu setelah halaman dimuat, gunakan kondisi berikut
    performance.now() > 5000
    
    • Ini cocok jika Anda hanya tertarik pada breakpoint setelah initial page load
    • Jika Anda ingin breakpoint tidak berhenti selama 5 detik berikutnya setelah diatur, lalu mulai berhenti sesudahnya, Anda bisa menyimpan waktu acuan di variabel global
    window.baseline = window.baseline || Date.now(),
    (Date.now() - window.baseline) > 5000
    
    • Anda bisa memulai ulang penghitung dari konsol dengan window.baseline = Date.now()
  • Kondisi berbasis status CSS

    • Anda bisa berhenti berdasarkan nilai CSS terhitung
    • Misalnya, jika Anda ingin berhenti hanya saat warna latar document.body merah, gunakan kondisi berikut
    window.getComputedStyle(document.body).backgroundColor === "rgb(255,0,0)"
    
  • Jumlah eksekusi dan sampling

    • Dengan menaikkan penghitung setiap kali baris dieksekusi, Anda bisa berhenti sekali setiap dua kali
    window.counter = (window.counter || 0) + 1, window.counter % 2 === 0
    
    • Jika Anda ingin berhenti hanya 1 dari 10 kali dengan sampling acak, gunakan kondisi berikut
    Math.random() < 0.1
    
  • Jangan pernah berhenti di lokasi tertentu

    • Di Chrome, klik kanan gutter lalu pilih “Never Pause Here” untuk membuat conditional breakpoint yang selalu bernilai false, sehingga tidak berhenti di baris itu
    • Ini bisa dipakai untuk mengecualikan baris tertentu dari breakpoint XHR atau mengabaikan exception tertentu
  • Memberi ID instance secara otomatis

    • Anda bisa menaruh conditional breakpoint di constructor kelas untuk menyimpan setiap instance ke dalam array
    (window.instances = window.instances || []).push(this)
    
    • ID unik dari instance tertentu bisa dicek lewat indeks array
    window.instances.indexOf(instance)
    
  • Toggle global untuk breakpoint

    • Satu atau lebih conditional breakpoint bisa dikendalikan dengan boolean global
    • Anda bisa mengubahnya langsung dari konsol, mengubahnya dari breakpoint lain, atau mengubahnya lewat timer
    window.enableBreakpoints = true
    setTimeout(() => (window.enableBreakpoints = true), 5000)
    

Melacak pemanggilan fungsi dan kelas

  • Memantau pemanggilan method kelas

    • Dengan metode command line monitor di Chrome, Anda bisa melacak pemanggilan method kelas dengan mudah
    • Jika Anda ingin melihat pemanggilan method untuk semua instance dari kelas Dog, Anda bisa menerapkan monitor ke semua properti milik prototype
    var p = Dog.prototype;
    Object.getOwnPropertyNames(p).forEach((k) => monitor(p[k]));
    
    • Konsol akan menampilkan informasi pemanggilan seperti function bark called with arguments: 2
    • Jika Anda ingin berhenti saat dipanggil alih-alih hanya meninggalkan log, gunakan debug sebagai ganti monitor
  • Melacak kelas dari instance tertentu

    • Jika Anda tidak tahu nama kelasnya tetapi punya instance, Anda bisa memantaunya dengan cara yang sama lewat prototype dari constructor
    var p = instance.constructor.prototype;
    Object.getOwnPropertyNames(p).forEach((k) => monitor(p[k]));
    
    • Ini berguna saat membuat fungsi yang bekerja untuk instance sembarang tanpa terikat ke kelas tertentu
  • Debugging tepat sebelum fungsi dipanggil dari konsol

    • Sebelum memanggil fungsi yang ingin Anda debug dari konsol, jalankan debugger, lalu lakukan Step into pada pemanggilan fungsi berikutnya untuk masuk ke implementasi fungsi
    debugger; fn(1);
    
    • Ini berguna jika Anda malas mencari lokasi definisi fungsi atau ketika fn diikat secara dinamis sehingga Anda tidak tahu lokasi sumbernya
    • Di Chrome, Anda juga bisa memanggil debug(fn) agar eksekusi berhenti di dalam fn setiap kali ia dipanggil

Debugging perubahan URL dan pembacaan properti

  • Berhenti sebelum routing SPA

    • Jika Anda ingin berhenti tepat sebelum single-page application mengubah URL, Anda bisa menghubungkan fungsi yang berisi debugger ke history.pushState, history.replaceState, window.onhashchange, dan window.onpopstate
    const dbg = () => {
      debugger;
    };
    history.pushState = dbg;
    history.replaceState = dbg;
    window.onhashchange = dbg;
    window.onpopstate = dbg;
    
    • Versi dbg ini tidak mencakup implementasi yang menghentikan sambil tetap menjaga navigasi agar tidak rusak
    • Jika window.location.replace atau window.location.assign dipanggil langsung, halaman akan di-unload segera setelah penugasan, jadi cara ini tidak bisa menanganinya
    • Di Chrome, Anda bisa memasang debug pada method terkait untuk melihat sumber redirect dan state saat itu
    debug(window.location.replace);
    debug(window.location.assign);
    
  • Menemukan titik pembacaan properti

    • Jika Anda ingin tahu persis saat properti tertentu pada objek dibaca, Anda bisa menaruh debugger di dalam getter
    { get configOption() { debugger; return true; } }
    
    • Ini berguna untuk memeriksa kode mana yang menggunakan opsi konfigurasi dan bagaimana cara memakainya
    • Anda bisa menerapkannya dengan mengubah source asli atau lewat conditional breakpoint

Menyalin data dari konsol

  • Dengan copy() Console API, Anda bisa menyalin informasi dari browser ke clipboard tanpa masalah pemotongan string
  • Ini bisa dipakai untuk menyalin snapshot DOM saat ini, metadata resource seperti gambar, JSON blob besar, atau dump localStorage
copy(document.documentElement.outerHTML)
copy(performance.getEntriesByType("resource"))
copy(JSON.parse(blob))
copy(localStorage)

Debugging HTML/CSS

  • Memeriksa DOM saat eksekusi JS dihentikan

    • Di DOM inspector, pada Chrome/Windows Anda bisa menekan ctrl+\ untuk menghentikan eksekusi JS kapan saja
    • Bahkan ketika JS mengubah DOM atau event seperti mouseover mengubah DOM, Anda tetap bisa memeriksa snapshot DOM saat ini dengan stabil
  • Memeriksa elemen yang menghilang

    • Elemen DOM bersyarat yang menghilang saat mouse dipindahkan bisa diperiksa dengan memasang timer 5 detik di konsol untuk menjalankan debugger
    setTimeout(function() { debugger; }, 5000);
    
    • Setelah UI ditampilkan selama 5 detik dan eksekusi JS dihentikan, elemen tidak akan menghilang, sehingga Anda bisa berpindah ke developer tools untuk memeriksanya
    • Selama eksekusi JS dihentikan, Anda bisa memeriksa elemen, mengedit CSS, dan menjalankan perintah konsol JS
    • Ini efektif saat memeriksa DOM yang bergantung pada posisi kursor atau fokus
  • Merekam snapshot DOM

    • Jika Anda ingin menyalin DOM saat ini, gunakan perintah berikut
    copy(document.documentElement.outerHTML);
    
    • Jika Anda ingin menyimpan string DOM ke array setiap 1 detik, Anda bisa memakai setInterval seperti berikut
    doms = [];
    setInterval(() => {
      const domStr = document.documentElement.outerHTML;
      doms.push(domStr);
    }, 1000);
    
    • Anda juga bisa terus mencetaknya ke konsol tanpa menyimpannya ke array
  • Memantau elemen yang sedang fokus

    • Dengan membandingkan document.activeElement secara berkala, Anda bisa menampilkan perubahan fokus ke konsol
    (function () {
      let last = document.activeElement;
      setInterval(() => {
        if (document.activeElement !== last) {
          last = document.activeElement;
          console.log("Focus changed to: ", last);
        }
      }, 100);
    })();
    
  • Menemukan elemen yang ditampilkan tebal

    • Anda bisa mencari elemen yang fontWeight terhitungnya bernilai "bold" atau "700"
    const isBold = (e) => {
      let w = window.getComputedStyle(e).fontWeight;
      return w === "bold" || w === "700";
    };
    Array.from(document.querySelectorAll("*")).filter(isBold);
    
    • Jika Anda hanya ingin mencari di antara turunan elemen yang saat ini dipilih di inspector, Anda bisa mencari berdasarkan $0
    Array.from($0.querySelectorAll("*")).filter(isBold);
    
  • Menangani elemen yang dipilih dan event

    • $0 di konsol adalah referensi otomatis ke elemen yang saat ini dipilih di Element Inspector
    • Di Chrome dan Edge, elemen yang sebelumnya diperiksa bisa diakses sebagai $1, dan elemen sebelumnya lagi sebagai $2
    • Di Chrome, Anda bisa memeriksa event listener dari elemen yang sedang dipilih
    getEventListeners($0)
    
    • Untuk men-debug semua event pada elemen yang dipilih, Anda bisa memakai monitorEvents($0)
    • Jika Anda hanya ingin melihat grup event tertentu, Anda bisa memberikan array
    monitorEvents($0, ["control", "key"])
    

1 komentar

 
GN⁺ 2023-11-12
Opini Hacker News
  • Selama beberapa dekade terakhir, alat debugging bawaan di browser benar-benar sudah berkembang pesat
    Sebagai orang yang sudah lama memakai JS, saya sangat berterima kasih kepada orang-orang yang membuat debugging kode di dalam browser menjadi seintuitif ini
    Saat beralih ke area pengembangan lain seperti backend atau bahasa lain, saya jadi merindukan ekosistem alat debugging yang disediakan browser modern secara bawaan

    • Saya juga ingin memberi apresiasi kepada orang-orang yang membuat ekstensi Firebug, yang benar-benar mengangkat DevTools browser ke level berikutnya
    • Saya penasaran, apa sebenarnya yang terasa begitu istimewa dalam pengalaman debugging JS?
      Saya sudah banyak melakukan debugging selama bertahun-tahun di Python, Java, dan C++, tetapi tidak pernah merasa kekurangan alat
      Tentu saja saya cukup sering melihat orang yang tidak tahu opsi-opsi apa saja yang tersedia di bidang ini
    • Memang tidak sempurna, tetapi jauh lebih baik daripada pengalaman debugging Node.js dengan VS Code yang didorong oleh rekan kerja saya
      Dibanding neraka itu, saya lebih memilih console
  • setTimeout(function() { debugger; }, 5000); itu cerdas
    Pada akhirnya, satu-satunya cara bagi debugger Chrome untuk mengalahkan tumpukan kura-kura rekursif saat men-debug dirinya sendiri adalah statement debugger
    sam.pl dari worm Myspace Sammy yang terkenal buruk juga memakai jebakan debugging agar pengunjung tidak bisa membongkar homepage HTML yang diobfuscate

    • Ini salah satu bookmarklet yang sering saya pakai: https://darekkay.com/blog/debugging-dynamic-content/
    • Ini terjadi ketika sebuah situs web menghalangi panel samping Console/DevTools yang terbuka
      Mereka menjalankan main loop, menyisipkan statement debugger; yang menjengkelkan di sana-sini, lalu mengeksekusinya pada 30FPS / interval 32ms sehingga DevTools menjadi tidak berguna
      Karena tidak ada cara untuk “mengabaikan” statement debugger
    • Kalau tidak ingin menunggu 5 detik, gunakan pintasan pause script execution cmd-\
      Halaman akan berhenti di baris JS yang sedang berjalan, dan Anda bisa menginspeksi elemen bermasalah seperti biasa
    • Saya berharap pembuat browser menjadikannya opsi yang diaktifkan secara eksplisit di DevTools, dan secara default mengabaikan statement debugger
      Sebagian besar kasus penggunaan statement debugger yang sah bisa diganti dengan breakpoint biasa jika Anda sedang mengerjakan kode sendiri
    • Tunggu, cuma itu? Terlalu sederhana, tapi bagus sekali
  • Terlihat jelas bahwa queryObjects belum disebut
    Ini API yang cukup gila, yang mengembalikan daftar semua objek yang dibuat oleh constructor tertentu
    Misalnya, dengan queryObjects(Function) Anda bisa mendapatkan daftar semua function yang ada di heap
    Bahkan function “private” di dalam suatu modul pun ikut dikembalikan

    • Jujur saja, bisa dimaklumi kalau fitur ini tidak ingin dipublikasikan
      Ini benar-benar fitur gila, dan sepertinya khusus Chromium
  • Saya sama sekali tidak bisa memakai watch variable dengan benar
    Scope dan aturan pembaruannya terlalu tidak jelas, rasanya hanya variabel global yang bisa dipantau, tetapi itu pun tidak berjalan sesuai harapan, jadi saat testing akhirnya saya membanjiri log dengan nilai
    Selama bertahun-tahun saya berpikir seharusnya ada UI bergaya Data.gui [1] di console agar variabel dan nilai konfigurasi bisa dilihat dan diuji
    Anda bisa melihatnya bekerja di CodePen ini [2]

    1. https://github.com/dataarts/dat.gui
    2. https://codepen.io/russellbeattie/full/kGxaqM
    • Saya merasakan frustrasi yang sama
      Secara teori, browser punya banyak fitur debugging yang bagus, tetapi dalam praktiknya tampaknya tidak bekerja dengan andal
      Bahkan breakpoint pun tidak bisa saya buat selalu terpasang dengan stabil
      Saat kodenya masih terbuka apa adanya, semuanya baik-baik saja, tetapi begitu dibundel, meskipun belum diminify, banyak fitur debugger tampaknya rusak
      Karena saya bukan engineer frontend, mungkin saja ada sesuatu yang saya lakukan dengan keliru
    • Sebaiknya coba matikan source map di debugger
      Kemungkinan besar itulah sumber frustrasinya, dan saya masih tidak paham mengapa fitur itu aktif secara default padahal pengalaman debugging aktif saat fitur itu menyala bisa seburuk ini
    • Di panel sidebar Chrome, variabel yang sudah diminify terlihat dengan nama yang benar, tetapi di watchpoint muncul error bahwa variabel itu tidak terdefinisi, dan itu menyebalkan
  • Akan sangat bagus kalau ada cara untuk mengakses variabel lokal IIFE tanpa menghentikan eksekusi kode di dalam scope IIFE
    Apakah ada cara untuk meyakinkan debugger agar melakukan itu?

    • IIFE adalah Immediately Invoked Function Expression
      https://en.m.wikipedia.org/wiki/Immediately_invoked_function...
    • Kalau masuk ke breakpoint di fungsi yang dipanggil oleh IIFE, cukup naik kembali di stack
      Kalau sudah sepenuhnya berada di luar IIFE, menurut saya itu tidak mungkin
      Variabel yang dicari mungkin tidak ada di memori sebelum atau sesudah eksekusi
      JavaScript tidak punya variabel statis seperti bahasa lain, jadi setiap kali IIFE dipanggil, variabel internalnya dibuang
      JavaScript punya model single-thread yang cukup kuat kecuali memakai sesuatu seperti web worker, jadi kecuali Anda sengaja membuat race condition dengan pemanggilan async/await, konsep bahwa variabel seperti itu tetap berada di memori di luar scope IIFE sendiri sulit berlaku
      Kalau menyalahgunakan var untuk menginisialisasi variabel di luar scope IIFE, Anda bisa melihat nilai yang dibuat oleh pemanggilan IIFE terakhir
    • Sekitar 12 tahun lalu saya membuat tool yang melakukan hal seperti itu
      Perlu sedikit modifikasi, tetapi hasilnya besar dibanding usaha yang dikeluarkan
      https://github.com/kristopolous/_inject
      Anda bisa berkeliling hampir ke konteks fungsi mana pun pada titik waktu arbitrer dan melihat apa yang terjadi
      Caranya dengan menyalahgunakan reference counter agar konteks tidak dihancurkan
      Saat saya banyak mengerjakan JS sisi klien, ini benar-benar berguna
      Versi killer app yang dibuat dengan benar untuk ini mungkin berupa membuka REPL di konteks mana pun
      Dalam kondisi sekarang pun, untuk memakainya dengan baik dibutuhkan keahlian yang cukup tinggi
    • Apakah yang Anda cari adalah logpoint?
      https://firefox-source-docs.mozilla.org/devtools-user/debugg...
      Edit: baru sadar bahwa itu benar-benar hal pertama yang dibahas di artikel yang ditautkan
    • Di Chrome, Anda bisa memeriksa closure yang dijelaskan di https://news.ycombinator.com/item?id=38226743#38231705 lewat Watch panel, lalu melihat pseudo-properti [[Scopes]]
      Sepertinya tidak ada cara di Firefox
  • Demi kelengkapan, saya bisa merekomendasikan Werkzeug
    Saya memakainya untuk pengembangan backend Django dan ini sangat berguna
    Ini memungkinkan Anda memakai shell “PDB” di dalam browser kapan pun dan di mana pun exception terjadi

    • Mudah, karena cukup taruh 1/0 di tempat Anda ingin memunculkan Werkzeug di browser
    • Saya ingin pengalaman seperti itu ada di mana-mana, termasuk nose.js dan browser
      Sangat sederhana dan intuitif
    • Apakah masih perlu django-extension/runserver_plus?
  • Satu trik yang selalu saya pakai adalah men-debug dengan mencari skrip yang dimuat berdasarkan string UI
    Buka panel Network, mulai perekaman network request, buka sidebar kiri, lalu cari kode atau string UI yang ingin ditemukan
    Biasanya ditemukan di dalam file chunk JS bundle yang aneh, dan ketika hasilnya diklik, network request untuk file tersebut akan terbuka
    Klik kanan di mana saja di dalam file itu lalu pilih item semacam “Open in Sources” untuk berpindah ke debugger
    Sekarang tinggal letakkan pernyataan debugger, dan dalam proses ini source map mungkin juga ikut dimuat

  • Saya sudah lama bekerja sebagai programmer Python/Elixir dan banyak memakai pdb.set_trace() serta IEx.pry()
    Baru-baru ini saya mewarisi backend NodeJS yang sangat berantakan, dan tanpa tool debugging yang layak saya sampai ingin menjambak sisa rambut saya
    Saya kembali ke debugging dengan console.log, tapi rasanya seperti menjadi manusia purba
    Sulit dipercaya ekosistem sepopuler ini tidak punya debugging REPL yang layak; bisa beri tahu saya harus ke mana?

    • Ada
      Pakai node --inspect-brk, lalu Anda bisa tersambung dengan VS Code atau Chrome DevTools
      Bagian yang tricky adalah apakah build tool seperti transformasi TypeScript berada sebelum perintah nodejs atau tidak
      Kalau Anda hanya menjalankan node, itu cukup mudah
      Debugging REPL-nya adalah konsol JavaScript itu sendiri
    • Dengan developer tools VSCode, Anda bisa men-debug NodeJS dengan cukup solid
      Kalau ditambahkan sebagai opsi debugging, Anda bisa memasang breakpoint dan step into ke dalam fungsi
      Karena sebagian besar dienkapsulasi di dalam objek, JavaScript cukup enak untuk di-debug
    • Seperti yang dikatakan orang lain, yang Anda inginkan adalah --inspect atau --inspect-brk
      Di VSCode Anda juga bisa memakai perintah “open JavaScript debug terminal”
      Perintah ini membuka terminal tempat perintah node apa pun otomatis dimulai dengan debugger terpasang
    • Mungkin belum cukup, tetapi saya baru saja mengetahui python snoop
      https://pypi.org/project/snoop/
      Ini dekorator untuk tracing mendalam
    • Hal bagus di REPL Elixir, yang tampaknya mirip dengan REPL Erlang, adalah kemampuan untuk terhubung ke proses yang sedang berjalan
      Saya belum melihat fitur seperti ini di ekosistem Node JS
  • Di bagian “Debugging Property Reads”, saya penasaran bagaimana breakpoint bersyarat digunakan untuk mengubah {configOption: true} menjadi {get configOption() { debugger; return true; }}

    • Itu bukan isi di bawah judul breakpoint bersyarat
      Anda cukup menimpa nilainya dengan getter di konsol, dan kalau punya izin tulis, bisa juga mengubahnya langsung di source code
  • Ini sepertinya sesuatu yang wajib dipelajari, tapi penasaran apakah ada buku khusus atau materi belajar untuk itu
    Atau memang satu-satunya cara adalah terus menggali pengembangan web dan frontend tanpa henti?

    • Saya sangat merekomendasikan mengikuti seri “What’s new in DevTools” dari tim Chrome
      Saat sedang sibuk bekerja, mungkin tidak terasa menarik untuk mengeklik tautan demi membaca catatan rilis, tetapi meluangkan 5 menit untuk meninjau sekilas setiap kali versi baru keluar sudah sangat berharga
      Ada juga video beberapa menit yang mudah dicerna, sehingga bisa mendapat gambaran singkat
      Tujuannya memang memperkenalkan fitur baru, tetapi dari pengalaman, ini juga sering membantu memahami batasan alat saat ini