Pembaruan: jawaban ini tampaknya cukup populer sehingga saya mengambil sedikit waktu untuk membersihkannya sedikit, menambahkan beberapa info baru dan mengklarifikasi beberapa hal yang saya pikir tidak cukup jelas. Berikan komentar jika Anda merasa ada hal lain yang perlu diklarifikasi atau diperbarui.
Sebagian besar kekhawatiran Anda benar-benar masalah pendapat dan preferensi pribadi, tetapi saya akan mencoba menjawab secara objektif yang saya bisa:
Native vs. Compiled
Tulis JavaScript dalam vanilla JavaScript, tulis CSS dalam CSS, tulis HTML dalam HTML.
Kembali pada hari ada perdebatan panas apakah seseorang harus menulis Majelis asli dengan tangan atau menggunakan bahasa tingkat yang lebih tinggi seperti C untuk membuat kompiler menghasilkan kode Majelis untuk Anda. Bahkan sebelum itu orang menolak untuk mempercayai perakit dan lebih suka menulis kode mesin asli dengan tangan ( dan saya tidak bercanda ).
Sementara itu, hari ini ada banyak orang yang menulis HTML di Haml atau Jade , CSS di Sass atau Kurang dan JavaScript dalam CoffeeScript atau TypeScript . Itu disana. Berhasil. Beberapa orang lebih menyukainya, beberapa tidak.
Intinya adalah bahwa tidak ada yang salah secara fundamental dalam tidak menulis JavaScript dalam JavaScript vanilla, CSS dalam CSS, dan HTML dalam HTML. Ini benar-benar masalah preferensi.
DSL Internal vs. Eksternal
Enkapsulasi gaya menggunakan Shadow DOM React memiliki ini, yang membutuhkan penulisan CSS dalam JavaScript. Tidak cantik.
Cantik atau tidak, tentu ekspresif. JavaScript adalah bahasa yang sangat kuat, jauh lebih kuat daripada CSS (bahkan termasuk salah satu dari preprosesor CSS). Ini tergantung pada apakah Anda lebih suka DSL internal atau eksternal untuk hal-hal semacam itu. Sekali lagi, masalah preferensi.
(Catatan: Saya berbicara tentang gaya sebaris di Bereaksi yang direferensikan dalam pertanyaan asli.)
Jenis DSL - penjelasan
Pembaruan: Membaca jawaban saya beberapa saat setelah menulisnya, saya pikir saya perlu menjelaskan apa yang saya maksud di sini. DSL adalah bahasa khusus domain dan dapat berupa internal (menggunakan sintaks dari bahasa host seperti JavaScript - seperti misalnya Bereaksi tanpa JSX, atau seperti gaya inline dalam Bereaksi yang disebutkan di atas) atau bisa juga eksternal (menggunakan sintaks berbeda daripada bahasa host - seperti dalam contoh ini akan inlining CSS (DSL eksternal) di dalam JavaScript).
Ini dapat membingungkan karena beberapa literatur menggunakan istilah yang berbeda dari "internal" dan "eksternal" untuk menggambarkan jenis-jenis DSL. Terkadang "tertanam" digunakan alih-alih "internal" tetapi kata "tertanam" dapat memiliki arti yang berbeda - misalnya Lua digambarkan sebagai "Lua: bahasa yang disematkan yang dapat diperluas" di mana tertanam tidak ada hubungannya dengan DSL (internal) yang tertanam (dalam) yang merasakannya justru sebaliknya - DSL eksternal) tetapi itu berarti bahwa itu tertanam dalam arti yang sama bahwa, katakanlah, SQLite adalah database tertanam. Bahkan ada eLua di mana "e" adalah singkatan dari "embedded" dalam arti ketiga - yang dimaksudkan untuk embedded system! Itu sebabnya saya tidak suka menggunakan istilah "DSL yang disematkan" karena hal-hal seperti eLua dapat menjadi "DSL" yang "tertanam" dalam dua pengertian yang berbeda dan sama sekali tidak menjadi "DSL yang disematkan"!
Untuk membuat keadaan menjadi lebih buruk, beberapa proyek bahkan menimbulkan lebih banyak kebingungan. Misalnya. Template seterika dijelaskan sebagai "bebas DSL", padahal sebenarnya ini hanyalah contoh sempurna dari DSL internal dengan sintaksis seperti:map.where('href').is('/').insert('newurl');
Yang telah dikatakan, ketika saya menulis "JavaScript adalah bahasa yang sangat kuat, jauh lebih kuat daripada CSS (bahkan termasuk salah satu preprosesor CSS). Itu tergantung pada apakah Anda lebih suka DSL internal atau eksternal untuk hal-hal semacam itu. Sekali lagi, masalah preferensi. " Saya berbicara tentang dua skenario itu:
Satu:
/** @jsx React.DOM */
var colored = {
color: myColor
};
React.renderComponent(<div style={colored}>Hello World!</div>, mountNode);
Dua:
// SASS:
.colored {
color: $my-color;
}
// HTML:
<div class="colored">Hello World!</div>
Contoh pertama menggunakan apa yang dijelaskan dalam pertanyaan sebagai: "menulis CSS dalam JavaScript. Tidak cantik." Contoh kedua menggunakan Sass. Meskipun saya setuju bahwa menggunakan JavaScript untuk menulis CSS mungkin tidak cukup (untuk beberapa definisi "cantik") tetapi ada satu keuntungan melakukannya.
Saya dapat memiliki variabel dan fungsi di Sass, tetapi apakah cakupannya secara leksikal atau dinamis? Apakah mereka diketik secara statis atau dinamis? Kuat atau lemah? Bagaimana dengan tipe numerik? Ketik pemaksaan? Nilai-nilai mana yang benar dan mana yang salah? Bisakah saya memiliki fungsi tingkat tinggi? Pengulangan? Panggilan ekor? Penutupan leksikal? Apakah mereka dievaluasi dalam urutan normal atau urutan aplikatif? Apakah ada evaluasi malas atau bersemangat? Apakah argumen untuk fungsi dilewatkan oleh nilai atau dengan referensi? Apakah mereka bisa berubah? Abadi? Gigih? Bagaimana dengan benda? Kelas? Prototipe? Warisan?
Itu bukan pertanyaan sepele, namun saya harus tahu jawaban mereka jika saya ingin mengerti kode Sass atau Less. Saya sudah tahu jawaban-jawaban untuk JavaScript sehingga itu berarti bahwa saya sudah mengerti setiap DSL internal (seperti gaya inline dalam Bereaksi) pada tingkat-tingkat itu jadi jika saya menggunakan Bereaksi maka saya harus tahu hanya satu set jawaban untuk itu (dan banyak yang serupa ) pertanyaan, sedangkan ketika saya gunakan untuk mis. Sass dan Setang kemudian saya harus tahu tiga set jawaban itu dan memahami implikasinya.
Ini bukan untuk mengatakan bahwa salah satu cara atau yang lain selalu lebih baik tetapi setiap kali Anda memperkenalkan bahasa lain ke campuran maka Anda membayar harga yang mungkin tidak begitu jelas pada pandangan pertama, dan harga ini adalah kompleksitas.
Saya harap saya mengklarifikasi apa yang awalnya saya maksudkan sedikit.
Pengikatan data
Ikatan dua arah
Ini adalah subjek yang sangat menarik dan sebenarnya juga masalah preferensi. Dua arah tidak selalu lebih baik dari satu arah. Ini pertanyaan tentang bagaimana Anda ingin memodelkan keadaan yang bisa berubah dalam aplikasi Anda. Saya selalu melihat ikatan dua arah sebagai ide yang agak bertentangan dengan prinsip-prinsip pemrograman fungsional tetapi pemrograman fungsional bukan satu-satunya paradigma yang berfungsi, beberapa orang lebih menyukai perilaku semacam ini dan kedua pendekatan tampaknya bekerja dengan cukup baik dalam praktiknya. Jika Anda tertarik dengan detail keputusan desain yang terkait dengan pemodelan keadaan dalam React, saksikan ceramah oleh Pete Hunt (ditautkan dalam pertanyaan) dan ceramah oleh Tom Occhino dan Jordan Walke yang menjelaskannya dengan sangat baik di pendapat saya.
Perbarui: Lihat juga pembicaraan lain oleh Pete Hunt: Dapat diprediksi, tidak benar: pemrograman DOM fungsional .
Pembaruan 2: Perlu dicatat bahwa banyak pengembang menentang aliran data dua arah, atau mengikat dua arah, beberapa bahkan menyebutnya sebagai anti-pola. Ambil contoh arsitektur aplikasi Flux yang secara eksplisit menghindari model MVC (yang terbukti sulit untuk skala untuk aplikasi Facebook dan Instagram besar) yang mendukung aliran data searah (lihat Hacker Way: Memikirkan Kembali Pengembangan Aplikasi Web di Facebook talk oleh Tom Occhino, Jing Chen dan Pete Hunt untuk perkenalan yang bagus). Juga, banyak kritik terhadap AngularJS (kerangka kerja Web paling populer yang didasarkan pada model MVC, yang dikenal untuk pengikatan data dua arah) termasuk argumen terhadap aliran data dua arah, lihat:
Pembaruan 3: Artikel menarik lainnya yang menjelaskan beberapa masalah yang didiskusikan di atas adalah Mendekonstruksi Fluks ReactJS - Tidak menggunakan MVC dengan ReactJS oleh Mikael Brassman, penulis RefluxJS (perpustakaan sederhana untuk arsitektur aplikasi aliran data searah yang diilhami oleh Flux).
Pembaruan 4: Ember.js saat ini sedang menjauh dari pengikatan data dua arah dan dalam versi mendatang itu akan menjadi satu arah secara default. Lihat: Pembicaraan Masa Depan Ember oleh Stefan Penner dari Simposium Embergarten di Toronto pada 15 November 2014.
Pembaruan 5: Lihat juga: The Road to Ember 2.0 RFC - diskusi menarik dalam permintaan tarik oleh Tom Dale :
"Ketika kami merancang lapisan templating asli, kami menduga bahwa membuat semua ikatan data dua arah tidak terlalu berbahaya: jika Anda tidak menetapkan ikatan dua arah, itu adalah pengikatan satu arah de facto!
Kami telah menyadari (dengan bantuan dari teman-teman kami di React), bahwa komponen ingin dapat membagikan data kepada anak-anak mereka tanpa harus waspada terhadap mutasi yang tidak patuh.
Selain itu, komunikasi antar komponen seringkali paling alami diungkapkan sebagai peristiwa atau panggilan balik . Ini dimungkinkan dalam Ember, tetapi dominasi pengikatan data dua arah sering membuat orang menggunakan jalur pengikatan dua arah sebagai saluran komunikasi . Pengembang Ember yang berpengalaman tidak (biasanya) melakukan kesalahan ini, tapi itu mudah dilakukan. " [Penekanan ditambahkan]
Asli vs VM
Dukungan browser asli (baca "dijamin lebih cepat")
Sekarang akhirnya sesuatu yang bukan masalah pendapat.
Sebenarnya di sini justru sebaliknya. Tentu saja "asli" kode dapat ditulis dalam C ++ tetapi apa yang Anda pikirkan mesin JavaScript ditulis?
Sebenarnya mesin JavaScript benar-benar luar biasa dalam optimasi yang mereka gunakan saat ini - dan tidak hanya V8 lagi, juga SpiderMonkey dan bahkan Chakra bersinar hari ini. Dan perlu diingat bahwa dengan kompiler JIT kode tidak hanya sebagai asli seperti yang mungkin tetapi ada juga peluang optimasi waktu berjalan yang tidak mungkin dilakukan dalam kode yang dikompilasi secara statis.
Ketika orang-orang berpikir bahwa JavaScript lambat, mereka biasanya berarti JavaScript yang mengakses DOM. DOM lambat. Ini asli, ditulis dalam C ++ dan masih sangat lambat karena kompleksitas yang harus diimplementasikan.
Buka konsol Anda dan tulis:
console.dir(document.createElement('div'));
dan lihat berapa banyak properti yang div
harus diimplementasikan oleh elemen kosong yang bahkan tidak melekat pada DOM. Ini hanya properti tingkat pertama yang "properti sendiri" yaitu. tidak diwarisi dari rantai prototipe:
menyelaraskan, menunggu, onvolumechange, ontimeupdate, onsuspend, onsubmit, onshow, onselect, onseeking, onseeked, onscroll, onreset, onratet, onratechange, pada progres, bermain, onplay, onpause, onmumewewheel, onmouse, onmouse, onmouse, onmouse, onmouse, onmouse, onmouse, onmouse, onmouse, onmouse, onmouse, onmouse, onmome, onmome, onmome, onmouse). onmouseenter, onmousedown, onloadstart, onloadedmetadata, onloadeddata, onloadup, onkeyupress, onkeydown, oninvalid, oninput, onfokus, onerror, onending, ondtingkatkan, ondurationchange, ondrop, ondragstartterubah, ondrag ondragd ondddakdakadakdakdakakdakakdakakdakakadidakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakakimakanakanakanakanakandilemparkan, oncontextmenu, onclose, onclick, onchange, oncanplaythrough, oncanplay, oncancel, onabort, onabort, spellcheck, isContentEditable, contentEditable, outerText, innerText, accessKey, tersembunyi, webkitdropzone, draggable, tabIndex, direktori, jumlah, trans, jumlah, trans, tanda, jumlah, trans, tanda, jumlah, terjemahan,firstElementChild, anak-anak, nextElementSibling, sebelumnyaElementSibling, onwheel, onwebkitfullscreenerror, onwebkitfullscreenchange, onstectstart, onearch, onpaste, oncopy, onbeforepaste, onbeforecut, onbeforecut, onbeforecut, onbeforecut, onbeforecopy, scrollhobe, scrolldalam scrollhttp, penggambaranHal clientHeight, clientWidth, clientTop, clientLeft, offsetParent, offsetHeight, offsetWidth, offsetTop, offsetLeft, localName, awalan, namespaceURI, id, gaya, atribut, tagName, parentElement, textContent, baseURI, pemilikDokumen, anak-anak, pesan terakhir, natal parentNode, nodeType, nodeValue, nodeNameoncopy, onbeforepaste, onbeforecut, onbeforecopy, webkitShadowRoot, dataset, classList, className, outerHTML, innerHTML, scrollTinggi, scrollLebar, scrollTop, scrollLeft, clientHeight, clientLebar, clientTop, clientLeft, offsetTanggal, offsettangguh, offsettangguh ,tempuhtanggal namespaceURI, id, style, atribut, tagName, parentElement, textContent, baseURI, ownerDocument, NextSibling ,Segling sebelumnya, LastChild, firstChild, childNode, parentNode, nodeType, nodeValue, nodeNameoncopy, onbeforepaste, onbeforecut, onbeforecopy, webkitShadowRoot, dataset, classList, className, outerHTML, innerHTML, scrollTinggi, scrollLebar, scrollTop, scrollLeft, clientHeight, clientLebar, clientTop, clientLeft, offsetTanggal, offsettangguh, offsettangguh ,tempuhtanggal namespaceURI, id, style, atribut, tagName, parentElement, textContent, baseURI, ownerDocument, NextSibling ,Segling sebelumnya, LastChild, firstChild, childNode, parentNode, nodeType, nodeValue, nodeNameparentElement, textContent, baseURI, ownerDocument, nextSibling ,Segling sebelumnya, LastChild, firstChild, childNode, parentNode, nodeType, nodeType, nodeValue, nodeNameparentElement, textContent, baseURI, ownerDocument, nextSibling ,Segling sebelumnya, LastChild, firstChild, childNode, parentNode, nodeType, nodeType, nodeValue, nodeName
Banyak dari mereka sebenarnya adalah objek bersarang - untuk melihat properti level kedua (milik) asli yang kosong div
di browser Anda, lihat biola ini .
Maksud saya serius, properti onvolumechange pada setiap node div tunggal? Apakah ini sebuah kesalahan? Tidak, itu hanya versi lama DOM Level 0 versi model acara tradisional dari salah satu penangan acara "yang harus didukung oleh semua elemen HTML , karena atribut konten dan atribut IDL" [penekanan ditambahkan] pada Bagian 6.1.6.2 dari spesifikasi HTML oleh W3C - tidak ada jalan lain.
Sementara itu, ini adalah properti tingkat pertama dari DOM palsu div
di Bereaksi:
alat peraga, _owner, _lifeCycleState, _pendingProps, _pendingCallbacks, _pendingOwner
Cukup berbeda, bukan? Sebenarnya ini adalah seluruh objek yang diserialisasi ke JSON ( LIVE DEMO ), karena hei Anda benar - benar dapat membuat serial menjadi JSON karena tidak mengandung referensi melingkar - sesuatu yang tidak terpikirkan dalam dunia DOM asli (di mana ia hanya akan melemparkan pengecualian) ):
{
"props": {},
"_owner": null,
"_lifeCycleState": "UNMOUNTED",
"_pendingProps": null,
"_pendingCallbacks": null,
"_pendingOwner": null
}
Ini cukup banyak alasan utama mengapa Bereaksi bisa lebih cepat daripada DOM browser asli - karena tidak harus menerapkan kekacauan ini .
Lihat presentasi ini oleh Steven Luscher untuk melihat apa yang lebih cepat: DOM asli ditulis dalam C ++ atau DOM palsu yang seluruhnya ditulis dalam JavaScript. Ini adalah presentasi yang sangat adil dan menghibur.
Pembaruan: Ember.js dalam versi yang akan datang akan menggunakan DOM virtual yang sangat terinspirasi oleh React untuk meningkatkan kinerja. Lihat: Pembicaraan Masa Depan Ember oleh Stefan Penner dari Simposium Embergarten di Toronto pada 15 November 2014.
Singkatnya: fitur-fitur dari Komponen Web seperti templat, pengikatan data, atau elemen kustom akan memiliki banyak keunggulan dibandingkan Bereaksi tetapi sampai model objek dokumen itu sendiri secara signifikan disederhanakan maka kinerja tidak akan menjadi salah satunya.
Memperbarui
Dua bulan setelah saya memposting jawaban ini ada beberapa berita yang relevan di sini. Seperti yang baru saja saya tulis di Twitter , versi terbaru dari editor teks Atom yang ditulis oleh GitHub di JavaScript menggunakan Facebook's React untuk mendapatkan kinerja yang lebih baik meskipun menurut Wikipedia "Atom didasarkan pada Chromium dan ditulis dalam C ++" sehingga memiliki kontrol penuh terhadap implementasi DOM asli C ++ (lihat Inti dari Atom ) dan dijamin memiliki dukungan untuk Komponen Web karena ia dikirim dengan browser web sendiri. Ini hanyalah contoh yang sangat baru dari proyek dunia nyata yang dapat menggunakan jenis pengoptimalan lain yang biasanya tidak tersedia untuk aplikasi Web, namun ia telah memilih untuk menggunakan React yang ditulis dalam JavaScript, untuk mencapai kinerja terbaik, meskipun Atom tidak dibangun dengan React untuk memulai, jadi melakukan itu bukan perubahan sepele.
Perbarui 2
Ada perbandingan yang menarik oleh Todd Parker menggunakan WebPagetest untuk membandingkan kinerja contoh-contoh TodoMVC yang ditulis dalam Angular, Backbone, Ember, Polymer, CanJS, YUI, Knockout, React, dan Shoestring. Ini adalah perbandingan paling objektif yang pernah saya lihat sejauh ini. Yang penting di sini adalah bahwa semua contoh masing-masing ditulis oleh para ahli dalam semua kerangka kerja tersebut, semuanya tersedia di GitHub dan dapat ditingkatkan oleh siapa saja yang berpikir bahwa beberapa kode dapat dioptimalkan untuk berjalan lebih cepat.
Perbarui 3
Ember.js dalam versi mendatang akan mencakup sejumlah fitur Bereaksi yang dibahas di sini (termasuk DOM virtual dan pengikatan data searah, untuk menyebutkan beberapa) yang berarti bahwa ide-ide yang berasal dari Bereaksi sudah bermigrasi ke kerangka kerja lain. Lihat: The Road to Ember 2.0 RFC - diskusi menarik dalam permintaan tarik oleh Tom Dale (Tanggal Mulai: 2014-12-03): "Di Ember 2.0, kita akan mengadopsi" virtual DOM "dan model aliran data yang mencakup ide terbaik dari Bereaksi dan menyederhanakan komunikasi antar komponen. "
Selain itu, Angular.js 2.0 menerapkan banyak konsep yang dibahas di sini.
Perbarui 4
Saya harus menguraikan beberapa masalah untuk menjawab komentar ini oleh Igwe Kalu:
"Tidak masuk akal untuk membandingkan React (JSX atau output kompilasi) dengan JavaScript biasa, ketika React pada akhirnya berkurang menjadi JavaScript biasa. [...] Apapun strategi yang digunakan Bereaksi untuk penyisipan DOM dapat diterapkan tanpa menggunakan React. Dikatakan, itu tidak menambahkan manfaat khusus saat mempertimbangkan fitur yang dipermasalahkan selain kenyamanan. " (komentar lengkap di sini )
Dalam hal itu tidak cukup jelas, sebagian dari jawaban saya, saya membandingkan kinerja operasi langsung pada DOM asli (diimplementasikan sebagai objek host di browser) vs DOM palsu / virtual Dire (diterapkan dalam JavaScript). Titik Saya mencoba untuk membuat adalah bahwa DOM maya diimplementasikan dalam JavaScript dapat mengungguli DOM nyata diimplementasikan dalam C ++ dan tidak yang Bereaksi dapat mengungguli JavaScript (yang jelas tidak akan masuk akal karena ini ditulis dalam JavaScript). Maksud saya adalah bahwa kode "asli" C ++ tidak selalu dijamin lebih cepat daripada JavaScript "tidak asli". Menggunakan Bereaksi untuk menggambarkan titik itu hanyalah sebuah contoh.
Namun komentar ini menyentuh masalah yang menarik. Dalam arti tertentu memang benar bahwa Anda tidak memerlukan kerangka kerja apa pun (Bereaksi, Sudut atau jQuery) untuk alasan apa pun (seperti kinerja, portabilitas, fitur) karena Anda selalu dapat membuat ulang apa yang dilakukan kerangka kerja untuk Anda dan menemukan kembali roda - jika Anda dapat membenarkan biayanya, yaitu.
Tapi - seperti Dave Smith baik memasukkannya ke dalam Bagaimana kehilangan titik ketika membandingkan kinerja kerangka web : "Ketika membandingkan dua kerangka web, pertanyaannya adalah tidak bisa aplikasi saya cepat dengan kerangka X. Pertanyaannya adalah akan app saya cepat dengan kerangka X. "
Dalam jawaban 2011 saya untuk: Apa beberapa alasan teknis empiris untuk tidak menggunakan jQuery Saya menjelaskan masalah yang sama, bahwa bukan tidak mungkin untuk menulis kode DOM-manipulasi portabel tanpa perpustakaan seperti jQuery, tetapi orang jarang melakukannya.
Saat menggunakan bahasa pemrograman, perpustakaan atau kerangka kerja, orang cenderung menggunakan cara yang paling nyaman atau idiomatis dalam melakukan sesuatu, bukan yang sempurna tetapi tidak nyaman. Nilai sebenarnya dari kerangka kerja yang baik adalah memudahkan apa yang seharusnya sulit dilakukan - dan rahasianya adalah membuat hal-hal yang benar nyaman. Hasilnya masih memiliki kekuatan yang persis sama yang Anda inginkan sebagai bentuk paling sederhana dari kalkulus lambda atau mesin Turing paling primitif, tetapi ekspresi relatif dari konsep-konsep tertentu berarti bahwa konsep-konsep tersebut cenderung diekspresikan lebih mudah atau sama sekali, dan bahwa solusi yang tepat tidak hanya mungkin tetapi sebenarnya diimplementasikan secara luas.
Perbarui 5
React + Performance =? artikel oleh Paul Lewis dari Juli 2015 menunjukkan contoh di mana React lebih lambat daripada JavaScript vanilla yang ditulis tangan untuk daftar gambar Flickr yang tak terbatas, yang khususnya penting di ponsel. Contoh ini menunjukkan bahwa setiap orang harus selalu menguji kinerja untuk kasus penggunaan khusus dan platform serta perangkat target tertentu.
Terima kasih kepada Kevin Lozandier karena membawanya ke perhatian saya .