Peta di chapter Framework Overview kini harus dijadikan keputusan. Budi menyiapkan situs portofolio, Siti merencanakan dashboard gudang untuk tiga orang, dan perusahaan tempat mereka bekerja menyiapkan etalase daring nasional — tiga proyek, tiga jawaban berbeda, dan ketiganya benar. Kesalahan yang mahal di tahap ini jarang berupa alat yang buruk; kesalahannya adalah alat yang tepat untuk proyek orang lain dipakai tanpa diukur terhadap proyek sendiri.

Chapter penutup section ini menyusun keputusan itu menjadi kerangka: pertanyaan yang harus dijawab sebelum memilih, rekomendasi per profil proyek, pelengkap rangkaian di luar framework, dan sebuah checklist keputusan yang bisa dijalankan ulang setiap kali keadaan berubah.

Empat Pertanyaan Sebelum Memilih #

Setiap pilihan tools yang tahan lama dimulai dari empat pertanyaan yang jawabannya ada pada proyek, bukan pada iklan:

  1. Apa yang dibangun? — situs berisi konten, aplikasi interaktif penuh (SPA), halaman publik yang harus tampil lengkap sejak permintaan pertama (SSR), atau alat baris perintah.
  2. Siapa yang memelihara? — satu orang atau tim; pengalaman yang tersedia; seberapa mudah mencari penulis baru yang mengenal alatnya.
  3. Berapa umur rencana kode? — skrip tiga bulan dan sistem tiga tahun menanggung risiko yang berbeda, seperti yang kita ukur di chapter Kapan Mempertimbangkan TypeScript.
  4. Batasan apa yang menekan? — perangkat pengguna yang terbatas, koneksi yang lambat, atau waktu belajar tim yang pendek.

Ketiga proyek pembuka menjawab berbeda: portofolio Budi adalah konten statis untuk satu penulis; dashboard Siti adalah SPA internal dengan umur panjang; etalase nasional adalah halaman publik yang butuh cepat tampil dan ramah mesin pencari, ditulis delapan orang.

Satu istilah dari pertanyaan pertama layak dijelaskan. Pada SPA, server mengirim kerangka HTML yang kosong dan browser menyusun antarmuka dari JavaScript. Pada SSR (server-side rendering), server yang menyusun HTML pertama sehingga halaman terlihat lengkap sejak respons pertama — inilah alasan etalase daring memilihnya, dan metode ini hanya bisa dikerjakan alat yang menyadari server, bukan sekadar bundler.

Memilih Framework Sesuai Profil #

Empat pertanyaan di atas menghasilkan pemetaan profil ke pilihan. Tabel ini memakai baris “Cocok untuk” dari chapter sebelumnya:

Profil proyekPilihan wajarAlasan singkat
Situs konten, portofolioHTML + JavaScript murni; Svelte atau Vue bila interaksi bertambahkeluaran kecil, pipeline ringan
Dashboard, SPA internalReact atau Vue, dibundel Viteekosistem komponen, perekrutan mudah
Halaman publik dengan SSRNext.js, Nuxt, atau SvelteKitmeta-framework: SSR dan routing siap pakai
Aplikasi korporat, tim besarAngularstruktur seragam, TypeScript bawaan, alat terpadu

Tiga nama di baris ketiga disebut meta-framework: lapisan di atas framework UI yang menambahkan pekerjaan sisi server — SSR, routing, pengambilan data — ke atas komponennya masing-masing. Next.js dibangun di atas React, Nuxt di atas Vue, dan SvelteKit di atas Svelte. Menambahkannya ke tabel memperlihatkan pola umum: framework menyediakan komponen, meta-framework menyediakan aplikasi.

Melengkapi Rangkaian: Build, Uji, Jaga Kualitas #

Framework hanyalah satu keputusan; rangkaian pengembangan memuat tiga lagi, dan semuanya sudah kita kenal bentuk mentahnya:

  • Build — Vite adalah bundler yang paling sering dipasangkan dengan React, Vue, dan Svelte: server pengembangan cepat untuk harian, hasil bundel untuk produksi, dengan esbuild menerjemahkan dan Rollup membundel di dalamnya — dua alat yang dibedah di chapter Bundlers Overview. Angular memakai CLI-nya sendiri dengan peran yang sama.
  • Pengujian — Vitest menuruti API node:test yang dipelajari di section Testing, sehingga pindah dari satu ke yang lain terasa seperti mengganti cara menjalankan, bukan mengganti cara menulis uji. Untuk alur browser penuh — klik, formulir, navigasi — Playwright menguji aplikasi di browser sungguhan.
  • Kualitas kode — ESLint dan Prettier dari section Tooling dan Code Quality tetap berlaku di setiap pilihan di atas. TypeScript melengkapinya dengan tsc --noEmit: pemeriksaan tipe penuh tanpa menulis keluaran, sebagaimana dibedah di chapter Transpilation Overview.

Rangkaian itu juga menjelaskan mengapa baris TypeScript di tabel framework penting: pipeline yang sama dipakai alat yang sama; yang berubah antar pilihan hanyalah komponennya.

Memutuskan dengan Kerangka yang Bisa Dijalankan #

Supaya keputusan ini tidak berhenti sebagai opini, kita susun aturannya menjadi data. Aturannya: setiap profil proyek dipetakan ke paket rekomendasi — pilihan UI, alat build, alat uji, dan catatan adopsi tipe; catatan tipe mengikuti ukuran tim dan umur rencana. Mekanismenya: profil dicocokkan ke katalog lewat Map, catatan diganti bila proyek masih kecil dan muda, dan jenis yang tidak dikenal ditolak di pintu masuk.

Sebelum masuk ke kodenya, satu sentuhan TypeScript menutup lingkaran section ini. Profil keputusan adalah bentuk data — dan bentuk data yang penting layak dideklarasikan:

ts Ilustrasi: profil keputusan sebagai tipe
type ProfilProyek = {
  nama: string;
  jenis: "statis" | "spa" | "ssr" | "korporat";
  tim: number;
  umurBulan: number;
};

function rekomendasikan(profil: ProfilProyek) {
  // isi function — dibahas bersama berkas di bawah
}

Tipe jenis berbentuk union literal: hanya empat kata itu yang sah. Salah tik "spaa" dilaporkan compiler sebelum program berjalan — kesalahan yang pada versi JavaScript baru tertangkap oleh pemeriksaan runtime if (!pilihan). Blok di atas ilustrasi dan tidak dijalankan di chapter ini (TypeScript butuh langkah kompilasi); keduanya hidup berdampingan: tipe menjaga penulis kode di dalam proyek, pemeriksaan runtime menjaga data yang datang dari luar, sesuai pesan di chapter JavaScript vs TypeScript.

Katalog lengkapnya, beserta tiga profil pembuka chapter, kita jalankan sebagai berkas JavaScript biasa:

// panduan-keputusan.js — kerangka memilih tools untuk tiga profil proyek.
// Jalankan di terminal: node panduan-keputusan.js

const KATALOG = new Map([
  [
    "statis",
    {
      ui: "tanpa framework — HTML + JavaScript murni",
      build: "esbuild langsung",
      uji: "node:test",
      catatan: "JSDoc + pemeriksaan tipe opsional sudah cukup",
    },
  ],
  [
    "spa",
    {
      ui: "React atau Vue",
      build: "Vite",
      uji: "Vitest (polanya sama dengan node:test)",
      catatan: "adopsi TypeScript sejak hari pertama",
    },
  ],
  [
    "ssr",
    {
      ui: "Next.js (React) atau Nuxt (Vue)",
      build: "bawaan meta-framework",
      uji: "Vitest + Playwright",
      catatan: "TypeScript wajib; kontrak server-klien jadi dokumen hidup",
    },
  ],
  [
    "korporat",
    {
      ui: "Angular",
      build: "Angular CLI",
      uji: "Vitest + Playwright",
      catatan: "TypeScript bawaan framework, tidak opsional",
    },
  ],
]);

function rekomendasikan(profil) {
  const pilihan = KATALOG.get(profil.jenis);
  if (!pilihan) {
    throw new Error(`Jenis proyek tidak dikenal: ${profil.jenis}`);
  }
  const catatanTipe =
    profil.tim >= 3 || profil.umurBulan >= 12
      ? pilihan.catatan
      : "mulai tanpa framework berat; evaluasi ulang saat tim bertambah";
  return { ...pilihan, catatan: catatanTipe };
}

const profil = [
  { nama: "situs portofolio Budi", jenis: "statis", tim: 1, umurBulan: 6 },
  { nama: "dashboard gudang Siti", jenis: "spa", tim: 3, umurBulan: 24 },
  { nama: "etalase nasional", jenis: "ssr", tim: 8, umurBulan: 36 },
];

for (const p of profil) {
  const r = rekomendasikan(p);
  console.log(`${p.nama} (${p.jenis}, tim ${p.tim}, rencana ${p.umurBulan} bulan)`);
  console.log(`  UI    : ${r.ui}`);
  console.log(`  Build : ${r.build}`);
  console.log(`  Uji   : ${r.uji}`);
  console.log(`  Catatan: ${r.catatan}`);
}

Output yang Dihasilkan:

text
situs portofolio Budi (statis, tim 1, rencana 6 bulan)
  UI    : tanpa framework — HTML + JavaScript murni
  Build : esbuild langsung
  Uji   : node:test
  Catatan: mulai tanpa framework berat; evaluasi ulang saat tim bertambah
dashboard gudang Siti (spa, tim 3, rencana 24 bulan)
  UI    : React atau Vue
  Build : Vite
  Uji   : Vitest (polanya sama dengan node:test)
  Catatan: adopsi TypeScript sejak hari pertama
etalase nasional (ssr, tim 8, rencana 36 bulan)
  UI    : Next.js (React) atau Nuxt (Vue)
  Build : bawaan meta-framework
  Uji   : Vitest + Playwright
  Catatan: TypeScript wajib; kontrak server-klien jadi dokumen hidup

Mari kita telaah bagian-bagian pentingnya:

  1. Baris 4–41 (const KATALOG = new Map([ ... ])): seluruh kebijakan dinyatakan sebagai data, bukan cabang if yang bertaburan. Menambah profil baru berarti menambah entri — struktur yang sama dengan pola peta operasi yang menggantikan rangkaian if di section Security.
  2. Baris 43–47 (function rekomendasikan(profil) { ... } bagian atas): jenis yang tidak ada di katalog ditolak dengan pesan yang menyebut jenisnya — penjagaan pintu masuk yang sama dengan factory di section Architecture: kesalahan tertangkap di tempat pemanggilan, bukan jauh di ujung laporan.
  3. Baris 48–51 (const catatanTipe = ...): catatan adopsi tipe menimbang dua hal dari chapter pertama section ini — ukuran tim dan umur rencana. Proyek kecil dan muda diminta menunda; selebihnya mewarisi catatan katalognya.
  4. Baris 55–59 (const profil = [ ... ]): ketiga proyek pembuka chapter dijadikan data. Keluaran memperlihatkan hasil yang berbeda untuk masing-masing — portofolio Budi diminta menunda adopsi, dashboard Siti memulai dengan TypeScript, etalase nasional mewajibkannya sebagai kontrak server-klien.

Keputusan tools juga bukan pernikahan seumur hidup. Profil berubah: tim bertambah, proyek muda menua, SPA membutuhkan SSR. Kerangka di atas bisa dijalankan ulang kapan pun keadaan berubah, dan saran katalognya mengikuti. Dengan begitu section ini menutup dengan pola yang sama seperti seluruh course: keputusan yang diukur dengan data, bukan dengan mode — bekal yang tepat sebelum kita menyusun proyek nyata di section Proyek.

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

panduan-keputusan.js

Unduh berkas
javascript
// panduan-keputusan.js — kerangka memilih tools untuk tiga profil proyek.
// Jalankan di terminal: node panduan-keputusan.js

const KATALOG = new Map([
  [
    "statis",
    {
      ui: "tanpa framework — HTML + JavaScript murni",
      build: "esbuild langsung",
      uji: "node:test",
      catatan: "JSDoc + pemeriksaan tipe opsional sudah cukup",
    },
  ],
  [
    "spa",
    {
      ui: "React atau Vue",
      build: "Vite",
      uji: "Vitest (polanya sama dengan node:test)",
      catatan: "adopsi TypeScript sejak hari pertama",
    },
  ],
  [
    "ssr",
    {
      ui: "Next.js (React) atau Nuxt (Vue)",
      build: "bawaan meta-framework",
      uji: "Vitest + Playwright",
      catatan: "TypeScript wajib; kontrak server-klien jadi dokumen hidup",
    },
  ],
  [
    "korporat",
    {
      ui: "Angular",
      build: "Angular CLI",
      uji: "Vitest + Playwright",
      catatan: "TypeScript bawaan framework, tidak opsional",
    },
  ],
]);

function rekomendasikan(profil) {
  const pilihan = KATALOG.get(profil.jenis);
  if (!pilihan) {
    throw new Error(`Jenis proyek tidak dikenal: ${profil.jenis}`);
  }
  const catatanTipe =
    profil.tim >= 3 || profil.umurBulan >= 12
      ? pilihan.catatan
      : "mulai tanpa framework berat; evaluasi ulang saat tim bertambah";
  return { ...pilihan, catatan: catatanTipe };
}

const profil = [
  { nama: "situs portofolio Budi", jenis: "statis", tim: 1, umurBulan: 6 },
  { nama: "dashboard gudang Siti", jenis: "spa", tim: 3, umurBulan: 24 },
  { nama: "etalase nasional", jenis: "ssr", tim: 8, umurBulan: 36 },
];

for (const p of profil) {
  const r = rekomendasikan(p);
  console.log(`${p.nama} (${p.jenis}, tim ${p.tim}, rencana ${p.umurBulan} bulan)`);
  console.log(`  UI    : ${r.ui}`);
  console.log(`  Build : ${r.build}`);
  console.log(`  Uji   : ${r.uji}`);
  console.log(`  Catatan: ${r.catatan}`);
}