Dukungan CSS-in-JS di DevTools

Alex Rudenko
Alex Rudenko

Artikel ini membahas dukungan CSS-in-JS di DevTools yang hadir sejak Chrome 85 dan, secara umum, apa yang kami maksud dengan CSS-in-JS dan perbedaannya dengan CSS biasa yang telah lama didukung oleh DevTools.

Apa itu CSS-in-JS?

Definisi CSS-in-JS agak samar. Secara luas, ini adalah pendekatan untuk mengelola kode CSS menggunakan JavaScript. Misalnya, ini dapat berarti bahwa konten CSS ditetapkan menggunakan JavaScript dan output CSS akhir dihasilkan dengan cepat oleh aplikasi.

Dalam konteks DevTools, CSS-in-JS berarti konten CSS dimasukkan ke halaman menggunakan CSSOM API. CSS reguler dimasukkan menggunakan elemen <style> atau <link>, dan memiliki sumber statis (mis. node DOM atau resource jaringan). Sebaliknya, CSS-in-JS sering kali tidak memiliki sumber statis. Kasus khususnya di sini adalah konten elemen <style> dapat diperbarui menggunakan GCM API, yang menyebabkan sumber menjadi tidak sinkron dengan stylesheet CSS yang sebenarnya.

Jika Anda menggunakan library CSS-in-JS apa pun (mis. komponen bergaya, Emosi, JSS), library mungkin akan memasukkan gaya menggunakan API GCM di balik layar, bergantung pada mode pengembangan dan browser.

Mari kita lihat beberapa contoh tentang bagaimana Anda dapat menginjeksikan stylesheet menggunakan ProGuard API yang mirip dengan yang dilakukan oleh library CSS-in-JS.

// Insert new rule to an existing CSS stylesheet
const element = document.querySelector('style');
const stylesheet = element.sheet;
stylesheet.replaceSync('.some { color: blue; }');
stylesheet.insertRule('.some { color: green; }');

Anda juga dapat membuat stylesheet yang benar-benar baru:

// Create a completely new stylesheet
const stylesheet = new CSSStyleSheet();
stylesheet.replaceSync('.some { color: blue; }');
stylesheet.insertRule('.some { color: green; }');

// Apply constructed stylesheet to the document
document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];

Dukungan CSS di DevTools

Di DevTools, fitur yang paling umum digunakan saat menangani CSS adalah panel Styles. Di panel Styles, Anda dapat melihat aturan yang diterapkan ke elemen tertentu, dan Anda dapat mengedit aturan serta melihat perubahan di halaman secara real time.

Sebelum tahun lalu, dukungan untuk aturan CSS yang dimodifikasi menggunakan GCM API agak terbatas: Anda hanya bisa melihat aturan yang diterapkan, tetapi tidak dapat mengeditnya. Tujuan utama yang kami capai tahun lalu adalah memungkinkan pengeditan aturan CSS-in-JS menggunakan panel Styles. Terkadang kita juga menyebut gaya CSS-in-JS sebagai "builted" untuk menunjukkan bahwa gaya tersebut dibuat menggunakan Web API.

Mari pelajari detail pekerjaan pengeditan Gaya di DevTools.

Mekanisme pengeditan gaya di DevTools

Mekanisme pengeditan gaya di DevTools

Saat Anda memilih elemen di DevTools, panel Styles akan ditampilkan. Panel Gaya menerbitkan perintah CDP yang disebut CSS.getMatchedStylesForNode untuk mendapatkan aturan CSS yang berlaku pada elemen. CDP adalah singkatan dari Chrome DevTools Protocol, dan ini adalah API yang memungkinkan frontend DevTools mendapatkan informasi tambahan tentang halaman yang diperiksa.

Saat dipanggil, CSS.getMatchedStylesForNode mengidentifikasi semua stylesheet dalam dokumen dan mengurainya menggunakan parser CSS browser. Kemudian, CSS membangun indeks yang mengaitkan setiap aturan CSS dengan posisi di sumber stylesheet.

Anda mungkin bertanya, mengapa CSS perlu menguraikan CSS lagi? Masalah yang ada di sini adalah karena alasan kinerja browser itu sendiri tidak peduli dengan posisi sumber aturan CSS dan, oleh karena itu, tidak menyimpannya. Namun, DevTools memerlukan posisi sumber untuk mendukung pengeditan CSS. Kami tidak ingin pengguna Chrome reguler membayar penalti performa, tetapi kami ingin pengguna DevTools memiliki akses ke posisi sumber. Pendekatan penguraian ulang ini mengatasi kedua kasus penggunaan dengan kelemahan minimal.

Selanjutnya, implementasi CSS.getMatchedStylesForNode meminta mesin gaya browser untuk menyediakan aturan CSS yang cocok dengan elemen yang diberikan. Dan terakhir, metode tersebut mengaitkan aturan yang ditampilkan mesin gaya dengan kode sumber dan memberikan respons terstruktur tentang aturan CSS sehingga DevTools mengetahui bagian aturan mana yang merupakan pemilih atau properti. Hal ini memungkinkan DevTools untuk mengedit pemilih dan properti secara independen.

Sekarang mari kita lihat pengeditan. Ingat bahwa CSS.getMatchedStylesForNode menampilkan posisi sumber untuk setiap aturan? Hal itu sangat penting untuk pengeditan. Saat Anda mengubah aturan, DevTools akan mengeluarkan perintah CDP lain yang benar-benar memperbarui laman. Perintah ini menyertakan posisi asli fragmen aturan yang sedang diperbarui dan teks baru yang perlu diupdate dengan fragmen.

Di backend, saat menangani panggilan edit, DevTools memperbarui stylesheet target. Tindakan ini juga mengupdate salinan sumber stylesheet yang dipertahankan dan memperbarui posisi sumber untuk aturan yang diperbarui. Sebagai respons terhadap panggilan edit, frontend DevTools mendapatkan kembali posisi yang diperbarui untuk fragmen teks yang baru saja diperbarui.

Hal ini menjelaskan mengapa pengeditan CSS-in-JS di DevTools tidak langsung berhasil: CSS-in-JS tidak memiliki sumber sebenarnya yang disimpan di mana pun dan aturan CSS berada di memori browser di struktur data GCM.

Cara kami menambahkan dukungan untuk CSS-in-JS

Jadi, untuk mendukung pengeditan aturan CSS-in-JS, kami memutuskan bahwa solusi terbaik adalah dengan membuat sumber untuk stylesheet yang dibangun yang dapat diedit menggunakan mekanisme yang ada seperti dijelaskan di atas.

Langkah pertama adalah membangun teks sumber. Mesin gaya browser menyimpan aturan CSS di class CSSStyleSheet. Class tersebut adalah class yang instance-nya dapat Anda buat dari JavaScript seperti yang dibahas sebelumnya. Kode untuk membangun teks sumber adalah sebagai berikut:

String InspectorStyleSheet::CollectStyleSheetRules() {
  StringBuilder builder;
  for (unsigned i = 0; i < page_style_sheet_->length(); i++) {
    builder.Append(page_style_sheet_->item(i)->cssText());
    builder.Append('\n');
  }
  return builder.ToString();
}

Hal ini mengiterasi aturan yang ditemukan dalam instance CSSStyleSheet dan membuat string tunggal darinya. Metode ini dipanggil saat instance class InspectorStyleSheet dibuat. Class InspectorStyleSheet menggabungkan instance CSSStyleSheet dan mengekstrak metadata tambahan yang diperlukan oleh DevTools:

void InspectorStyleSheet::UpdateText() {
  String text;
  bool success = InspectorStyleSheetText(&text);
  if (!success)
    success = InlineStyleSheetText(&text);
  if (!success)
    success = ResourceStyleSheetText(&text);
  if (!success)
    success = CSSOMStyleSheetText(&text);
  if (success)
    InnerSetText(text, false);
}

Dalam cuplikan ini, kita melihat CSSOMStyleSheetText yang memanggil CollectStyleSheetRules secara internal. CSSOMStyleSheetText dipanggil jika stylesheet tidak inline atau stylesheet resource. Pada dasarnya, kedua cuplikan ini sudah memungkinkan pengeditan dasar stylesheet yang dibuat menggunakan konstruktor new CSSStyleSheet().

Kasus khususnya adalah stylesheet yang terkait dengan tag <style> yang telah dimutasi menggunakan Engage API. Dalam hal ini, stylesheet berisi teks sumber dan aturan tambahan yang tidak ada di sumber. Untuk menangani kasus ini, kami memperkenalkan metode untuk menggabungkan aturan tambahan tersebut ke dalam teks sumber. Urutan itu penting karena aturan CSS dapat disisipkan di tengah teks sumber yang asli. Misalnya, anggap elemen <style> asli berisi teks berikut:

/* comment */
.rule1 {}
.rule3 {}

Kemudian, halaman menyisipkan beberapa aturan baru menggunakan JS API yang menghasilkan urutan aturan berikut: .rule0, .rule1, .rule2, .rule3, .rule4. Teks sumber yang dihasilkan setelah operasi penggabungan seharusnya seperti berikut:

.rule0 {}
/* comment */
.rule1 {}
.rule2 {}
.rule3 {}
.rule4 {}

Penyimpanan komentar dan indentasi asli merupakan hal penting untuk proses pengeditan karena posisi teks sumber pada aturan harus tepat.

Aspek lain yang khusus untuk stylesheet CSS-in-JS adalah elemen tersebut dapat diubah oleh halaman kapan saja. Jika aturan DMARC yang sebenarnya tidak sinkron dengan versi teks, pengeditan tidak akan berfungsi. Untuk itu, kami memperkenalkan pemeriksaan, yang memungkinkan browser memberi tahu bagian backend DevTools saat stylesheet sedang diubah. Stylesheet yang diubah kemudian disinkronkan selama panggilan berikutnya ke CSS.getmatchingStylesForNode.

Dengan semua bagian ini pada tempatnya, pengeditan CSS-in-JS sudah berfungsi, tetapi kami ingin meningkatkan UI untuk menunjukkan apakah stylesheet telah dibuat. Kami telah menambahkan atribut baru bernama isConstructed ke CSS.CSSStyleSheetHeader CDP yang digunakan frontend untuk menampilkan sumber aturan CSS dengan benar:

Stylesheet yang dapat dibuat

Kesimpulan

Untuk meringkas cerita di sini, kita telah membahas kasus penggunaan yang relevan terkait CSS-in-JS yang tidak didukung DevTools dan membahas solusi untuk mendukung kasus penggunaan tersebut. Bagian yang menarik dari implementasi ini adalah kita bisa memanfaatkan fungsionalitas yang ada dengan membuat aturan CSS RStudio memiliki teks sumber reguler, sehingga kita tidak perlu mendesain ulang sepenuhnya pengeditan gaya di DevTools.

Untuk latar belakang selengkapnya, lihat proposal desain kami atau bug pelacakan Chromium yang merujuk ke semua patch terkait.

Mendownload saluran pratinjau

Pertimbangkan untuk menggunakan Chrome Canary, Dev, atau Beta sebagai browser pengembangan default Anda. Saluran pratinjau ini memberi Anda akses ke fitur DevTools terbaru, menguji API platform web tercanggih, dan menemukan masalah di situs Anda sebelum pengguna melakukannya.

Menghubungi tim Chrome DevTools

Gunakan opsi berikut untuk membahas fitur dan perubahan baru di postingan ini, atau hal lain yang terkait dengan DevTools.

  • Kirim saran atau masukan kepada kami melalui crbug.com.
  • Laporkan masalah DevTools menggunakan Opsi lainnya   Lainnya   > Bantuan > Laporkan masalah DevTools di DevTools.
  • Tweet di @ChromeDevTools.
  • Tuliskan komentar di video YouTube Yang baru di DevTools atau video YouTube di DevTools.