Bermula dari Bolt.js Hingga Akhirnya Menjadi React.js

Ridwan Fajar 20 Oktober 2016

Bermula dari Bolt.js Hingga Akhirnya Menjadi React.js

React.js adalah salah satu teknologi client-side javascript yang kian meranjak mengikuti pendahulunya. Teknologi client-side ini dibuat untuk memudahkan web developer membangun user interface yang lebih mudah dikelola dan berbasis komponen. Tidak hanya itu, library ini pun dilengkapi dengan komunikasi data seperti AJAX yang sudah dibungkus sedemikian rupa sehingga memudahkan pengunanya. Seperti kita ketahui, jauh sebelum React.js ada, Angular.js, Ember.js, dan Backbone.js sudah lama bersaing di dunia teknologi client-side ini.

Dikutip dari Halaman Github Facebook, pada tanggal 28 September 2016 Vjeux menceritakan bagaimana kesuksesan React.js diraih hingga akhirnya mencapai 50.000 bintang di Github yang diberikan oleh pengguna Github kepada reposiori ini. Bermula dari Bolt.js, hingga akhirnya ditambahkan JSX, dan dipiloti oleh Instagram dengan menggunakan React.js di website-nya, itulah titik awal bagaimana React.js sukses. Mari kita simak cerita dari Vjeux yang dituliskannya di halaman Github Facebook React.js.

Selection_011

Cerita Awal

Tim React.js telah menghabiskan waktu yang cukup banyak untuk menjelaskan konsep bagaimana React.js bekerja dan masalah yang harus diselesaikannya, tapi hingga belum ada waktu untuk membicarakan React.js yang begitu cepat berevolusi sebelum di-opensource-kan. Milestone ini merupakan waktu yang menyenangkan dan awal yang baik.

Cerita dimulai ketika di divisi ads, ingin membangun aplikasi client-side web yang keren dan memukau menggunakan MVC framework milik internal yang bernama Bolt.js. Berikut adalah contoh kodenya:

var CarView = require('javelin/core').createClass({
  name: 'CarView',
  extend: require('container').Container,
  properties: {
    wheels: 4,
  },
  declare: function() {
    return {
      childViews: [
        { content: 'I have ' },
        { ref: 'wheelView' },
        { content: ' wheels' }
      ]
    };
  },
  setWheels: function(wheels) {
    this.findRef('wheelView').setContent(wheels);
  },
  getWheels: function() {
    return this.findRef('wheelView').getContent();
  },
});

var car = new CarView();
car.setWheels(3);
car.placeIn(document.body);
//<div>
//  <div>I have </div>
//  <div>3</div>
//  <div> wheels</div>
//</div>

Bolt mengenalkan sejumlah API dan fitur yang mungkin akan melahirkan React.js seperti render, createClass, dan refs. Bolt memperkenalkan konsep seperti refs yang dapat membuat referensi ke nodes dan dapat digunakan secara imperatif. Hal ini sangat relevan untuk interoperabilitas dengan sistem yang sudah ada ataupun penggunaan secara bertahap. Walaupun pada saat itu React.js diharapkan lebih functional, refs membuktikan kegunaannya tanpa harus menghancurkan paradigma functional yang semakin populer.

[caption id="attachment_12923" align="aligncenter" width="700"]Halaman github Bolt.js Halaman github Bolt.js[/caption]

Tapi dengan aplikasi yang terus membesar dan semakin keren, codebase Bolt semakin membingungkan. Melihat framework lainnya yang dikembangkan oleh Jordan Walke dengan FaxJS-nya, masalah yang dihadapi pun hampir sama dengan Bolt. Namun dia dapat menyelesaikannya dengan cara yang berbeda. Disinilah React.js versi awal mulai lahir termasuk props, state, server-side rendering, dan konsep dasar component.

TestProject.PersonDisplayer = {
  structure : function() {
    return Div({
      classSet: { personDisplayerContainer: true },
      titleDiv: Div({
        classSet: { personNameTitle: true },
        content: this.props.name
      }),
      nestedAgeDiv: Div({
        content: 'Interests: ' + this.props.interests
      })
    });
  }
};

FBolt Lahir ke Dunia

Dengan eksperiman FaxJS-nya, Jordan memberikan saran untuk perubahan API yang lebih baik dan lebih skalabel dalam membangun user interface. Dia mengimport library-nya ke codebase Facebook pada Maret 2012 dan menamainya dengan FBolt, ekstensi penting untuk Bolt yang komponennya ditulis menggunakan gaya functional programming. Mungkin "FBolt" ada singkatan FaxJS-nya tapi dia tidak memberitahu apapun tentang ini.

Interoperabilitas antara FBolt dan Bolt membuat kita untuk bereksperimen dengan mengganti satu komponen sekali saja dengan lebih banyak API komponen functional. Kami dapat test the waters paradigma functional baru kami tanpa harus melangkah lebih dalam. Kami mulai dengan komponen yang sangat jelas fungsionalitasnya terlebih dahulu.

Melihat FBolt tidak akan menjadi nama yang keren untuk library miliknya, Jordan Walke dan Tom Occhino memutuskan memberi nama baru yang disebut dengan "React". Setelah Tom mengirimkan diff untuk mengubah seluruh nama menjadi React, Jordan berkomentar:

Jordan Walke: I might add for the sake of discussion, that many systems advertise some kind of reactivity, but they usually require that you set up some kind of point-to-point listeners and won't work on structured data. This API reacts to any state or property changes, and works with data of any form (as deeply structured as the graph itself) so I think the name is fitting.
Saat itu, kebanyakan commit Tom adalah untuk pengembangan versi awal GraphiQL, proyek yang baru saja di-open source-kan.

Menambahkan Bumbu yang Bernama JSX

Sejak sekitar 2010, Facebook telah menggunakan ekstensi PHP yang dinamakan XHP, yang dapat membuat kita untuk membuat UI dengan menggunakan XML di dalam kode PHP langsung. Hal ini pertama kali diperkenalkan untuk mencegah lubang XSS tapi akhirnya membuat struktur aplikasi dengan cara yang bagus.
final class :a:post extends :x:element {
  attribute :a;
  protected function render(): XHPRoot {
    $anchor = <a>{$this->getChildren()}</a>;
    $form = (
      <form
        method="post"
        action={$this->:href}
        target={$this->:target}
        class="postLink"
      >{$anchor}</form>
    );
    $this->transferAllAttributes($anchor);
    return $form;
  }
}

Sebelum Jordan bergabung, Adam Hupp telah mengimplementasikan konsep seperti XHP untuk Javascript yang ditulis dalam Haskell. Sistem ini dapat membuat Anda menulis kode XML di dalam file Javascript seperti berikut:

function :example:hello(attrib, children) {
  return (
    <div class="special">
      <h1>Hello, World!</h1>
      {children}
    </div>
  );
}

Kode diatas akan di-compile menjadi kode Javascript ES3-compatible seperti berikut:

function jsx_example_hello(attrib, children) {
  return (
    S.create("div", {"class": "special"}, [
      S.create("h1", {}, ["Hello, World!"]),
      children
    ]
  );
}

Di dalam purwarupa ini, S.create akan dengan segera membuat dan mengembalikan sebuah DOM node. Selama obrolan masalah ini semua mengerucut pada masalah performa antara innerHTML dan pembuatan DOM node scara langsung. Pada waktu itu, sangat kurang ideal bila harus mengajak developer untuk menghindari pembuatan DOM node secara langsung karena masalah performa. CTO Facebook saat itu, Bret Taylor, tetap menyarangkan penggunaan innerHTML ketimbang document.createElement.

Bret Taylor: If you are not convinced about innerHTML, here is a small microbenchmark. It is about the same in Chrome. innerHTML is about 30% faster in the latest version of Firefox (much more in previous versions), and about 90% faster in IE8.
Kedatangan React.js membuat masalah ini menjadi lebih cerah. Konsep "Virtual DOM" yang dikenalkan oleh Jordan menepis masalah performa yang telah dibahas sebelumnya.
Jordan Walke: For the first step, I propose that we do the easiest, yet most general transformation possible. My suggestion is to simply map xml expressions to function call expressions.
    &lt;x&gt;&lt;/x&gt; becomes x( )
    &lt;x height=12&gt;&lt;/x&gt; becomes x( {height:12} )
    &lt;x&gt; &lt;y&gt; &lt;/y&gt; &lt;/x&gt; becomes x({ childList: [y( )] })

At this point, JSX doesn't need to know about React - it's just a convenient way to write function calls. Coincidentally, React's primary abstraction is the function. Okay maybe it's not so coincidental ;)

Adam memberikan komentar menarik pada masalah ini, yang sekarang menjadi cara paling umum menulis sebuah list di React.js dengan JSX.

Adam Hupp: I think we should just treat arrays of elements as a frag. This is useful for constructs like:

    <ul>{foo.map(function(i) { return <li>{i.data}</li>; })}</ul>

In this case the ul(..) will get a childList with a single child, which is itself a list.

React.js tidak berakhir pada implementasi Adam saja. Kami membuat JSX dengan mem-fork js-xml-literal, sebuah side project yang dikerjakan oleh pembuat XHP, Marcel Laverdet. JSX mengambil namanya dari js-xml-literal, yang dimodifikasi Jordan untuk membuat nested function call yang lebih dalam.

API Campuraduk

Selama awal masa - masa React.js, penggunaan internal tumbuh dengan cepat tapi ada berbagai churn dalam API komponen seperti konvensi penggunaan nama:
  • project diganti menjadi declare kemudian menjadi structure dan akhirnya menjadi render
  • Componentize diganti namanya menjadi createComponent dan akhirnya menjadi createClass
Sehubungan dengan akan di-opensource-kannya proyek ini, Lee Byron duduk bersama dengan Jordan Walke, Tom Occhino, dan Sebastian Markbage untuk merefaktor, mengimplementasikan ulang, dan mengganti nama salah satu bagian React.js yang paling disukai - lifecycle API. Lee akhirnya datang dengan well-designed API yang masih ada hingga hari ini. Berikut adalah API rancangan Lee tersebut:
  • Concepts
    • component - a ReactComponent instance
    • state - internal state terhadap komponent
    • props - external state terhadap komponent
    • markup - sebuah string HTML yang dihasilkan oleh komponen
    • DOM - dokumen dan elemen di dalam dokumen
  • Actions
    • mount - untuk menaruh komponen ke dalam DOM
    • initialize - menyiapkan komponen untuk proses rendering
    • update - transition of state yang menghasilkan render.
    • render - side-effect-free process untuk mendapatkan markup suatu komponen.
    • validate - membuat pengujian apakah sesuatu sudah dibuat atau disediakan
    • destroy - kebalikan dari initialize
  • Operands
    • create - membuat sesuatu yang baru
    • get - mengambil sesuatu yang sudah ada
    • set - menggabungkan sesuatu ke yang sudah ada
    • replace - menimpa yang sudah ada
    • receive - tanggapan terhadap data yang diberikan
    • force - melewati aksi
  • Notifications
    • shouldObjectAction
    • objectWillAction
    • objectDidAction

Instagram

Pada tahun 2012, Instagram diakuisisi oleh Facebook. Pete Hunt, yang waktu itu bekerja untuk Facebook Photo dan Video, bergabung dengan tim web yang baru dibentuk. Dia ingin membangun website-nya dengan React.js seluruhnya, yang justru berseberangan dengan penggunaan bertahap yang digunakan oleh Facebook.

Untuk membuat hal ini terjadi, React.js harus di-decouple dari infrastruktur Facebook, karena Instagram tidak menggunakan sedikit pun. Proyek ini merupakan sebuah keharusan agar React.js dapat di-open source-kan. Selama proses, Pete juga menemukan dan mempromosikan sebuah proyek kecil bernama Webpack. Dia juga mengimplementasikan cikal bakal renderToString yang dibutuhkan untuk server-side rendering.

Sambil menyiapkan untuk membuat React.js open source, Maykel Loomans, desainer dari Instagram, membuat rancangan website untuk React.js akan seperti apa. Header halaman tersebut memberikan kesan identitasi visual bagaimana React.js terlihat dan logonya berwarna biru elektrik.

Pada masa awal terbentuknya, React.js mendapat banyak sekali berbagai macam saran, ide, dan kontribusi teknis dari pengguna dan kolaborator awal di seluruh tempat di Facebook. Mungkin ini terlihat seperti keajaiban satu malam, tapi cerita perjalanannya merupakan contoh besar bagaimana sebuah ide baru harus mengalami sejumlah perbaikan, perjalanan, dan perbaikan dalam waktu yang panjang sebelum akhirnya mencapai potensi penuh ide tersebut.

Pendekatan React.js adalah membangun user interface dengan prinsip functional programming telah mengubah bagaimana cara kita membuat user interface dalam beberapa tahun terakhir. Kita dapat melihat hal tersebut dengan sendirinya, tapi React.js tidak akan menjadi apapun tanpa kehadiran komunitas open source yang luar biasa dalam membangun proyek ini.

(rfs/reactjs/facebook)