chromedp არის sebuah biblioteca yang ditulis sepenuhnya di Go, berlisensi MIT, dan mengendalikan Chrome asli lewat Chrome DevTools Protocol. Ia membaca DOM setelah JavaScript halaman selesai berjalan, langsung dari program Go, tanpa WebDriver terpisah atau runtime Node. Modul Go-nya dikompilasi ke dalam aplikasi, tetapi saat runtime tetap membutuhkan file executable Chrome eksternal, yang siklus hidupnya dikendalikan lewat Go-contexts.
Instalasinya cuma go get plus Chrome yang harus saya sediakan sendiri: buat allocator, turunkan context, lalu kirim daftar actions ke Run. Di mesin macOS arm64 ini, dengan headless shell yang sudah hangat di disk, proses baru sampai hasil script pertama punya median 102 ms. Ini patokan lokal, bukan klaim umum bahwa startup tidak pernah jadi bottleneck. Dalam satu kasus uji yang menyuntikkan sebuah link 800 milidetik setelah load, dua dari empat strategi baca berhasil kembali sebelum link itu muncul.
Browser-nya nyata, kontennya memang ada, dan kodenya פשוט saja tidak menunggu sampai konten itu muncul. Celah itulah hal paling berguna yang saya pelajari dari chromedp, dan itu bukan bug — itu bedanya antara “saya merender halaman” dan “saya menunggu tepat hal yang saya butuhkan”, perbedaan yang sering kabur di dunia headless. Yang menentukan apakah datanya didapat atau tidak adalah strategi menunggunya, bukan browser-nya. Semua angka di sini berasal dari fixture lokal yang saya kendalikan, dengan ground truth dicatat sebelum ada eksekusi apa pun, dan ringkasan mentahnya ada di chromedp-mappen i vårt benchmark-repo.
Vad chromedp faktiskt är
chromedp-stacken sengaja dibuat ringkas. Tidak ada Selenium-server. Tidak ada jembatan WebDriver. Tidak ada runtime Node yang bersembunyi di latar belakang. Program Go kamu membuka koneksi WebSocket ke instans Chrome dan berbicara CDP langsung dengannya, kurang lebih protokol yang sama seperti Puppeteer pakai, tapi tanpa lapisan JavaScript.
Repo-nya punya 13 212 stjärnor dan 178 issue terbuka saat saya cek pada 27 Juli 2026, di bawah lisensi MIT. Versi yang saya uji adalah v0.16.0, yaitu tag terbaru di repo itu. Ada satu hal yang perlu dicatat supaya tidak bingung: halaman GitHub Releases masih menampilkan v0.15.1 (dirilis 2026-04-01) sebagai objek release terbaru, sedangkan go get github.com/chromedp/chromedp@latest mengarah ke v0.16.0. Jadi, Go module dan objek release GitHub di sini sudah agak melenceng. Bukan rusak, cuma bikin jengkel saat kamu mencoba memastikan apa sebenarnya yang sedang kamu pakai.
Model mentalnya bertumpu pada Go-contexts dari atas sampai bawah. Kamu membuat allocator-context (yang tahu bagaimana Chrome dimulai), menurunkan browser-context darinya, lalu menjalankan chromedp.Run(ctx, actions...) dengan daftar Actions. Child context dari browser-context itu adalah tab baru. Begitu context dibatalkan, apa pun yang diwakilinya ikut hilang. Kalau kamu pernah kerja dengan concurrency di Go, ini langsung terasa akrab; kalau belum, guide för att komma igång med web scraping i Go adalah pintu masuk yang lebih lembut daripada godoc chromedp.
Batas penting yang harus jelas sejak awal: chromedp memberi kamu DOM yang sudah dirender. Ia tidak memberi data terstruktur. Semua yang kamu ambil dari DOM — field, tabel, harga — adalah kode yang kamu tulis dan rawat sendiri. Ini driver, bukan scraping framework.
Maskineriet under huven
Semua di chromedp adalah sebuah Action, dan Run mengeksekusi slice action itu secara berurutan terhadap sebuah target. Navigate, Click, Evaluate, OuterHTML, WaitVisible — interface-nya sama, semuanya bisa dikomposisikan, dan pada praktiknya hanyalah perintah CDP yang dibungkus tipe Go. Keseragaman ini adalah keputusan desain terbaiknya, karena berarti lapisan kenyamanan dan protokol mentah hidup di level yang sama.
Itu penting, karena lapisan kenyamanan memang sengaja dibuat tipis. chromedp dibangun di atas cdproto, yaitu sekumpulan binding Go bertipe yang dihasilkan otomatis untuk mencakup seluruh DevTools Protocol, dan chromedps godoc mendokumentasikan kedua lapisan itu berdampingan. Saat action yang enak tidak tersedia, kamu turun ke pemanggilan domain — network.Enable(), page.CaptureScreenshot(), runtime.Evaluate() — di dalam Run yang sama. Tidak ada tembok antara “API yang nyaman” dan “API yang sebenarnya”, dan itu tidak selalu terjadi pada semua driver browser.
Cara menunggu adalah tempat penilaian sehari-hari terjadi, dan pilihannya lebih banyak daripada yang dipakai kebanyakan orang:
| Väntesätt | Vad det väntar på |
|---|---|
WaitReady(sel) | sampai node terpasang di DOM |
WaitVisible(sel) | sampai node benar-benar terlihat |
WaitNotPresent(sel) / WaitNotVisible(sel) | kebalikannya, berguna untuk loading indicator |
Poll(js, res) | mengevaluasi kondisi JavaScript secara berkala sampai bernilai benar |
Manajemen proses adalah bagian mesin kedua yang layak dipahami, karena itulah yang menentukan apakah program kamu meninggalkan browser yang masih hidup. chromedp menjalankan Chrome lewat exec.CommandContext milik Go. Kalau context itu dibatalkan, prosesnya ikut mati. Detail implementasi kecil ini menjelaskan perilaku yang bagus sekaligus sudut tajam yang saya temui saat pengujian.
Installationen är en Go-binär plus en Chrome du själv måste tillhandahålla
go get github.com/chromedp/chromedp terpasang mulus ke v0.16.0 tanpa drama, dan dependency tree-nya tidak memuat import cgo. Jadi klaim “pure Go, tanpa dependensi eksternal” yang sering diulang itu memang benar — tetapi hanya untuk modul Go-nya.
Untuk runtime, itu tidak benar. chromedp mengendalikan Chrome eksternal, dan tanpa Chrome di mesin, eksekusi langsung gagal. Setiap pengukuran yang saya ambil mengirimkan executable yang tepat lewat chromedp.ExecPath, menunjuk ke Chrome for Testing 151.0.7922.10 headless shell. Ini bukan kritik — mengendalikan browser memang butuh browser — tetapi “tanpa dependensi eksternal” dan “kamu harus mengirim 155 MB Chrome bersama binari kamu” adalah dua cerita distribusi yang sangat berbeda, dan hanya yang pertama yang kelihatan di README.
Satu jebakan lain saat startup juga menghabiskan waktu saya dan layak diketahui sebelum kamu menulis kode. chromedp-issue #1591 melaporkan bahwa test runner Go 1.25+ membatalkan NewExecAllocator di tengah proses startup; kode yang sama berjalan baik sebagai binari hasil kompilasi. Saya membuat probe binary dengan go build dan menjalankannya untuk setiap pengukuran, bukan lewat go test. Versi Go di sini adalah 1.26.5, macOS arm64. Kalau pengalaman pertama kamu dengan chromedp adalah file test yang mati saat Chrome mulai, issue itu yang perlu dibaca dulu sebelum menyalahkan kode sendiri.
Praktiskt: fyra sätt att läsa samma sida, två av dem tomma

Fixture-nya adalah server lokal di 127.0.0.1 yang menyajikan tiga jenis konten yang hanya berbeda pada kapan mereka masuk ke DOM: sebuah <a> statis di bytes yang dikirim, sebuah <a> yang dibuat oleh <script> inline saat parsing pertama, dan sebuah <a> yang dibuat oleh setTimeout sejumlah milidetik yang bisa dikonfigurasi setelah event load. Marker dan href untuk dua link yang dibuat script dibangun dari potongan string di JavaScript, jadi tidak ada literal utuh di bytes yang dikirim. Karena itu, status “found” membuktikan Chrome mengeksekusi JavaScript, bukan sekadar membaca HTML.
Recall dihitung di Python terhadap ground-truth marker yang sudah diregistrasi sebelumnya, bukan di dalam Go probe, jadi probe tidak bisa curang dengan mengetahui jawabannya. Setiap strategi dijalankan tiga kali; set yang ditemukan identik di ketiga putaran.
| Lässtrategi | Statisk HTML-länk | Injicerad vid parse | Injicerad 800 ms efter load | Tid |
|---|---|---|---|---|
Navigate + läsning, ingen väntan | hittad | hittad | missad | 317 ms |
WaitReady("body") | hittad | hittad | missad | 107 ms |
WaitVisible("#delayed-injected") | hittad | hittad | hittad | 912 ms |
| Poll tills markören visas | hittad | hittad | hittad | 972 ms |
Dua baris kembali dengan dua link dari tiga. Pembacaan naif gagal karena Navigate kembali pada load-event, sementara link ketiga belum ada. WaitReady("body") gagal karena alasan yang lebih halus dan lebih berbahaya di praktik: body sudah terpasang saat load, jadi tungguannya langsung dianggap selesai dan kamu merasa sudah melakukan hal yang benar. Ia kembali pada 107 ms, lebih cepat daripada tanpa tunggu, dan memberi kamu halaman yang sama-sama belum lengkap.
Untuk memastikan mekanismenya alih-alih menebak, saya mengubah-ubah delay injeksi dan menjalankan ulang dua ujung ekstrem (recall-summary.json):
| Injektionsfördröjning efter load | Läsning utan väntan ser den | WaitVisible ser den | WaitVisible tid |
|---|---|---|---|
| 0 ms | ja (race) | ja | 109 ms |
| 100 ms | nej | ja | 208 ms |
| 400 ms | nej | ja | 519 ms |
| 800 ms | nej | ja | 911 ms |
| 1500 ms | nej | ja | 1625 ms |
Waktu WaitVisible mengikuti delay injeksi dalam fixture ini — 100 ke 208, 400 ke 519, 800 ke 911, 1500 ke 1625 — yang menunjukkan bahwa ia benar-benar menunggu sampai node ada, bukan membaca terlalu cepat. Baris 0 ms adalah kasus batas: setTimeout(…, 0) bisa saja dijalankan sebelum pembacaan langsung, jadi jalur tanpa tunggu bisa menangkapnya. Pada 100 ms dan seterusnya dalam sweep ini, ia gagal setiap kali.
Di produksi, kesalahan timing seperti ini bisa menghasilkan HTML yang valid tapi nol baris yang diekstrak, lalu exit code 0, kalau pipeline tidak memeriksa ukuran output. Itu perilaku gagal yang masuk akal dan didukung oleh fixture di sini, bukan insiden yang saya ukur di lingkungan nyata. Rendering hanya setengah syarat; pembacaan harus menunggu kondisi aplikasi yang terkait dengan data yang benar-benar kamu butuhkan.
WaitReady och WaitVisible är inte rankade — de svarar på olika frågor
Rumusan umum mengatakan WaitVisible itu “lebih andal” daripada WaitReady. Itu terlalu samar dan bisa menyesatkan. Pada halaman dengan node yang terpasang di DOM tetapi bergaya display: none, keduanya jelas berbeda (waitsem-summary.json, tiga run identik):
| Målnod | Action | Resultat | Tid |
|---|---|---|---|
fäst, display:none | WaitReady | returnerar | ~6 ms |
fäst, display:none | WaitVisible | timear ut, context deadline exceeded | 4000 ms |
| synlig nod | WaitVisible, standard query | returnerar | 4–12 ms |
| synlig nod | WaitVisible, ByID | returnerar | 1–2 ms |
| synlig nod | WaitVisible, ByQuery | returnerar | 1 ms |
WaitReady berarti terpasang. WaitVisible berarti terlihat. Kalau kamu menanyakan hal yang salah, kamu bisa melewati konten yang belum sempat dirender, atau malah menahan seluruh timeout pada node yang memang takkan pernah terlihat. Perilaku deadline-nya sendiri bersih — context deadline exceeded yang tepat pada 4 detik, tanpa hang, tanpa zombie mode — dan itu lebih baik daripada yang bisa dilakukan beberapa driver lain.
Satu jebakan yang dilaporkan tidak berhasil saya reproduksi. Issue #440 menjelaskan bahwa WaitVisible("#id") hang dengan default query, tetapi itu tidak terulang di v0.16.0 — default query, ByID, dan ByQuery semuanya kembali pada node yang terlihat dalam setiap run. Tidak berhasil direproduksi bukan berarti sudah beres: ini hanya selector form pada satu halaman, jadi belum cukup untuk menutup kasusnya.
Det defer cancel() du hoppade över håller uppe taket
Hitung proses, bukan nilai retur. Setiap run siklus hidup memakai --user-data-dir unik dan menghitung proses Chrome browser yang nyata dengan pgrep, sambil memfilter child renderer. Setiap jalur dijalankan tiga kali (lifecycle-summary.json).
| Utgångsväg (macOS, 3 körningar vardera) | Vad som hände med den startade chrome-headless-shell | Tid |
|---|---|---|
| Avbryt context och allocator | försvann | 13, 13 och 12 millisekunder |
| Avsluta Go-processen utan att avbryta | överlever ditt program — noll browserprocesser före, en efter att proben avslutats; föräldralös i tre av tre körningar | — |
Membatalkan itu bersih, cepat, dan persis apa yang dijanjikan exec.CommandContext. (Setiap proses yatim dipaksa mati oleh harness setelahnya; host dibersihkan sampai tuntas.)
Ini perilaku yang dikenal, terdokumentasi, dan terikat platform — pengukurannya milik saya, penemuannya bukan. issue tracker chromedp sudah membahasnya dari beberapa sisi: #774 menjelaskan exit yang tidak terjadi di FreeBSD, #752 melaporkan Chromium yang menggantung di macOS, dan #562 plus #1566 menjelaskan mekanismenya. Yang saya tambahkan adalah hitungan proses dan timing di kedua sisi kontras itu, yang tidak diberikan oleh laporan kualitatif.
Mekanismenya sendiri berkaitan dengan build tags dan itu layak diketahui. Di source v0.16.0, allocate_linux.go menyetel Pdeathsig = SIGKILL ke child process, jadi Linux mendapat sinyal level kernel ketika parent mati. allocate_other.go, yang dikompilasi di macOS, membuat pemanggilan itu jadi no-op. Tidak ada sinyal yang setara di darwin, jadi tidak ada yang membunuh Chrome saat program kamu berakhir. Sementara itu, prosa godoc terdengar seperti janji umum — bahwa command default “mengirim SIGKILL ke semua browser yang terbuka saat program Go berakhir” — padahal pembatasan Linux itu hanya ada di source yang dibuild-tag dan harus kamu baca sendiri. Mengatakan dokumentasinya terlalu menjanjikan itu wajar; menyebutnya bug chromedp tidak.
Konsekuensi praktisnya tetap sama: di macOS, defer cancel() itu penting. Lewatkan itu, dan setiap run akan meninggalkan satu browser process. Saya tidak menguji Linux, jadi saya tidak menggeneralisasi hasil orphan ke sana — source mengisyaratkan perilaku Linux berbeda, dan isyarat bukanlah pengukuran.
Cold start, concurrency och det tråkiga som avgör din driftsättning

102 ms adalah median dari proses baru, allocator, context, navigation ke localhost, dan Evaluate pertama, dihitung dari lima proses, dengan rentang 98 sampai 111 ms (coldstart-summary.json). Dalam fixture macOS arm64 ini dengan headless shell hangat di disk, startup kecil dibanding menunggu konten tertunda. Container, filesystem dingin, CI, lingkungan serverless, dan navigasi produksi tidak diukur.
Untuk concurrency, chromedp memberi kamu dua pola — satu browser dengan banyak child context (tab), atau beberapa browser independen. Empat navigasi, tiga run per jalur (concurrency-summary.json):
| Läge | Väggtid (p50) | Intervall | Max antal Chrome browserprocesser |
|---|---|---|---|
| Delad browser, 4 barncontexts | 214 ms | 209–219 | 1 |
| 4 separata browsers | 264 ms | 261–278 | 4 |
Temuan terukur di sini adalah jumlah proses: satu Chrome browser process versus empat untuk empat navigasi lokal sederhana ini. Rentang waktu memang tidak tumpang tindih, tetapi tetap harus dibaca sebagai arah, bukan benchmark throughput. RSS dan PSS tidak diukur, jadi tes ini tidak membuktikan penghematan memori.
Probe jalur error-nya tidak cukup detail untuk mendukung klaim ketahanan: draft ini tidak menyebut apakah HTTP status, navigasi error, event, atau logika harness mengekspos masing-masing state. Perlakuan terhadap 500/dead-link harus dianggap belum terlapor sampai hasil API yang tepat dan artefak mentahnya dipublikasikan.
Tidak diuji, jadi di luar cakupan angka ini: perilaku Linux untuk lifecycle, concurrency di luar N=4 atau dengan kerja halaman nyata, perbedaan memori (saya menghitung proses, bukan RSS), network interception dan request capture, serta laporan timeout WaitReady yang masih terbuka di #168 dan #1593 — itu menggambarkan timeout yang intermiten, sedangkan yang saya ukur adalah semantik menunggu, pertanyaan yang berbeda. Satu mesin, satu versi Chrome.
chromedp bukan satu-satunya driver Go CDP dalam tes ini: rod dijalankan melalui fixture, harness, host, dan versi Chrome yang sama persis dalam sesi yang sama, dan punya pembahasannya sendiri.
För- och nackdelar
Fördelar:
- Akses CDP asli — action kenyamanan dan panggilan domain
cdprotomentah bisa dipakai bersama dalamRunyang sama, jadi kamu tidak pernah mentok batas API. - Baseline cold-cycle lokal 102 ms p50 dengan sebaran 98–111 ms pada fixture macOS yang diuji.
- Cancel membersihkan Chrome sekitar 13 ms, konsisten, setiap kali.
- Child context berbagi satu browser process untuk banyak tab (1 proses versus 4 untuk browser terpisah).
- Deterministik dalam pengujian — set recall, semantik tunggu, dan hasil lifecycle identik pada tiga pengulangan masing-masing.
- Penanganan deadline yang bersih:
WaitVisiblepada kondisi yang mustahil mengembalikancontext deadline exceededtepat pada 4 s, bukan hang. - Modul pure-Go (tanpa cgo), lisensi MIT; tetapi file Chrome executable eksternal tetap diperlukan saat runtime.
Nackdelar:
- Saat runtime, tetap butuh Chrome eksternal; reputasi “tanpa dependensi” cuma berlaku untuk modul Go.
WaitReady("body")adalah jebakan yang terasa benar tetapi diam-diam melewatkan konten yang datang setelah load — ia kembali pada 107 ms dengan halaman yang belum lengkap.- Jalur naif
Navigate+ membaca melewatkan semua yang disuntik sekitar ≥ 100 ms setelah load, secara deterministik dan tanpa error. - Di macOS, keluar tanpa
cancel()meninggalkan browser yatim (3/3 run). Dikenal dan terikat platform, tapi mudah terlewat. - Rumusan godoc tentang SIGKILL saat exit terdengar universal, padahal mekanismenya hanya ada di source yang dibuild-tag khusus Linux.
go testpada Go 1.25+ bisa membatalkan startup allocator (#1591); bangun binari sebagai gantinya.- Ia mengembalikan DOM, bukan data terstruktur — tiap field yang kamu butuhkan harus diparsing sendiri, dan kodenya kamu yang merawat.
- Tag terbaru (v0.16.0) lebih baru daripada objek GitHub Release terbaru (v0.15.1), jadi cek versi sebentar jadi membingungkan.
Vem chromedp passar för, och vem som bör hoppa över det
Kalau layanan kamu sudah ditulis di Go dan kamu butuh browser asli di dalamnya, chromedp hampir jadi pilihan yang paling masuk akal. Tidak ada proses Node yang perlu dipantau, tidak ada server WebDriver yang harus dijaga hidup, hanya binari hasil kompilasi plus Chrome yang kamu sediakan atau instal sendiri. Model context-nya cocok sekali dengan primitif concurrency Go, sehingga siklus hidup browser pada praktiknya dikendalikan oleh disiplin defer yang sama seperti sisa codebase. Dan kalau kamu butuh sesuatu yang tidak dicakup API kenyamanan — event jaringan CDP, page-lifecycle hook yang presisi, trik di level protokol — kamu bisa turun ke cdproto tanpa keluar dari library.
Ia juga cocok saat kamu ingin kontrol yang jelas atas proses menunggu. Cara menunggu itu primitif, bukan heuristik; ia melakukan persis apa yang ia katakan, dan itu keuntungan besar begitu kamu menerima bahwa sekarang tugasmu adalah memilih yang tepat.
Lewati kalau tim kamu tidak menulis Go — komitmen bahasa adalah biaya sebenarnya, bukan library-nya. Lewati kalau kamu ingin logika tunggu otomatis yang menebak dengan benar untukmu, karena chromedp tidak menebak; ia melakukan persis yang kamu minta dan mengembalikan apa yang halaman punya saat itu. Lewati, atau anggarkan dengan serius, kalau yang kamu butuhkan sebenarnya adalah record terstruktur, bukan DOM: setiap field adalah selector yang harus kamu tulis, uji, dan perbaiki saat situs berubah. Dan kalau seluruh kebutuhanmu cuma “beri saya data dari 500 URL ini”, orkestrasi browser di Go adalah terlalu banyak mesin untuk tugas itu. guide till browser automation menjelaskan kapan mesin itu layak dipakai dan kapan tidak.
Alternativ, inklusive var vår egen stack passar in
Dalam kategori driver browser, rod adalah driver Go CDP lain, sementara Playwright dan Puppeteer adalah alternatif berbasis Node yang dibahas dalam genomgång av Playwright kontra Puppeteer. Kontrak menunggu mereka tidak saling bisa dipertukarkan. Playwright melakukan auto-wait untuk actionability sebelum banyak aksi; itu tetap tidak berarti ia tahu kapan data aplikasi sudah benar-benar datang setelah aksi. chromedp memberi kamu primitif tunggu di level lebih rendah dan menyerahkan actionability serta status siap aplikasi ke pemanggil. Kalau kamu memetakan medan yang lebih luas, genomgång av open source-scrapers vi testat mencakup crawler statis dan library ekstraksi di sisi lain garis ini.
Relaterad recension: Browserless-recension.
Layanan ekstraksi terkelola adalah kategori lain. Ia menukar kontrol atas browser dan selector dengan rendering dan pembentukan schema yang di-outsourcing. Ini bisa berguna saat output yang dibutuhkan adalah record terstruktur, bukan DOM, sedangkan chromedp lebih cocok saat browser harus tetap berada di bawah kendali layanan Go kamu. Kami membangun Thunderbit, sebuah layanan seperti itu, tetapi tidak menjalankannya terhadap fixture ini; jadi tes ini tidak mendukung perbandingan dengan chromedp soal kesetaraan, latensi, kualitas ekstraksi, atau biaya.
Prova Thunderbit för extraktion av webdata
Slutsats
Haruskah kamu memakai chromedp? Ya, kalau kamu menulis Go dan ingin browser asli di bawah kendalimu. Dalam fixture lokal ini, ia mencapai hasil script pertama pada median 102 ms, membersihkan Chrome sekitar 13 ms setelah cancel, dan memakai satu browser process untuk empat tab paralel. Itu observasi terbatas, bukan janji performa universal; nilai yang benar-benar bertahan adalah akses CDP langsung dari Go saat lapisan kenyamanan habis.
Tapi ukuran klaimnya harus pas, karena reputasinya sering terlalu dijual di dua hal. “Pure Go, tanpa dependensi” hanya menggambarkan modul; saat runtime kamu tetap harus menyediakan dan mengelola binari Chrome. Dan “pakai headless browser lalu kamu dapat konten dinamis” hanya benar kalau tunggumu terikat pada node yang benar — pembacaan naif dan WaitReady("body") sama-sama memberi saya halaman yang kehilangan konten yang disuntik 800 ms setelah load, diam-diam, setiap kali. Di macOS, defer cancel() bukan soal gaya; kalau kamu melewatkannya, kamu akan meninggalkan satu browser per run, yang memang perilaku platform yang dikenal tetapi tetap jadi masalahmu. Kalau tiga hal itu benar, chromedp adalah salah satu driver browser yang paling dapat diprediksi yang saya ukur. Kalau salah, ia gagal diam-diam, dan itu cara terburuk bagi sebuah scraper untuk gagal.
Prova Thunderbit för extraktion av webdata Get Started Free
FAQ
Ser chromedp faktiskt JavaScript-renderat innehåll?
Ya — tetapi hanya dengan tunggu yang terhubung ke node yang kamu butuhkan. Dalam fixture tempat sebuah link disuntik 800 ms setelah load-event, baik Navigate plus pembacaan maupun WaitReady("body") gagal menangkapnya, sementara WaitVisible pada node itu dan poll JavaScript sama-sama menemukannya, masing-masing tiga dari tiga run. Saat saya mengubah-ubah delay, pembacaan tanpa tunggu melewatkan node pada setiap setelan dari 100 ms ke atas. Rendering itu perlu; tunggu yang tepatlah yang membuatnya cukup.
Vad är skillnaden mellan WaitReady och WaitVisible?
WaitReady menunggu sampai node terpasang di DOM. WaitVisible menunggu sampai node itu benar-benar terlihat. Pada node yang terpasang tetapi diberi display: none, WaitReady kembali sekitar 6 ms sementara WaitVisible menunggu sampai deadline context 4 detik dan mengembalikan context deadline exceeded yang bersih. Tidak ada yang “lebih andal” — mereka menjawab pertanyaan yang berbeda, dan kesalahan nyatanya adalah memilih yang salah.
Behöver jag verkligen defer cancel() med chromedp?
Di macOS, ya. Membatalkan context dan allocator membersihkan proses Chrome yang diluncurkan dalam 12–13 ms pada setiap run; keluar dari proses Go tanpa membatalkan meninggalkan satu browser process yatim di ketiga run. Ini perilaku yang dikenal dan terikat platform — tracker chromedp mendokumentasikan pola exit yang sama yang tidak terjadi di sistem non-Linux lain, dan mekanisme berbasis parent-death yang menangani itu ada di source yang dibuild-tag khusus Linux. Saya tidak menguji Linux, jadi anggap hasil orphan itu terbatas pada macOS.
Måste chromedp ha Chrome installerat separat?
Ya. Modul Go-nya sendiri pure Go tanpa cgo, tetapi ia mengendalikan browser eksternal dan langsung gagal tanpa browser seperti itu. Saya secara eksplisit menunjuk ke Chrome for Testing 151.0.7922.10 headless shell lewat chromedp.ExecPath. Keuntungannya, biaya startup kecil: satu cold cycle penuh sampai hasil script pertama punya median 102 ms dari lima proses baru, dengan rentang 98–111 ms.
Ska jag dela en browser mellan flikar eller starta separata browsers?
Pilih child contexts kalau tujuanmu meminimalkan jumlah browser process. Empat navigasi localhost lewat satu browser memakai 1 Chrome browser process; empat browser terpisah memakai 4. Waktu wall clock juga cenderung lebih baik pada solusi bersama (214 ms versus 264 ms median), tetapi empat halaman lokal sederhana bukan benchmark throughput. Memori tidak diukur. Browser terpisah tetap bisa tepat kalau kamu butuh isolasi sesi yang lebih kuat, proxy yang berbeda, atau radius crash yang lebih kecil; pertukaran itu berada di luar tes ini.


