Lompat ke konten
dokumentasi.id
Commit 9a47d33
v2
Star3,4 rb

9

Utilitas, Logger, dan Environment

Tiga modul kecil di src/lib menyangga hampir seluruh komponen: cn yang menggabungkan class Tailwind, logger yang mencetak log bergaya INFO, dan env.ts yang memvalidasi variabel environment dengan zod. Rantai sakelar logger tidak berhenti di src/lib, karena nilai showLogger dihitung di src/constant/env.ts (src/constant/env.ts:1-6).

Katalog utilitas

BerkasEksporPeran
src/lib/utils.tscnmenggabungkan clsx dan twMerge menjadi satu className
src/lib/logger.tslogger (default)membungkus console.log dengan gerbang showLogger
src/lib/env.tsefek samping envVariables.parsememvalidasi process.env dengan skema zod
src/constant/env.tsisProd, isLocal, showLoggermenerjemahkan NODE_ENV dan NEXT_PUBLIC_SHOW_LOGGER menjadi boolean
src/lib/helper.tsgetFromLocalStorage, getFromSessionStoragepembacaan storage yang aman saat render server
src/lib/og.tsopenGraphmenyusun URL gambar Open Graph

cn: clsx untuk bentuk, twMerge untuk konflik

cn menerima ...inputs: ClassValue[] dari clsx, memanggil clsx(inputs), lalu menyerahkan hasilnya ke twMerge (src/lib/utils.ts:1-7). Pembagian tugasnya jelas: clsx meratakan string, array, dan objek kondisional menjadi satu string, sedangkan twMerge membuang utilitas Tailwind yang bertabrakan di kelompok yang sama.

graph LR
  A["cn(...inputs: ClassValue[])"]
  A --> B["clsx(inputs)<br/>meratakan string, array, objek"]
  B --> C["twMerge(hasil clsx)<br/>menyelesaikan utility yang bertabrakan"]
  C --> D["satu string className"]
  style A fill:#f59e0b,color:#000
  style B fill:#f59e0b,color:#000
  style C fill:#8b5cf6,color:#fff
  style D fill:#2d7d46,color:#fff
%% fig: Pipeline cn dari masukan sampai className final
%% desc: clsx meratakan bentuk masukan, twMerge membuang konflik utilitas Tailwind, keluarannya satu string className.
Fig. 1: Pipeline cn dari masukan sampai className finalclsx meratakan bentuk masukan, twMerge membuang konflik utilitas Tailwind, keluarannya satu string className.

Urutan argumen menentukan pemenang. Di Button, className diletakkan sebagai argumen terakhir setelah class dasar, array size, dan array variant, sehingga class dari pemanggil menimpa class bawaan (src/components/buttons/Button.tsx:48-99). Pola yang sama dipakai komponen link, NextImage, dan Skeleton; daftar pemakainya ada di Katalog Komponen Pratinjau.

showLogger sebagai gerbang logger

logger diekspor sebagai default dan menerima object: unknown serta comment?: string (src/lib/logger.ts:9). Baris pertama berkas mematikan aturan no-console supaya pemanggilan console.log lolos lint (src/lib/logger.ts:1). Gerbangnya berupa early return: if (!showLogger) return; (src/lib/logger.ts:9-19).

Saat sakelar menyala, console.log mencetak penanda %c ============== INFO LOG dengan warna #22D3EE, window.location.pathname bila kode berjalan di browser, komentar yang dioper, lalu objeknya (src/lib/logger.ts:12-18). Parameternya dirancang untuk snippet lg pada editor.

Nilai showLogger dihitung sekali saat modul dimuat: isLocal (dari NODE_ENV === 'development') membuatnya selalu true, sedangkan di luar development nilainya process.env.NEXT_PUBLIC_SHOW_LOGGER === 'true' (src/constant/env.ts:4-6). Dua konstanta pendampingnya, isProd dan isLocal, hanya membaca process.env.NODE_ENV (src/constant/env.ts:1-2).

⚠️ Di development sakelar ini tidak bisa dimatikan lewat environment, karena isLocal selalu menang. Di production nilainya hanya menyala bila string-nya persis "true".

Pada commit ini belum ada berkas yang memanggil logger; satu-satunya kemunculan logger( di repository adalah definisinya sendiri (src/lib/logger.ts:9).

src/lib/env.ts memvalidasi process.env

Berkas src/lib/env.ts diimpor murni untuk efek sampingnya dari src/app/page.tsx, yang berjalan sebagai client component (src/app/page.tsx:1-4). Begitu modul dievaluasi, envVariables.parse(process.env) langsung dijalankan (src/lib/env.ts:13).

Skemanya hanya punya satu kunci, NEXT_PUBLIC_SHOW_LOGGER: z.enum(['true', 'false']).optional() (src/lib/env.ts:9-11). Karena skema tidak memakai .strict(), variabel lain di process.env diabaikan. Setelah parse berhasil, declare global memperluas NodeJS.ProcessEnv dengan z.infer dari skema itu, sehingga process.env.NEXT_PUBLIC_SHOW_LOGGER bertipe 'true' | 'false' | undefined (src/lib/env.ts:15-19).

Rantai lengkapnya, dari impor sampai pemanggilan logger, tampak pada diagram berikut.

sequenceDiagram
  autonumber
  participant Page as src/app/page.tsx
  participant Env as src/lib/env.ts
  participant Zod as skema zod
  participant Proc as process.env
  participant Const as src/constant/env.ts
  participant Log as src/lib/logger.ts

  Page->>Env: import '@/lib/env'
  Env->>Proc: "envVariables.parse(process.env)"
  Proc-->>Env: NEXT_PUBLIC_SHOW_LOGGER
  Env->>Zod: "z.enum(['true', 'false']).optional()"
  alt nilai tidak cocok skema
    Zod-->>Page: ZodError saat modul dimuat
  else valid atau tidak diset
    Zod-->>Env: lolos validasi
  end
  Const->>Proc: "process.env.NODE_ENV"
  Note over Const: "showLogger = isLocal ? true : NEXT_PUBLIC_SHOW_LOGGER === 'true'"
  Log->>Const: "import { showLogger }"
  Log->>Log: "if (!showLogger) return"
  alt showLogger false
    Note over Log: tidak ada output
  else showLogger true
    Log->>Log: "console.log('%c ============== INFO LOG', ...)"
  end
%% fig: Alur pembacaan environment sampai pemanggilan logger
%% desc: Impor src/lib/env memvalidasi process.env dengan zod, src/constant/env.ts menurunkan showLogger, lalu logger memutuskan berhenti atau mencetak log.
Fig. 2: Alur pembacaan environment sampai pemanggilan loggerImpor src/lib/env memvalidasi process.env dengan zod, src/constant/env.ts menurunkan showLogger, lalu logger memutuskan berhenti atau mencetak log.

Variabel yang benar-benar dibaca kedua modul itu hanya dua.

VariabelSkema zodDibaca olehEfek
NEXT_PUBLIC_SHOW_LOGGERz.enum(['true', 'false']).optional() (src/lib/env.ts:9-11)showLoggermenyalakan log di luar development
NODE_ENVtidak divalidasiisProd, isLocal (src/constant/env.ts:1-2)menentukan apakah showLogger otomatis true

.env.example mendaftarkan satu variabel contoh, NEXT_PUBLIC_SHOW_LOGGER="false", dengan instruksi menduplikasi berkas itu menjadi .env.local dan catatan agar nilainya tidak dipasang di environment deployment produksi (.env.example:1-6). Versi pustaka yang terlibat adalah clsx ^2.0.0, tailwind-merge ^2.6.0, dan zod ^3.24.1 (package.json:20-29).

⚠️ Nilai selain "true" atau "false", misalnya "1", membuat envVariables.parse(process.env) melempar ZodError saat modul dimuat. Karena NEXT_PUBLIC_ di-inline ke bundle klien, nilai yang salah juga merusak halaman, bukan hanya server.

Helper storage dan openGraph

src/lib/helper.ts menyediakan dua pembaca storage. getFromLocalStorage memeriksa typeof window !== 'undefined' lebih dahulu, dan getFromSessionStorage memeriksa typeof sessionStorage !== 'undefined'; keduanya mengembalikan null ketika objek itu tidak tersedia (src/lib/helper.ts:1-13).

openGraph menyusun URL gambar dari siteName, description, logo, dan templateTitle opsional. Setiap bagian di-encodeURIComponent setelah di-trim, dan parameter templateTitle hanya ditempel bila dioper (src/lib/og.ts:10-27). Perilaku ini dikunci oleh test di src/lib/__tests__/og.test.ts:3-19, yang membahas penyertaan parameter tersebut; selengkapnya di Pengujian dengan Jest.

⚠️ Nilai bawaan logo masih placeholder https://og.<your-domain>/images/logo.jpg dan host gambar memakai og.<your-domain>. Komentar di berkas itu meminta domain dan logo diganti sebelum dipakai (src/lib/og.ts:10-27). Pemakaian metadata Open Graph di layout dibahas di SEO, Sitemap, dan Deploy.