Memindahkan Puppeteer ke TypeScript

Kami adalah penggemar berat TypeScript di tim DevTools—bahkan kami menulis kode baru di dalamnya dan sedang melakukan migrasi besar seluruh codebase untuk diperiksa jenisnya oleh TypeScript. Anda dapat mengetahui lebih lanjut migrasi tersebut dalam presentasi kami di Chrome Dev Summit 2020. Oleh karena itu, sangat tepat untuk melihat migrasi codebase Puppeteer ke TypeScript juga.

Merencanakan migrasi

Saat merencanakan cara melakukan migrasi, kami ingin dapat membuat progres dalam langkah-langkah kecil. Hal ini akan mengurangi overhead migrasi—Anda hanya mengerjakan sebagian kecil kode pada satu waktu—dan juga mengurangi risiko. Jika ada yang salah dengan salah satu langkah, Anda dapat memulihkannya dengan mudah. Puppeteer memiliki banyak pengguna dan rilis yang rusak akan menyebabkan masalah bagi banyak pengguna tersebut. Jadi, kami harus meminimalkan risiko perubahan yang dapat menyebabkan kerusakan.

Kita juga beruntung karena Puppeteer memiliki rangkaian pengujian unit yang andal yang mencakup semua fungsinya. Artinya, kita dapat yakin bahwa kita tidak merusak kode saat bermigrasi, tetapi juga tidak memperkenalkan perubahan pada API. Tujuan migrasi adalah menyelesaikannya tanpa pengguna Puppeteer menyadari bahwa kami telah melakukan migrasi, dan pengujian adalah bagian penting dari strategi tersebut. Jika kami tidak memiliki cakupan pengujian yang baik, kami akan menambahkannya sebelum melanjutkan migrasi.

Melakukan perubahan kode apa pun tanpa pengujian berisiko, tetapi perubahan yang melibatkan seluruh file atau seluruh codebase sangat berisiko. Saat melakukan perubahan mekanis, akan sangat mudah melewatkan satu langkah, dan pada beberapa kesempatan pengujian menemukan masalah yang luput dari pelaksana dan peninjau.

Satu hal yang kami lakukan di awal adalah penyiapan Continuous Integration (CI). Kami melihat bahwa CI yang berjalan terhadap permintaan pull tidak stabil dan sering gagal. Hal ini sering terjadi sehingga kami terbiasa mengabaikan CI kita dan tetap menggabungkan permintaan pull, dengan asumsi bahwa kegagalan tersebut adalah masalah satu kali pada CI, bukan masalah di Puppeteer.

Setelah melakukan beberapa pemeliharaan umum dan meluangkan waktu untuk memperbaiki beberapa kegagalan pengujian reguler, kami berhasil membuat pengujian tersebut lulus dengan lebih konsisten, sehingga kami dapat memproses CI dan mengetahui bahwa kegagalan menunjukkan masalah yang sebenarnya. Pekerjaan ini tidak glamor, dan menjengkelkan jika menonton CI tanpa henti, tetapi sangat penting untuk menjalankan suite pengujian kami dengan andal mengingat jumlah permintaan pull yang dihasilkan oleh migrasi.

Memilih dan men-deploy satu file

Pada tahap ini, migrasi kita sudah siap dan server CI yang andal penuh dengan pengujian untuk mengawasi kita. Daripada langsung menggunakan file arbitrer, kami sengaja memilih file kecil untuk dimigrasikan. Ini adalah latihan yang berguna karena memungkinkan Anda untuk memvalidasi proses yang direncanakan yang akan Anda lakukan. Jika berhasil pada file ini, pendekatan Anda valid; jika tidak, Anda dapat kembali ke papan gambar.

Selain itu, dengan memeriksa file satu per satu (dan dengan rilis Puppeteer reguler, sehingga semua perubahan tidak dikirim dalam versi npm yang sama), risikonya dapat diminimalkan. Kita memilih DeviceDescriptors.js sebagai file pertama, karena file ini adalah salah satu file yang paling sederhana di codebase. Mungkin terasa sedikit mengecewakan untuk melakukan semua pekerjaan persiapan ini dan mendapatkan perubahan kecil seperti itu, tetapi tujuannya bukanlah untuk segera melakukan perubahan besar, melainkan untuk melanjutkan dengan hati-hati dan secara metodis file demi file. Waktu yang dihabiskan untuk memvalidasi pendekatan benar-benar menghemat waktu di kemudian hari dalam migrasi ketika Anda menemukan file yang lebih rumit tersebut.

Buktikan polanya dan ulangi

Untungnya, perubahan pada DeviceDescriptors.js berhasil diterapkan ke codebase, dan rencana tersebut berfungsi seperti yang kami harapkan. Pada tahap ini, Anda siap untuk bekerja keras dan melanjutkannya, yang tepat seperti yang kita lakukan. Menggunakan label GitHub adalah cara yang sangat bagus untuk mengelompokkan semua permintaan pull, dan kami merasa hal itu berguna untuk melacak progres.

Migrasikan dan sempurnakan nanti

Untuk setiap file JavaScript, proses kami adalah:

  1. Ganti nama file dari .js menjadi .ts.
  2. Jalankan compiler TypeScript.
  3. Perbaiki masalah apa pun.
  4. Buat permintaan pull.

Sebagian besar pekerjaan dalam permintaan pull awal ini adalah mengekstrak antarmuka TypeScript untuk struktur data yang ada. Dalam kasus permintaan pull pertama yang memigrasikan DeviceDescriptors.js yang telah kita bahas sebelumnya, kode beralih dari:

module.exports = [
  { 
    name: 'Pixel 4',
     // Other fields omitted to save space
  }, 
  
]

Dan menjadi:

interface Device {
  name: string,
  
}

const devices: Device[] = [{name: 'Pixel 4', }, ]

module.exports = devices;

Sebagai bagian dari proses ini, kita harus memeriksa setiap baris codebase untuk menemukan masalah. Seperti codebase apa pun yang telah ada selama beberapa tahun dan berkembang seiring waktu, ada peluang untuk memfaktorkan ulang kode dan meningkatkan situasi. Terutama dengan beralih ke TypeScript, kami melihat tempat-tempat yang sedikit menyusun ulang kode sehingga kami dapat lebih mengandalkan compiler dan mendapatkan keamanan jenis yang lebih baik.

Meskipun tidak masuk akal, sangat penting untuk menahan diri agar tidak langsung melakukan perubahan ini. Tujuan migrasi adalah untuk memasukkan codebase ke TypeScript, dan setiap saat selama migrasi besar, Anda harus memikirkan risiko yang menyebabkan kerusakan pada software dan pengguna. Dengan menjaga perubahan awal tetap minimal, kami menjaga risiko tersebut tetap rendah. Setelah file digabungkan dan dimigrasikan ke TypeScript, kita dapat melakukan perubahan lanjutan untuk meningkatkan kualitas kode guna memanfaatkan sistem jenis. Pastikan Anda menetapkan batasan yang ketat untuk migrasi dan mencoba untuk tetap berada dalam batas tersebut.

Memigrasikan pengujian untuk menguji definisi jenis

Setelah seluruh kode sumber dimigrasikan ke TypeScript, kita dapat mengalihkan fokus ke pengujian. Pengujian kami memiliki cakupan yang bagus, tetapi semuanya ditulis dalam JavaScript. Ini berarti satu hal yang tidak mereka uji adalah definisi tipe kami. Salah satu sasaran jangka panjang project ini (yang masih kami kerjakan) adalah mengirimkan definisi jenis berkualitas tinggi secara langsung dengan Puppeteer, tetapi kami tidak memiliki pemeriksaan apa pun di codebase tentang definisi jenis kami.

Dengan memigrasikan pengujian ke TypeScript (mengikuti proses yang sama, membuka file demi file), kami menemukan masalah pada TypeScript kami yang seharusnya diserahkan kepada pengguna untuk ditemukan. Sekarang, pengujian kami tidak hanya mencakup semua fungsi, tetapi juga berfungsi sebagai pemeriksaan kualitas TypeScript kami.

Kami telah mendapatkan banyak manfaat dari TypeScript sebagai engineer yang mengerjakan codebase Puppeteer. Ditambah dengan lingkungan CI yang jauh lebih baik, hal ini memungkinkan kami menjadi lebih produktif saat mengerjakan Puppeteer dan membuat TypeScript menangkap bug yang seharusnya masuk ke rilis npm. Kami senang dapat menghadirkan definisi TypeScript berkualitas tinggi yang dikirimkan untuk memungkinkan semua developer yang menggunakan Puppeteer mendapatkan manfaat dari pekerjaan ini juga.

Mendownload saluran pratinjau

Sebaiknya gunakan Chrome Canary, Dev, atau Beta sebagai browser pengembangan default Anda. Saluran pratinjau ini memberi Anda akses ke fitur DevTools terbaru, memungkinkan Anda menguji API platform web canggih, dan membantu Anda menemukan masalah di situs sebelum pengguna melakukannya.

Hubungi tim Chrome DevTools

Gunakan opsi berikut untuk membahas fitur baru, update, atau hal lain yang terkait dengan DevTools.