Seperti Sports.ru menulis editor WYSIWYG mereka

Pada pertengahan 2018, Sports.ru berpikir untuk pindah ke editor teks WYSIWYG baru untuk posting pengguna. Sejak Juni 2019, editor telah dalam mode beta. Selama waktu ini, kami memecahkan banyak masalah yang terkait dengan desain arsitektur seluruh layanan dan implementasi editor itu sendiri di browser berdasarkan pada perpustakaan ProseMirror , dan memutuskan untuk berbagi pengalaman kami.



Daftar Isi


1. Pendahuluan
1.1. Mengapa Anda membutuhkan WYSIWYG
1.2. Deskripsi tugas yang dihadapi pengembang
2. Cara memilih alat
3. Apa yang terjadi
3.1. Arsitektur layanan
3.2. Apa saja tantangannya
4. Hasil Tes Beta


1. Perkenalan



1.1. Mengapa Anda membutuhkan WYSIWYG


Sports.ru adalah media tentang olahraga dengan pemirsa 20 juta pengguna per bulan. Perbedaan utama kami dari media klasik adalah komunitas dan UGC . Konten pengguna - peringkat, komentar, obrolan, posting - tidak hanya melengkapi nilai editorial, tetapi juga menciptakan platform bagi pengguna untuk berinteraksi satu sama lain. Setiap bulan, pengguna kami menulis hampir 10 ribu posting. Yang terbaik dikirim ke halaman utama situs bersama dengan yang editorial, dikirim ke aplikasi mobile, jejaring sosial. Konten pengguna menyumbang sekitar 40% dari semua bacaan di halaman Sports.ru.

Kami ingin menjadi platform yang paling nyaman bagi penulis olahraga, untuk membantu membuat konten dan mengirimkannya kepada pemirsa yang tertarik. 10 tahun kami menggunakan editor TinyMCE- dan pada akhirnya menjadi usang, tidak lagi sesuai dengan tim dan pengguna yang terbiasa dengan editor modern.


Ara. 1. Antarmuka editor lama berdasarkan TinyMCE

Dari penulis blog secara teratur menerima tentang keluhan berikut:

  • Saya menulis untuk waktu yang lama, kemudian secara tidak sengaja menutup tab dan semuanya hilang;
  • menulis teks yang panjang sangat tidak nyaman;
  • Sangat menyebalkan bahwa untuk menyisipkan setiap gambar, Anda harus mengunggahnya terlebih dahulu ke hosting gambar.

Tim juga memiliki keluhan sendiri:

  • di TinyMCE Anda tidak dapat mengunggah gambar langsung dari file, Anda hanya dapat melampirkan tautan ke gambar, dan karena kenyataan bahwa pengguna tidak dapat mengunggah gambar ke penyimpanan kami, jika tautan ke mereka mati, kami tidak dapat berbuat apa-apa;
  • kemungkinan untuk mengedit dan memformat teks tidak seimbang. Di satu sisi, tidak ada cukup gaya, misalnya, untuk header internal dalam teks. Di sisi lain, dimungkinkan untuk menggunakan alat yang tersedia dalam kombinasi apa pun. Akibatnya, tulisan tampak tidak seragam (di Sports.ru, pekerjaan dimulai pada implementasi sistem desain dan tulisan pengguna harus terlihat sesuai dengan itu);
  • konten dibuat dan disimpan dalam HTML, sehingga sulit untuk mengelola gaya dalam posting pada klien yang berbeda, dan hanya membuat perubahan pada tata letak posting.

Berikutnya adalah kisah tentang bagaimana kami memecahkan masalah membuat editor baru di sisi front-end. Benar, juga akan ada sesuatu tentang produk, desain dan bagian backend, karena tanpa ini akan sulit untuk memahami mengapa keputusan tertentu dibuat di ujung depan.


1.2. Deskripsi tugas yang dihadapi pengembang


Singkatnya, tesis dari mana kita awalnya memanfaatkan: blogging di Sports.ru adalah suatu hal yang menyakitkan. Pada prinsipnya, adalah mungkin untuk tidak membuat editor baru, tetapi cukup menambahkan penyimpanan otomatis dan kemampuan untuk mengunggah gambar ke penyimpanan Anda sendiri - dan sebagian besar keluhan dari pengguna dan karyawan akan hilang. Tapi saya masih ingin tidak mendukung alat pada teknologi lama, tetapi untuk membuat editor modern baru yang dapat dengan mudah kita kembangkan dan skala.

Selain antarmuka yang tidak nyaman, salah satu masalah teknis utama dari editor lama adalah bahwa konten pos segera disimpan sebagai string HTML, dan perubahan pada tampilan pos memerlukan intervensi pengembang backend, atau diimplementasikan dalam runtime pada klien (misalnya, penempatan unit iklan di badan pos). Tugas kami, antara lain, adalah untuk memisahkan data dari presentasi mereka dan, dengan demikian, meninggalkan tata letak dan antarmuka dalam kode klien, dan bekerja dengan data dalam kode server.

Sebagai panutan, kami menggunakan Medium , terkadang memata-matai ide dari Google Doc . Selain menyelesaikan masalah yang sudah diidentifikasi, kami memutuskan untuk menambahkan beberapa fitur baru yang akan membuat menggunakan editor lebih nyaman:

  • WYSIWYG, .. what you see is what you get (. « , », ), , . , ;
  • ( , , , , ; , ) .

Pada saat yang sama, editor itu sendiri seharusnya tidak terikat dengan fitur Sports.ru, karena Sports.ru, meskipun proyek unggulan di perusahaan kami, masih bukan satu-satunya. Perusahaan ini juga mengembangkan media olahraga internasional Tribuna , jejaring sosial untuk para penggemar taruhan Betting Insider , dan baru-baru ini meluncurkan studio produksinya sendiri yang bergerak dalam proyek periklanan. Mengembangkan editor online cukup mahal untuk tidak ingin menggunakan kembali kode ini di situs lain dengan berbagai pengaturan huruf dan gaya, dengan seperangkat alat sendiri untuk mengedit dan memformat.

Kami memiliki banyak konten teks, dan sebelum mulai bekerja membuat editor posting baru, kami memikirkan bagaimana konten ini harus disimpan. TinyMCE tidak memberi kami pilihan dan konten harus disimpan hanya dalam HTML, yang, sebagaimana disebutkan di atas, tidak sesuai dengan tim. Sebagai hasilnya, kami membuat format sendiri untuk menyimpan data teks yang memenuhi persyaratan kami, dan menyebutnya sebagai badan terstruktur.

Tubuh terstruktur adalah array objek yang mencerminkan struktur konten. Dalam hal ini, konten dibagi menjadi elemen-elemen yang merupakan blok independen, misalnya paragraf, daftar, gambar. Suatu elemen menyimpan informasi tentang tipe apa itu dan properti apa yang dimilikinya. Sebagai contoh, blok subtitle menggambarkan judul dalam teks, itu harus berisi teks dan bidang level. Dengan demikian, teks berisi teks dari pos ini, dan level berisi level (dari 1 hingga 4). Badan terstruktur, yang terdiri dari satu tajuk tingkat kedua, mungkin terlihat, misalnya, seperti ini:

const structuredBody = [
    {
        type: 'subtitle',
        value: {
            text: '    ',
            level: 2,
        },
    },
];

Transisi ke badan terstruktur memungkinkan kami memulai proses pemisahan logika bisnis, data, dan presentasi mereka. Pada akhirnya, kami ingin server dan klien hanya bertukar data. Dan bagaimana dan mengapa untuk menampilkan data ini ke pengguna akhir, setiap klien akan menentukan secara independen.

Konten dalam format tubuh formatd disimpan dalam JSON, dan untuk memvalidasi isinya, kami membuat skema JSON yang disebut skema tubuh terstruktur. Diagram ini menjelaskan semua elemen yang valid dan propertinya. Dengan demikian, kita dapat yakin bahwa di mana pun badan terstruktur diperlukan, satu set kunci dan nilai digunakan.

Selain itu, ini memungkinkan tim yang berbeda untuk menggunakan layanan yang sama untuk memproses konten dalam format ini. Misalnya, layanan untuk menghasilkan HTML dari badan terstruktur untuk menampilkan konten atau editor untuk membuat konten. Ini secara signifikan mengurangi biaya pengembangan dan dukungan seluruh inti layanan yang terkait dengan pembuatan dan tampilan konten.

Diasumsikan bahwa editor baru harus menerima konten input dan output secara eksklusif dalam format tubuh terstruktur. Dan di sini perlu untuk mempertimbangkan titik halus: karena sebelumnya posting segera disimpan dalam HTML, string HTML ini dari database dikirim ke klien untuk ditampilkan (selanjutnya, oleh klien yang kami maksud hanya browser, kecuali ditentukan lain). Sekarang kami ingin menyimpan konten dari semua posting di tubuh terstruktur, tetapi klien hanya dapat memproses HTML. Jadi, bersama dengan tugas pindah ke editor baru, tugas menerapkan cara baru bagi klien untuk menampilkan posting untuk dibaca langsung dari badan terstruktur secara bersamaan terjadi. Kami memutuskan bahwa lebih baik memakan sedikit demi sedikit gajah, jadi pertama-tama Anda harus benar-benar meninggalkan TinyMCE, dan baru kemudian mengambil logika menampilkan posting untuk dibaca. Bahkan,tidak semua posting lama berhasil menerjemahkan konten ke dalam format baru, yang berarti bahwa posting ini akan selalu disimpan hanya dalam HTML dan perlu bagi mereka untuk tetap memiliki kemampuan membaca.

Total: bagian dari pos (semua baru dan lama yang berhasil ditransfer ke format baru) akan disimpan dalam dua format - HTML dan badan terstruktur - hingga logika tampilan baru untuk membaca diterapkan, dan sisanya (sebagian besar lama dan sangat sangat lama) posting) hanya akan tetap dalam HTML.


2. Cara memilih alat


Kami harus menyadari kemampuan untuk mengedit dan membuat posting pada klien, dengan mempertimbangkan fitur dan batasan di atas. Seperti biasa, Anda dapat mengambil solusi yang sudah jadi, atau Anda bisa membuat sendiri.

Untuk mulai dengan, kami memeriksa apa perpustakaan yang sudah jadi untuk membuat editor WYSIWYG dan apakah mereka cocok untuk kita. Kami memilih Slate , Draft.js , dan ProseMirror .

Selain menyimpan konten dalam struktur data, momen penting bagi kami juga kemampuan untuk bekerja dengan Vue atau JS murni, karena kami sudah mulai memindahkan situs ke tumpukan teknologi baru menggunakan Vue + Vuex. Selain itu, saya ingin memperluas kemampuan perpustakaan yang sudah selesai dengan bantuan modul baru (pihak ketiga atau tulisan sendiri) jika perlu.

Tab. 1. Perbandingan perpustakaan yang ditinjau dengan parameter paling penting untuk Sports.ru


Seperti yang dapat Anda lihat dari tabel, ProseMirror sepenuhnya memenuhi persyaratan kami, jadi kami tidak lagi mempertimbangkan gagasan untuk menulis perpustakaan kami sendiri untuk mengedit konten teks, tetapi mulai mempelajari perpustakaan ini secara lebih rinci. Masih ada Quill yang agak populer , yang tidak masuk dalam perbandingan kami hanya karena kami dengan jujur ​​melupakannya pada tahap pemilihan alat. Menurut persyaratan utama kami, itu juga lewat, tetapi itu terjadi begitu saja. Kami sudah membicarakan apa ProseMirror itu dan bagaimana cara mengatasinya di artikel lain .


3. Apa yang terjadi



3.1. Arsitektur Layanan


Editor konten itu sendiri pada klien jauh dari semua. Anda perlu menempatkan editor di proyek yang ada, menampilkannya di suatu tempat di halaman web, dan juga mempertimbangkan interaksi dengan backend, menyelesaikan masalah mendukung dua editor secara bersamaan (Anda tidak dapat segera meninggalkan yang lama) dan menyimpan konten dalam dua format (HTML dan terstruktur). tubuh).

Semua tugas ini dapat dibagi menjadi yang terkait dengan frontend, backend dan integrasi mereka. Kami terutama memperhatikan masalah front-end dan integrasi, meskipun kami juga menyebutkan beberapa aspek penting dari tugas back-end.

Layanan frontend untuk editor dapat dibagi menjadi beberapa tingkatan:

  1. halaman web untuk membuat dan mengedit posting;
  2. Vue-app, . , , Vue, -, , , , .., , , ;
  3. WYSIWYG- ProseMirror, Vue. , , ;
  4. SB2HTML – HTML structured body, . , structured body – , . , , , . Sports.ru HTML structured body, - HTML . HTML Node.Js, JS- .

Proses menyimpan posting ditunjukkan pada Gambar. 2. Konten tulisan dalam format tubuh terstruktur dan meta-datanya ditransfer ke backend. Backend mengirim konten ke layanan SB2HTML, menerima HTML siap dalam respons, menempatkan semua ini ke dalam basis data dan memberi tahu klien bahwa pos telah berhasil disimpan, atau melaporkan kesalahan.


Ara. 2. Skema untuk menyimpan posting saat membuat atau mengedit di editor WYSIWYG


3.2. Kesulitan apa yang Anda hadapi?


Ada banyak kesulitan, mereka muncul terus-menerus dan seringkali di saat-saat yang paling tak terduga.

Seperti yang sudah kami katakan, editor konten terletak di dalam formulir, yang memungkinkan Anda memasukkan data tambahan yang diperlukan untuk membuat posting, seperti judul, anotasi, dll. Untuk anotasi, Anda dapat mengunduh gambar dari file dan melalui tautan dari Internet. Tetapi untuk konten kami juga ingin memuat gambar dari file dan dengan referensi, terlebih lagi, sesuai dengan aturan yang sama. Dan di sini kita dihadapkan pada sebuah dilema: di satu sisi, isi dari sebuah posting terisolasi dari bentuk eksternal ketika mengedit dan dilayani oleh ProseMirror, tetapi di sisi lain, saya ingin mengamati prinsip KERINGdan jangan menduplikasi kode yang sama. Kami memecahkan ini sebagai berikut: kami menggambarkan memuat gambar sebagai satu set metode dalam suatu objek di tingkat bentuk Vue dan melewati objek ini sebagai salah satu parameter untuk konstruktor editor WYSIWYG.

Entitas yang mendeskripsikan konten - Node dan Fragmen - didefinisikan dalam model ProseMirror. Namun, hanya indeks yang digunakan untuk transaksi untuk menentukan rentang karakter yang digunakan transaksi ini (indeks dihitung baik dari awal dokumen dan dari awal node induk). Pengindeksan karakter adalah salah satu konsep utama ProseMirror, tetapi ketika mengedit dan memformat teks, jauh lebih mudah untuk memikirkan entitas dari model ProseMirror. Sebagai hasilnya, untuk pekerjaan yang nyaman dengan konten, kami menulis bantuan kami untuk menyederhanakan interaksi dengan dokumen untuk transaksi. Setelah awal pekerjaan kami, perpustakaan tiptap muncul , yang merupakan seperangkat pembantu serupa.

Masalah berikutnya adalah pada tahap pembuatan skema, kami menyadari bahwa kami telah memiliki format internal yang disetujui untuk menyimpan konten - badan terstruktur yang memenuhi kebutuhan kami, dan ProseMirror menyimpan konten dalam formatnya sendiri dalam sebuah cerita. Beralih ke format ProseMirror sulit dan tidak praktis. Kami menemukan diri kami dalam situasi di mana data dalam satu format datang ke klien melalui API, dan yang lainnya perlu ditampilkan. Situasi serupa muncul ketika perlu untuk menyimpan konten yang dimodifikasi atau dibuat. Untuk melakukan ini, kami menerapkan konverter yang mengubah format bolak-balik. Mereka menulis tes sederhana untuknya, yang mengambil konten dari satu posting dalam format tubuh terstruktur, menerjemahkannya ke dalam format ProseMirror, lalu kembali dan sudah membandingkan versi aslinya dengan yang diterima. Ternyata dengan cepat dan mudah.

Di masa depan, ketika skema dokumen berubah dan, sebagai suatu peraturan, menjadi lebih rumit, menjadi jelas bahwa perubahan sekecil apa pun dapat menyebabkan kesalahan dalam editor, dan tes semacam itu tampaknya memberikan cakupan yang sangat buruk. Akibatnya, saya harus menulis tes pada hampir semua kombinasi node dan merek pada dua metode konverter kecil. Sekarang tanpa tes ini tidak mungkin untuk menentukan apakah perubahan berikutnya pada rangkaian akan merusak sesuatu atau tidak.

Masalah selanjutnya lagi terkait dengan kebutuhan kompatibilitas mundur teknologi lama dan baru. Editor WYSIWYG kami hanya diimplementasikan di browser (desktop dan, segera, ponsel). Oleh karena itu, untuk mengedit konten pada klien diberikan dalam JSON dalam format terstruktur, namun, membaca posting di browser dilakukan hanya dari HTML. Pada saat yang sama, sebagian besar aplikasi seluler sudah beralih ke menampilkan posting pengguna langsung dari badan terstruktur.

Untuk aplikasi seluler, perlu menyediakan kasus ketika klien tidak dapat memproses beberapa elemen dari tubuh terstruktur. Misalnya, jika elemen baru ditambahkan ke tubuh terstruktur, tampilan yang diimplementasikan hanya dalam versi aplikasi yang lebih baru. Karena tidak semua pengguna memperbarui aplikasi mereka pada saat yang sama, itu perlu untuk menyediakan rencana "B" untuk versi yang lebih lama: alih-alih membuat HTML dari badan terstruktur, masukkan fragmen HTML siap pakai untuk elemen yang diinginkan. Kehadiran fragmen HTML untuk setiap elemen tidak disediakan dalam skema struktur tubuh, karena gagasan struktur ini adalah menolak untuk menyimpan data dalam HTML. Tetapi pada akhirnya, kami sampai pada kesimpulan bahwa kami membutuhkan dua skema tubuh terstruktur - satu untuk tampilan dan satu untuk mengedit. Perbedaan antara skema adalahbahwa badan terstruktur untuk pengeditan hanya berisi konten artikel, dan untuk tampilan kami menambahkan beberapa elemen tambahan. Secara khusus, sebuah fragmen HTML untuk setiap elemen dibuat ketika sebuah posting disimpan dalam layanan SB2HTML dan ditambahkan hanya ke badan terstruktur untuk menampilkan posting. Selain itu, badan terstruktur juga menampilkan ruang iklan di konten untuk ditampilkan.

Saat kami membuka konten untuk diedit di browser, pada dasarnya kami tidak dapat menemukan elemen yang tidak dikenal, karena semua posting dibuat dan ditampilkan dengan cara yang sama. Tetapi mereka memutuskan untuk meramalkan kasus seperti itu untuk masa depan juga. Untuk melakukan ini, kami menambahkan elemen rintisan default ke skema ProseMirror. Kami menamai elemen ini unsupportedBlock. Rintisan muncul di tempat item yang tidak didukung. Kami mengubahnya sebagai persegi panjang abu-abu dengan teks yang menyatakan bahwa elemen ini tidak didukung dan tidak dapat diedit. Ketika posting disimpan, elemen seperti itu tetap tidak berubah dalam tubuh terstruktur. Pengguna dapat mengubah lokasi relatif terhadap elemen lain, tetapi konten internal elemen yang tidak diketahui tidak dapat diubah atau diedit. Namun, pengguna dapat menghapus elemen seperti itu, lalu, tentu saja,itu tidak akan disimpan dalam dokumen akhir.

Semua masalah yang dijelaskan terkait dengan kesulitan menerapkan editor WYSIWYG itu sendiri. Tetapi sementara itu ada dalam mode beta, kami tidak bisa meninggalkan editor lama di TinyMCE dan dipaksa untuk mendukung kedua editor, memberikan kompatibilitas ke belakang di antara mereka. Misalnya, Anda bisa membuat posting di editor WYSIWYG, simpan, lalu edit di TinyMCE, simpan, buka lagi di WYSIWYG, dan seterusnya. Akibatnya, saat dibuka di WYSIWYG, kami melihat konten yang sama dengan penyimpanan sebelumnya di TinyMCE. Untuk menerapkan kompatibilitas ke belakang, perlu mengirimkan konten HTML ke TinyMCE, yang telah kami pelajari untuk dibuat dari badan terstruktur dan simpan ke database sambil menyimpan posting. Dan ketika menyimpan posting melalui TinyMCE, konten yang dibuat di server dijalankan melalui layanan HTML2SB,sebagai hasilnya, kita dapat menyimpan HTML segar dan badan terstruktur.

HTML2SB adalah kebalikan dari apa yang dilakukan SB2HTML, yaitu, mengubah konten dari HTML ke tubuh terstruktur. Secara kronologis, layanan ini muncul lebih awal dari yang lain, karena sebelum pembuatan editor WYSIWYG, satu-satunya cara untuk mendapatkan konten posting dalam format tubuh terstruktur adalah penguraian langsung dari HTML. HTML2SB adalah bagian dari infrastruktur backend di sekitar editor posting, tetapi setelah meninggalkan TinyMCE, itu tidak lagi diperlukan.


4. Hasil Beta


Sekarang WYSIWYG-editor tersedia untuk semua pengguna dalam versi beta, dan akan segera menjadi editor utama posting Sports.ru. Kami telah menerima alat untuk membuat dan mengedit posting yang memenuhi sebagian besar persyaratan kami:

  • antarmuka editor menjadi jelas, ringkas dan modern, menulis posting panjang menjadi lebih mudah;
  • Sekarang Anda dapat mengunduh gambar dari file dan dengan tautan yang langsung ditempatkan di repositori kami;
  • menambahkan opsi untuk menyematkan sematan dari jaringan sosial utama dan situs hosting video;
  • membersihkan gaya pemformatan teks;
  • aplikasi seluler telah beralih ke menampilkan pos dari badan terstruktur dan dapat mengatur gaya mereka sendiri untuk konten.

Tentu saja, editor belum sepenuhnya didebug, kami secara berkala mendeteksi bug baru. Pembaruan berikut akan datang:

  • penyimpanan otomatis;
  • Versi WYSIWYG untuk pengguna dengan hak yang diperluas (administrator, editor penuh waktu);
  • membuat dan mengedit posting dari browser seluler;
  • Pesan tentang pengeditan dokumen secara paralel oleh beberapa pengguna;
  • tips dan orientasi;
  • widget statistik untuk tim olahraga, pertandingan, dan lineup.

Pada saat penulisan ini, lebih dari 13.000 posting telah diterbitkan melalui versi beta editor, yaitu sekitar 20% dari total jumlah teks pengguna di Sports.ru untuk periode dari Juni 2019 hingga Februari 2020 inklusif. Pangsa pos yang dibuat dan diterbitkan melalui editor baru terus berkembang.


Ara. 3. Proporsi posting pengguna dibuat dan dipublikasikan di editor baru

Tampaknya pertumbuhan organik dalam pangsa posting pengguna yang dibuat dan diterbitkan melalui editor baru adalah sinyal bahwa pengguna senang dengan pembaruan, yang juga dikonfirmasi oleh umpan balik dalam pengumuman peluncuran pengujian beta (beberapa dari mereka ditunjukkan pada Gambar. 4). Karenanya, dalam beberapa bulan mendatang kami berencana untuk sepenuhnya mentransfer pembuatan posting ke editor baru, sehingga hanya fokus pada dukungan dan pengembangannya. 
Omong-omong, fungsionalitas apa yang akan Anda tambahkan ke editor WYSIWYG kami?


Ara. 4. Komentar pengguna dalam posting dengan pengumuman pembaruan editor WYSIWYG 

All Articles