Tutorial Progressive Web Components dengan Elena.js
AW
Axel W

Dipublikasikan 1 Agustus 2026

Tutorial Progressive Web Components dengan Elena.js

Web components telah lama dianggap sebagai fondasi ideal untuk design system karena portability-nya di berbagai framework. Namun, masalah seperti flash of unstyled content, ketergantungan pada JavaScript client-side, dan keterbatasan server-side rendering sering menghambat adopsinya di skala enterprise. Elena.js hadir sebagai solusi dengan pendekatan progressive web components: render HTML dan CSS terlebih dahulu, baru kemudian dihydrate dengan JavaScript. Artikel ini membahas panduan praktis membangun progressive web components menggunakan Elena.js untuk design system yang bekerja di React, Vue, Angular, maupun vanilla HTML.

Apa itu Progressive Web Component?

Progressive Web Component adalah native Custom Element yang dibangun dalam dua lapisan utama. Lapisan pertama adalah HTML dan CSS yang merender seketika tanpa memerlukan JavaScript. Lapisan kedua adalah JavaScript yang menambahkan reaktivitas, event handling, dan templating lebih advanced. Pendekatan ini memastikan komponen tetap accessible, bebas layout shift, dan kompatibel dengan SSR sejak awal.

Berdasarkan filosofi dari Elena.js, terdapat tiga tipe komponen yang perlu dipahami. Composite Components mengekspos HTML di Light DOM dan mengekspresikan state melalui markup yang sudah ada. Primitive Components bersifat self-contained dan merender HTML sendiri dengan CSS di Light DOM. Declarative Components memanfaatkan Declarative Shadow DOM untuk isolasi yang lebih kuat namun tetap mendukung SSR. Masing-masing cocok untuk kasus penggunaan berbeda dalam design system skala besar.

Mengapa Elena.js?

Elena.js adalah library berukuran sangat kecil, hanya 2.6 kB setelah minified dan compressed. Berbeda dengan library web components lainnya, Elena.js tidak memaksa JavaScript untuk segala hal. Ia menangani sinkronisasi prop/attribute, event delegation, dan compatibility antar-framework sehingga developer bisa fokus membangun komponen, bukan plumbing infrastruktur.

Library ini juga mendukung SSR secara native. Komponen tanpa metode render() sudah SSR-compatible by default, sementara komponen dengan render() mendapat partial support dan hydration di client side. Elena juga mendukung Declarative Shadow DOM untuk kasus yang memerlukan isolasi style lebih kuat namun tetap ingin merender di server. Semua ini dibangun di atas standar web native tanpa runtime dependencies.

Langkah 1: Instalasi Elena CLI

Langkah pertama adalah menginstal Elena CLI untuk scaffolding komponen. Pastikan Node.js 18 atau lebih baru sudah terpasang di sistem. Elena CLI membantu membuat struktur komponen, konfigurasi bundler, dan boilerplate yang konsisten antar-project.

npm install -g @elenajs/cli
elena --version

Setelah terpasang, verifikasi dengan menjalankan elena --version. Output yang muncul menandakan CLI siap digunakan untuk scaffolding dan bundling library web components.

Langkah 2: Scaffold Komponen Pertama

Buat direktori project baru dan scaffold komponen button sebagai proof of concept. Komponen button dipilih karena representatif: memiliki state interaktif, styling, dan behavior yang umum di design system.

mkdir elena-design-system && cd elena-design-system
elena init
elena generate component elena-button --type=primitive

Perintah di atas akan menghasilkan struktur file: src/elena-button/elena-button.html, elena-button.css, dan elena-button.js. Tipe primitive dipilih karena komponen button bersifat self-contained dan merender HTML-nya sendiri. Jika ingin membuat komponen yang membungkus markup yang sudah ada di halaman, gunakan tipe composite.

Langkah 3: Membangun Base Layer HTML dan CSS

Isi file HTML dengan markup semantik yang bisa merender tanpa JavaScript. Ini adalah inti dari progressive enhancement. Jika JavaScript gagal termuat atau tertunda, pengguna tetap melihat button yang benar dan bisa berinteraksi secara dasar.

<button class="elena-button" type="button" disabled>
  <span class="elena-button__label">Submit</span>
</button>

Kemudian tambahkan CSS di file elena-button.css. Semua style ditempatkan di Light DOM agar tetap searchable oleh browser, tidak menimbulkan barrier accessibility, dan mudah di-override oleh consumer jika diperlukan.

.elena-button {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 1rem;
  background: #2563eb;
  color: #fff;
  border: none;
  border-radius: 0.375rem;
  cursor: pointer;
  font-family: inherit;
  font-size: 1rem;
}

.elena-button[disabled] {
  opacity: 0.6;
  cursor: not-allowed;
}

Dengan base layer ini, browser sudah bisa menampilkan button yang benar meskipun JavaScript belum termuat. Ini menghilangkan masalah flash of unstyled content yang sering terjadi pada web components tradisional.

Langkah 4: Menambahkan Enhancement Layer JavaScript

Buka file elena-button.js dan tambahkan logika interaktif menggunakan Elena core. Perhatikan bahwa komponen tidak menghapus HTML yang sudah ada, melainkan mengehance-nya.

import { define, reactive, html } from '@elenajs/core';

export class ElenaButton extends HTMLElement {
  static observedAttributes = ['variant', 'disabled', 'loading'];

  connectedCallback() {
    this._state = reactive({ pressed: false, counter: 0 });
    this.addEventListener('click', this.handleClick);
    this.addEventListener('keydown', this.handleKeydown);
  }

  handleClick = () => {
    if (this.hasAttribute('disabled')) return;
    this._state.counter++;
    this.setAttribute('aria-pressed', 'true');
    this.render();
  };

  handleKeydown = (e) => {
    if (e.key === 'Enter' || e.key === ' ') {
      e.preventDefault();
      this.handleClick();
    }
  };

  render() {
    const label = this.querySelector('.elena-button__label');
    if (label) label.textContent = `Clicked ${this._state.counter} times`;
  }
}

define('elena-button', ElenaButton);

Pendekatan ini menghindari hydration mismatch dan memastikan progressive enhancement berjalan mulus. Elena core menyediakan reaktivitas berbasis proxy sehingga perubahan state secara otomatis trigger re-render yang efisien dan batched.

Langkah 5: Bundling dan Integrasi Cross-Framework

Setelah komponen selesai, gunakan Elena bundler untuk menghasilkan library yang bisa diimpor di berbagai framework. Bundler Elena dirancang khusus untuk library web components dan menghasilkan output UMD serta ESM.

npm install @elenajs/bundler
npx elena-bundle --entry src/index.js --outDir dist

Output bundler akan menghasilkan file UMD dan ESM yang siap dipakai. Di React, komponen bisa langsung dipakai tanpa wrapper karena Elena menangani prop/attribute sync secara otomatis. Di Vue dan Angular, komponen custom element dikenali secara native oleh compiler template masing-masing.

Untuk integrasi lebih lanjut, kunjungi dokumentasi Framework Integration dan Repository Elena.js di GitHub. Elena juga menyediakan package SSR khusus untuk server-side rendering yang lebih advanced.

Kesimpulan

Progressive web components dengan Elena.js menawarkan pendekatan design system yang solid, lightweight, dan benar-benar cross-framework. Dengan memisahkan base layer HTML/CSS dari enhancement layer JavaScript, kita mendapatkan komponen yang SSR-friendly, accessible, dan bebas layout shift. Design system yang dibangun dengan filosofi ini akan lebih tahan lama dan mudah diadopsi di berbagai codebase tanpa mengkhawatirkan framework lock-in.