Dukungan CSS-in-JS di DevTools

Alex Rudenko
Alex Rudenko

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

Apa itu CSS-in-JS?

Definisi CSS-in-JS agak samar. Secara umum, ini adalah pendekatan untuk mengelola kode CSS menggunakan JavaScript. Misalnya, hal ini dapat berarti bahwa konten CSS ditentukan 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. Salah satu kasus khusus di sini adalah konten elemen <style> bisa diperbarui menggunakan API DevTools, yang menyebabkan sumber menjadi tidak sinkron dengan stylesheet CSS yang sebenarnya.

Jika Anda menggunakan library CSS-in-JS (mis. styled-component, Emotion, JSS), library dapat memasukkan gaya menggunakan DevTools API di balik layar, bergantung pada mode pengembangan dan browser.

Mari kita lihat beberapa contoh mengenai cara memasukkan stylesheet menggunakan API DevTools yang mirip dengan apa 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 Gaya, Anda dapat melihat aturan yang berlaku untuk elemen tertentu, mengedit aturan serta melihat perubahan pada halaman secara real time.

Sebelum tahun lalu, dukungan untuk aturan CSS yang dimodifikasi menggunakan API DevTools agak terbatas: Anda hanya dapat melihat aturan yang diterapkan namun tidak dapat mengeditnya. Tujuan utama yang kami miliki tahun lalu adalah memungkinkan pengeditan aturan CSS-in-JS menggunakan panel Styles. Terkadang, kita juga memanggil gaya CSS-in-JS "konstruksi" untuk menunjukkan bahwa gaya tersebut dibuat menggunakan Web API.

Mari pelajari detail pengeditan Styles di DevTools.

Mekanisme pengeditan gaya di DevTools

Mekanisme pengeditan gaya di DevTools

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

Saat dipanggil, CSS.getMatchedStylesForNode akan mengidentifikasi semua stylesheet dalam dokumen dan menguraikannya menggunakan parser CSS browser. Lalu, kode ini membangun indeks yang mengaitkan setiap aturan CSS dengan posisi di sumber stylesheet.

Anda mungkin bertanya, mengapa perlu mengurai CSS lagi? Masalahnya di sini adalah karena alasan kinerja, browser itu sendiri tidak mengkhawatirkan posisi sumber aturan CSS dan, oleh karena itu, tidak menyimpannya. Namun, DevTools memerlukan posisi sumber untuk mendukung pengeditan CSS. Kami tidak ingin pengguna reguler Chrome dikenakan denda performa, tetapi kami ingin pengguna DevTools memiliki akses ke posisi sumber. Pendekatan penguraian ulang ini menangani kedua kasus penggunaan dengan kerugian minimal.

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

Sekarang, mari kita bahas tentang pengeditan. Ingat bahwa CSS.getMatchedStylesForNode menampilkan posisi sumber untuk setiap aturan? Itu sangat penting untuk pengeditan. Saat Anda mengubah aturan, DevTools mengeluarkan perintah CDP lain yang benar-benar memperbarui halaman. Perintah ini menyertakan posisi asli fragmen aturan yang sedang diupdate dan teks baru yang harus diupdate dengan fragmen.

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

Ini menjelaskan mengapa pengeditan CSS-in-JS di DevTools tidak berhasil secara langsung: CSS-in-JS tidak memiliki sumber aktual yang disimpan di mana pun dan aturan CSS berada di memori browser dalam struktur data DevTools.

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 telah dibuat yang dapat diedit menggunakan mekanisme yang sudah ada yang 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 telah 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();
}

Class ini melakukan iterasi pada aturan yang ditemukan dalam instance CSSStyleSheet dan membuat satu string 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 menjadi 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 diubah menggunakan RenderScript 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. Di sini, urutannya penting karena aturan CSS dapat disisipkan di tengah teks sumber asli. Misalnya, bayangkan bahwa elemen <style> asli berisi teks berikut:

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

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

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

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

Aspek lain yang khusus untuk stylesheet CSS dalam JS adalah dapat diubah oleh halaman kapan saja. Jika aturan DevTools yang sebenarnya tidak sinkron dengan versi teks, pengeditan tidak akan berfungsi. Untuk ini, kami memperkenalkan apa yang disebut probe, yang memungkinkan browser memberi tahu bagian backend DevTools saat stylesheet sedang diubah. Stylesheet yang diubah kemudian disinkronkan selama panggilan berikutnya ke CSS.getMatchStylesForNode.

Dengan semua bagian ini, 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

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

Untuk informasi selengkapnya, lihat proposal desain kami atau bug pelacakan Chromium yang merujuk 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 mutakhir, dan menemukan masalah di situs Anda sebelum pengguna melakukannya.

Menghubungi tim Chrome DevTools

Gunakan opsi berikut untuk membahas fitur dan perubahan baru dalam postingan, 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.
  • Tulis komentar di Video YouTube yang baru di DevTools atau Tips DevTools Video YouTube.