
Catatan singkat tentang bagaimana Chrome DevTools bermigrasi dari pemuat modul internal ke modul JavaScript standar. Kami akan memberi tahu Anda bagaimana dan mengapa migrasi ditunda, tentang biaya migrasi yang tersembunyi dan tentang kesimpulan tim DevTools setelah migrasi selesai. Tapi mari kita mulai dengan sejarah alat pengembang web.
pengantar
Seperti yang mungkin Anda ketahui, Chrome DevTools adalah aplikasi web HTML, CSS, dan JavaScript. Selama bertahun-tahun DevTools telah menjadi kaya akan fitur, cerdas, dan berpengetahuan luas tentang platform web modern. Meskipun DevTools telah berkembang, arsitekturnya sebagian besar mengingatkan pada aslinya ketika menjadi bagian dari WebKit .
Kami akan menceritakan kisah DevTools, menjelaskan manfaat dan batasan solusi, dan apa yang telah kami lakukan untuk mengurangi batasan tersebut. Jadi mari selami sistem modular, cara memuat kode, dan bagaimana kita akhirnya menggunakan modul JavaScript.
Awalnya tidak ada apa-apa
Frontend sekarang memiliki banyak sistem modular dan alatnya, serta format modul JavaScript standar . Semua ini tidak terjadi saat DevTools dimulai. Alat ini dibuat di atas kode WebKit yang ditulis lebih dari 12 tahun yang lalu.
Sistem modular pertama kali disebutkan di DevTools pada tahun 2012: ini adalah pengenalan daftar modul dengan daftar sumber yang sesuai . Bagian dari infrastruktur Python yang digunakan saat itu untuk mengompilasi dan membangun DevTools. Pada 2013, modul diperiksa menjadi file oleh
frontend_modules.json komit ini , dan kemudian, pada 2014, menjadi file terpisah module.json(di sini ). Contoh module.json:
{
"dependencies": [
"common"
],
"scripts": [
"StylePane.js",
"ElementsPanel.js"
]
}
Sejak 2014, ini telah
module.jsondigunakan di alat pengembang untuk menunjuk ke modul dan file sumber. Sementara itu, ekosistem web berkembang pesat dan banyak format modul dibuat: UMD, CommonJS, dan akhirnya modul JavaScript terstandarisasi. Namun DevTools terhenti module.json. Sistem modular unik non-standar memiliki beberapa kelemahan:
module.jsonmembutuhkan alat pembuatannya sendiri.- Tidak ada integrasi IDE. Tentu saja, dia membutuhkan alat khusus untuk membuat file yang dia mengerti: (
jsconfig.jsonuntuk VS Code ). - Fungsi, kelas, dan objek telah ditempatkan dalam cakupan global untuk memungkinkan berbagi antar modul.
- Urutan daftar file itu penting. Tidak ada jaminan bahwa kode yang Anda andalkan diunggah selain verifikasi manusia.
Secara umum, mengevaluasi status sistem modular DevTools saat ini dan format modul lain yang lebih banyak digunakan, kami sampai pada kesimpulan bahwa hal itu
module.jsonmenciptakan lebih banyak masalah daripada penyelesaiannya.
Keuntungan dari standar
Kami telah memilih modul JavaScript. Saat keputusan ini dibuat, modul dalam bahasa tersebut masih ditandai di Node.js dan sejumlah besar paket NPM tidak mendukungnya. Terlepas dari itu, kami menyimpulkan bahwa modul JavaScript adalah opsi terbaik.
Keuntungan utama dari modul adalah bahwa mereka adalah format standar bahasa . Ketika kami membuat daftar kontra
module.json, kami menyadari bahwa hampir semuanya terkait dengan penggunaan format modul unik yang tidak standar. Memilih format modul non-standar berarti kita harus menginvestasikan waktu untuk membangun integrasi menggunakan alat pembangunan dan alat kolega kita. Integrasi ini sering kali rapuh dan kurang mendukung fitur, memerlukan waktu pemeliharaan tambahan dan terkadang bug yang rumit. Bug akhirnya menyerang pengguna.
Karena modul JavaScript adalah standar, ini berarti bahwa IDE seperti VS Code, alat pemeriksaan jenis seperti kompiler Closure / TypeScript, dan alat build seperti Rollup dan minifier akan dapat memahami kode sumber tertulis. Terlebih lagi, saat orang baru bergabung dengan tim DevTools, mereka tidak perlu membuang waktu untuk mempelajari hak milik
module.json.
Tentu saja, saat DevTools pertama kali dimulai, tidak ada manfaat di atas yang muncul. Butuh waktu bertahun-tahun bekerja dalam kelompok standar untuk mengimplementasikan runtime. Butuh waktu untuk mendapatkan umpan balik dari para pengembang - pengguna modul. Tetapi ketika modul muncul dalam bahasa tersebut, kami punya pilihan: terus mendukung format kami sendiri, atau berinvestasi dalam transisi ke format baru.
Berapa biaya kilauan kebaruan?
Meskipun modul JavaScript memiliki banyak manfaat yang ingin kami gunakan, kami tetap bertahan di dunia
module.json. Memanfaatkan modul bahasa berarti kami harus menginvestasikan upaya yang signifikan dalam hutang teknis. Sementara itu, migrasi dapat merusak fungsi dan menyebabkan bug regresi.
Ini bukan tentang apakah kami menggunakan modul JavaScript. Pertanyaannya adalah seberapa mahal kemampuan untuk menggunakan modul JavaScript . Kami harus menyeimbangkan risiko mengganggu pengguna dengan regresi, waktu yang dibutuhkan teknisi untuk bermigrasi, dan periode penurunan status sistem tempat kami akan beroperasi.
Poin terakhir ternyata sangat penting. Meskipun secara teoritis kita bisa mendapatkan modul JavaScript, selama migrasi kita akan berakhir dengan kode yang akan memperhitungkan kedua jenis modul tersebut . Hal ini tidak hanya menantang secara teknis, tetapi juga berarti bahwa semua teknisi yang mengerjakan DevTools perlu mengetahui cara bekerja di lingkungan seperti itu. Mereka harus terus-menerus bertanya pada diri sendiri, "Apa yang terjadi dalam kode ini, apakah itu
module.jsonJS, dan bagaimana saya bisa membuat perubahan?"
Biaya migrasi laten dalam hal melatih kolega lebih tinggi dari yang kami harapkan.Setelah menganalisis biayanya, kami sampai pada kesimpulan bahwa masih layak untuk beralih ke modul dalam bahasa tersebut. Oleh karena itu, tujuan utama kami adalah:
- Pastikan modul standar berguna sebaik mungkin.
- Pastikan integrasi dengan modul yang ada di pangkalan
module.jsonaman dan tidak menimbulkan dampak negatif pada pengguna (kesalahan regresi, frustrasi pengguna). - Berikan panduan migrasi DevTools. Terutama melalui proses check and balances yang dibangun ke dalam proses untuk mencegah kesalahan yang tidak disengaja.
Spreadsheet, konversi dan hutang teknis
Tujuannya jelas. Tetapi keterbatasan itu
module.jsonsulit untuk dihindari. Butuh beberapa iterasi, prototipe, dan perubahan arsitektur sebelum kami menemukan solusi yang dapat digunakan. Kami akhirnya menulis dokumen proyek dengan strategi migrasi. Dokumen ini memberikan perkiraan awal waktu: 2-4 minggu.
Bagian paling intensif dari migrasi memakan waktu 4 bulan, dan 7 bulan telah berlalu dari awal hingga akhir!Namun, rencana asli telah bertahan dalam ujian waktu: kami ingin mengajarkan runtime DevTools untuk memuat semua file dengan cara lama untuk menggunakan yang tercantum dalam larik
scripts module.json, sementara semua file yang tercantum dalam larik modulesharus dimuat dengan impor bahasa dinamis . File apa pun yang akan ada dalam array modulesdapat bekerja dengan importdan exportdari ES6.
Selain itu, kami ingin bermigrasi dalam 2 tahap. Akhirnya, kami membagi fase terakhir menjadi 2 sub-fase: ekspor dan impor. Modul dan fase dilacak dalam spreadsheet besar:

Cuplikan tabel migrasi di sini.
Fase ekspor
Langkah pertama adalah menambahkan pernyataan ekspor untuk semua entitas yang perlu dibagikan antar modul / file. Transformasi itu otomatis dengan menjalankan skrip untuk setiap folder . Katakanlah
module.jsonada entitas seperti itu:
Module.File1.exported = function() {
console.log('exported');
Module.File1.localFunctionInFile();
};
Module.File1.localFunctionInFile = function() {
console.log('Local');
};
Ini
Modulenama modulnya. File1- nama file. Pada pohon kode, terlihat seperti ini: front_end/module/file1.JS.
Kode di atas diterjemahkan menjadi ini:
export function exported() {
console.log('exported');
Module.File1.localFunctionInFile();
}
export function localFunctionInFile() {
console.log('Local');
}
/** Legacy export object */
Module.File1 = {
exported,
localFunctionInFile,
};
Kami awalnya berencana untuk menulis ulang impor menjadi satu file pada tahap ini. Misalnya, dalam contoh di atas, kita akan menulis ulang
Module.File1.localFunctionInFilemenjadi localFunctionInFile. Namun, kami menyadari bahwa akan lebih mudah untuk mengotomatiskan dan lebih aman untuk memisahkan kedua transformasi tersebut. Jadi, "mentransfer semua entitas ke dalam satu file" akan menjadi sub-fase impor kedua.
Karena menambahkan kata kunci
exportmengubah file dari "skrip" menjadi "modul", sebagian besar infrastruktur DevTools harus diperbarui. Kerangka kerja tersebut menyertakan runtime impor dinamis serta alat seperti ESLint untuk dijalankan dalam mode modul.
Satu gangguan adalah pengujian kami dijalankan dalam mode "tidak ketat". Modul JavaScript menyiratkan bahwa file dijalankan dalam mode ketat. Ini mempengaruhi tes. Ternyata, sejumlah pengujian non-sepele mengandalkan mode non-ketat, termasuk pengujian di mana operator hadir
with.
Pada akhirnya, memperbarui folder pertama (menambahkan ekspor) membutuhkan waktu sekitar satu minggu dan beberapa kali mencoba memuat ulang .
Fase impor
Setelah semua entitas diekspor menggunakan pernyataan ekspor, sementara tetap berada dalam cakupan global karena warisan, kami harus memperbarui semua referensi entitas, jika ada dalam beberapa file, untuk menggunakan impor ES. Tujuan utamanya adalah untuk menghapus semua ekspor yang kedaluwarsa dengan membersihkan ruang lingkup global. Transformasi itu otomatis dengan menjalankan skrip untuk setiap folder .
Misalnya, entitas berikut
module.json:
Module.File1.exported();
AnotherModule.AnotherFile.alsoExported();
SameModule.AnotherFile.moduleScoped();
Dikonversi ke:
import * as Module from '../module/Module.js';
import * as AnotherModule from '../another_module/AnotherModule.js';
import {moduleScoped} from './AnotherFile.js';
Module.File1.exported();
AnotherModule.AnotherFile.alsoExported();
moduleScoped();
Namun, ada beberapa keberatan dengan pendekatan ini:
- Tidak setiap entitas diberi nama berdasarkan prinsip
Module.File.symbolName. Beberapa entitas telah diberi namaModele.Fileatau bahkanModule.CompletelyDifferentName. Ketidakcocokan berarti kami harus membuat pemetaan internal dari objek global lama ke objek impor baru. -
moduleScoped. ,Events, ,Events. , , ,importEvents. - , . , . , , . , , ( DevTools). , , .
JavaScript
Pada Februari 2020, 6 bulan setelah dimulainya September 2019, pembersihan terakhir dilakukan di folder ui /. Beginilah migrasi berakhir secara tidak resmi. Ketika debu mereda, kami secara resmi menandai migrasi selesai pada 5 Maret 2020 .
Sekarang DevTools hanya bekerja dengan modul JavaScript. Kami masih menempatkan beberapa entitas dalam cakupan global (dalam file lama
module.js) untuk pengujian lama atau integrasi dengan bagian lain dari alat arsitek. Mereka akan dihapus dari waktu ke waktu, tetapi kami tidak menganggapnya menghalangi pengembangan. Kami juga memiliki panduan gaya untuk modul JavaScript .
Statistik
Perkiraan konservatif jumlah CL (daftar perubahan - istilah yang digunakan di Gerrit, mirip dengan permintaan tarik GitHub) yang terlibat dalam migrasi ini adalah sekitar 250 CL, sebagian besar dilakukan oleh 2 insinyur . Kami tidak memiliki statistik final tentang ukuran perubahan yang dibuat, tetapi perkiraan konservatif dari baris yang diubah (jumlah perbedaan mutlak antara penyisipan dan penghapusan untuk setiap CL) kira-kira 30.000 baris, yaitu sekitar 20% dari semua kode front-end DevTools .
File pertama yang diekspor didukung di Chrome 79, yang dirilis dalam rilis stabil pada Desember 2019. Perubahan terakhir untuk beralih ke impor ada di Chrome 83, yang dirilis pada rilis stabil pada Mei 2020.
Kami mengetahui satu kemunduran karena migrasi di Chrome stabil. Penyelesaian cuplikan kode di bilah perintah rusak karena ekspor default yang tidak relevan . Ada beberapa regresi lain, tetapi kasus pengujian otomatis kami dan pengguna Chrome Canary telah melaporkannya. Kami memperbaiki bug sebelum mereka dapat membuatnya menjadi rilis Chrome yang stabil.
Anda dapat melihat keseluruhan cerita dengan mendaftar di sini . Tidak semua, tetapi sebagian besar CL terkait dengan kesalahan ini.
Apa yang telah kita pelajari?
- . , JavaScript ( ) , DevTools . , , , .
- — , . , , . , , , .
- (, ) . -. , Python Rollup.
- (~20% ), . , , . , .
- , . . , , , . , , — . , , .
, Level Up , - SkillFactory:
- Java- (18 )
- JavaScript (12 )
E
- Data Science (12 )
- - (8 )
- Machine Learning (12 )
- «Machine Learning Pro + Deep Learning» (20 )
- « Machine Learning Data Science» (20 )
- «Python -» (9 )
- DevOps (12 )
- (9 )
- UX- (9 )
- Web- (7 )
