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 masuk akal 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 terjadi masalah pada salah satu langkah, Anda dapat dengan mudah mengembalikannya. 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 tidak memiliki cakupan pengujian yang baik, kita 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, Anda dapat dengan mudah melewatkan langkah, dan beberapa kali pengujian menemukan masalah yang terlewatkan oleh pelaksana dan peninjau.

Satu hal yang kami lakukan di awal adalah penyiapan Continuous Integration (CI). Kami melihat bahwa CI yang berjalan pada permintaan pull tidak stabil dan sering gagal. Hal ini sering terjadi sehingga kami terbiasa mengabaikan CI dan menggabungkan permintaan pull, dengan asumsi bahwa kegagalan tersebut adalah masalah satu kali di 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 sangat menjengkelkan melihat CI yang berjalan tanpa henti, tetapi sangat penting untuk membuat suite pengujian berjalan dengan andal mengingat jumlah permintaan pull yang diajukan 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 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, tetapi untuk melanjutkan dengan hati-hati dan secara metodis file demi file. Waktu yang dihabiskan untuk memvalidasi pendekatan ini pasti akan menghemat waktu nanti dalam migrasi saat Anda membuka file yang lebih rumit tersebut.

Buktikan pola dan ulangi

Untungnya, perubahan pada DeviceDescriptors.js berhasil masuk ke codebase, dan rencananya berhasil seperti yang kita 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 tingkatkan kualitasnya 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, berarti kita telah 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 berfokus pada pengujian. Pengujian kami memiliki cakupan yang bagus, tetapi semuanya ditulis dalam JavaScript. Artinya, satu hal yang tidak mereka uji adalah definisi jenis 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, file demi file), kami menemukan masalah pada TypeScript yang seharusnya diserahkan kepada pengguna untuk ditemukan. Sekarang pengujian kita tidak hanya mencakup semua fungsi, tetapi juga berfungsi sebagai pemeriksaan kualitas TypeScript kita.

Kami telah mendapatkan manfaat besar dari TypeScript sebagai engineer yang bekerja pada 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 mungkin akan masuk ke rilis npm. Kami senang dapat mengirimkan definisi TypeScript berkualitas tinggi agar semua developer yang menggunakan Puppeteer juga dapat memanfaatkan pekerjaan ini.

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.