Menggunakan JSX sebagai view engine Express.js
Tags: jsx, express
Published: 2020-09-12 11:20:25

JSX adalah sebuah ekstensi sintaks javascript. Walaupun dipopulerkan oleh React, tapi JSX tidak sama dengan React. Ada banyak framework lain yang menggunakannya seperti [Preact](https://preactjs.com/), [Inferno](https://infernojs.org/), dan [Solid](https://github.com/ryansolid/solid). Pada artikel kali ini, saya akan pakai JSX sebagai view engine untuk Express.js

### Kenapa JSX? 

Karena pada dasarnya jsx adalah javascript, sehingga semua tools yang tersedia untuk javascript bisa kita pakai untuk membangun UI yang menarik. Kalau butuh satu function tinggal import atau bikin langsung di file yang sama.

Berbeda sekali dibandingkan menggunakan template engine seperti pug, ejs, nunjucks, dkk. Yang masing-masingnya memiliki sintaks sendiri dan kalau mau menambahkan satu fungsi helper perlu diregistrasikan dulu ke enginenya atau didaftarkan sebagai local variable di express.

Sebenarnya ada library yang sudah jadi yang menggunakan jsx di expressjs, tapi semuanya depends ke React. Saya ingin sesuatu yang sederhana dan hanya memproduksi plain html. Karena ga ketemu yang cocok, saya putuskan untuk mencoba membuatnya sendiri.

Setelah membaca halaman [*Developing template engines for Express*](https://expressjs.com/en/advanced/developing-template-engines.html), saya berkesimpulan sepertinya membuat custom template engine bukan hal yang sulit. Express hanya butuh  disediakan satu callback dengan signature `(filePath, options, callback) => void`

- `filePath` adalah lokasi file yang diinvoke dengan `res.render`. Misalnya jika diinvoke `res.render('index')`, value filePath adalah `/absolute/path/to/index.jsx`
- `options` adalah value dari parameter kedua `res.render` digabung dengan value lain yang disediakan oleh express.
- `callback` adalah function yang harus diinvoke dengan hasil rendering dalam bentuk string.

Ada satu library bagus yang mengubah jsx element menjadi plain html string yang bisa dipakai sebagai dasar untuk percobaan membuat view engine expressjs. Yaitu [vhtml](https://github.com/developit/vhtml) yang dibuat oleh creator [preact](https://preactjs.com/).

Untuk mentransformasi jsx menjadi javascript normal dengan `vhtml` function call, kita perlu menggunakan babel dengan plugin [@babel/plugin-transform-react-jsx](https://babeljs.io/docs/en/babel-plugin-transform-react-jsx).

Berikutnya agar bisa mengimport css dan menggunakan css-in-js, saya tambahkan webpack dengan css-loader. Untuk css-in-js, saya menggunakan [linaria](https://github.com/callstack/linaria) dengan [linaria/loader](https://github.com/callstack/linaria/blob/master/docs/BUNDLERS_INTEGRATION.md#webpack) untuk webpack. Dan tentu saja tidak lupa tambahan konfigurasi untuk [tailwindcss](https://dev.to/armedi/tailwind-css-dan-bagaimana-menggunakannya-dengan-create-react-app-7ba).

Hasil jadi dari percobaan ini bisa diakses di [https://whatsmyip.fly.dev](https://whatsmyip.fly.dev/).

Seperti inilah code untuk halaman home yang dibuat dengan jsx, dan menggunakan kombinasi linaria + tailwindcss untuk styling. 

{% gist https://gist.github.com/armedi/361830f36ebc938b96d4e40ce6feb750 file=app.js %}

{% gist https://gist.github.com/armedi/361830f36ebc938b96d4e40ce6feb750 file=home.jsx %}

Kenapa saya pakai linaria + tailwind, gak cuma tailwind aja? Karena hasil markup akhir terlihat lebih rapi dengan satu class saja, dan juga lebih gampang untuk mengkombinasikan tailwind dengan custom css yang kita tambahkan sendiri seandainya diperlukan.

{% gist https://gist.github.com/armedi/361830f36ebc938b96d4e40ce6feb750 file=rendered.html %}

Source code lengkapnya tersedia di

{% github armedi/express-jsx no-readme %}

referensi:

- https://github.com/saltyshiomix/react-ssr
- https://github.com/reactjs/express-react-views