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

Kamu membaca versi lama. Halaman ini hanya bisa dibaca.

4

Konfigurasi Build dan Alat Pengembangan

Build di repository ini dijalankan sepenuhnya oleh next. Tidak ada bundler atau task runner terpisah, jadi seluruh pipeline ditentukan oleh empat berkas: next.config.js untuk perilaku build, postcss.config.js untuk rantai CSS, tsconfig.json untuk resolver alias, dan package.json untuk urutan perintah. Pemeriksaan kualitas menumpang pada eslint lewat next lint dan pada prettier lewat lint-staged (package.json:5-19).

Urutan build, postbuild, dan pemeriksaan lint

next build menghasilkan direktori .next, lalu hook postbuild menjalankan next-sitemap untuk membuat sitemap dan robots.txt. Jalur lint, typecheck, dan format:check berdiri sendiri dan tidak dipanggil oleh build; CI yang memanggilnya satu per satu (.github/workflows/lint.yml:34-44).

graph TD
  buildScript["pnpm build"] --> nextBuild["next build"]
  nextBuild --> webpackHook["webpack(): aturan svg"]
  nextBuild --> eslintDirs["eslint.dirs: ['src']"]
  nextBuild --> dotNext["output .next"]
  dotNext --> postBuild["postbuild: next-sitemap"]
  postBuild --> assets["sitemap.xml + robots.txt"]
  strictLint["pnpm lint:strict: --max-warnings=0"] -.-> eslintDirs
  typecheckRun["pnpm typecheck: tsc --noEmit"] -.-> tsconfigFile["tsconfig.json"]
  style buildScript fill:#2d7d46,color:#fff
  style nextBuild fill:#2d7d46,color:#fff
  style dotNext fill:#2d7d46,color:#fff
  style webpackHook fill:#f59e0b,color:#000
  style eslintDirs fill:#f59e0b,color:#000
  style strictLint fill:#f59e0b,color:#000
  style typecheckRun fill:#f59e0b,color:#000
  style tsconfigFile fill:#f59e0b,color:#000
  style postBuild fill:#8b5cf6,color:#fff
  style assets fill:#8b5cf6,color:#fff
%% fig: Urutan build, postbuild, dan pemeriksaan lint
%% desc: next build menghasilkan output .next, kemudian hook postbuild menjalankan next-sitemap; lint dan typecheck berjalan di jalur terpisah.
Fig. 1: Urutan build, postbuild, dan pemeriksaan lintnext build menghasilkan output .next, kemudian hook postbuild menjalankan next-sitemap; lint dan typecheck berjalan di jalur terpisah.

Seluruh perintah tinggal di blok scripts package.json (package.json:5-19):

ScriptPerintahFungsi
devnext devserver pengembangan
buildnext buildbuild produksi
startnext startmenjalankan hasil build
lintnext lintESLint lewat Next
lint:fixeslint src --fix && pnpm formatperbaikan otomatis, lalu format
lint:stricteslint --max-warnings=0 srcnol warning
typechecktsc --noEmit --incremental falsecek tipe tanpa menulis berkas
test, test:watchjest, jest --watchlihat Pengujian dengan Jest
format, format:checkprettier -w ., prettier -c .tulis ulang atau periksa format
postbuildnext-sitemap --config next-sitemap.config.jssitemap dan robots.txt
preparehusky installpasang hook git

⚠️ .npmrc hanya berisi satu baris, enable-pre-post-scripts=true (.npmrc:1-1). Tanpa baris itu pnpm tidak menjalankan hook pre/post secara otomatis, sehingga postbuild tidak pernah dieksekusi dan sitemap tidak terbentuk. Konfigurasi sitemap sendiri mematok siteUrl: 'https://tsnext-tw.thcl.dev' dan generateRobotsTxt: true (next-sitemap.config.js:5-13); nilai itu wajib diganti sebelum deploy, seperti dibahas di SEO, Sitemap, dan Deploy.

next.config.js: eslint, reactStrictMode, dan aturan webpack

nextConfig hanya memuat tiga kunci aktif, sisanya blok images yang masih dikomentari sebagai contoh whitelist domain (next.config.js:9-17).

KunciNilaiEfek
eslint.dirs['src']next lint dan pemeriksaan saat next build hanya menyentuh src (next.config.js:3-5)
reactStrictModetruekomponen dirender dua kali di mode pengembangan (next.config.js:7)
webpackfungsimenambal aturan svg sebelum config dikembalikan (next.config.js:19-49)

Fungsi webpack bekerja dalam tiga langkah. Pertama, ia mencari aturan bawaan yang menangani .svg lewat rule.test?.test?.('.svg') (next.config.js:21-23). Kedua, ia mendorong dua aturan baru: salinan aturan lama yang hanya berlaku untuk impor ?url, dan aturan @svgr/webpack untuk semua *.svg lain dengan dimensions: false serta titleProp: true (next.config.js:25-43). Ketiga, aturan lama diberi exclude = /\.svg$/i agar tidak ikut menangani SVG (next.config.js:46).

Hasilnya, import Logo from '~/svg/Logo.svg' menjadi komponen React yang menerima className (src/app/page.tsx:18, src/app/page.tsx:29). titleProp: true berarti prop title diteruskan sebagai elemen <title> di dalam SVG.

postcss.config.js dan Tailwind v4

Rantai CSS hanya berisi dua plugin dengan urutan tetap: @tailwindcss/postcss lebih dulu, lalu autoprefixer (postcss.config.js:1-6). Keduanya terpasang sebagai devDependency bersama postcss dan tailwindcss versi 4 (package.json:53-56).

Tidak ada tailwind.config.js di akar repository. Pada Tailwind v4, token justru dideklarasikan di CSS lewat blok @theme di src/styles/globals.css, setelah @import 'tailwindcss' dan @plugin '@tailwindcss/forms'. Rincian token warna dan animasinya ada di Styling, Token Warna, dan Tema.

tsconfig.json dan alias path

baseUrl diset "." dengan dua alias: @/* ke ./src/* dan ~/* ke ./public/* (tsconfig.json:16-20). strict, noEmit, isolatedModules, dan jsx: "preserve" aktif, dan plugins memuat next agar editor memakai tipe framework (tsconfig.json:2-27). Berkas yang diperiksa adalah next-env.d.ts, seluruh **/*.ts dan **/*.tsx, serta .next/types/**/*.ts yang dibangkitkan Next (tsconfig.json:28).

Satu alias punya tiga konsumen, dan hanya dua di antaranya membaca tsconfig.json secara langsung:

graph LR
  tsPaths["tsconfig.json paths"] --> atAlias["'@/*' ke ./src/*"]
  tsPaths --> tildeAlias["'~/*' ke ./public/*"]
  atAlias --> tscRun["tsc --noEmit"]
  atAlias --> webpackRun["next build, webpack resolver"]
  atAlias --> jestMap["jest moduleNameMapper"]
  tildeAlias --> jestMap
  jestMap --> svgMockFile["src/__mocks__/svg.tsx"]
  style tsPaths fill:#f59e0b,color:#000
  style atAlias fill:#f59e0b,color:#000
  style tildeAlias fill:#f59e0b,color:#000
  style tscRun fill:#2d7d46,color:#fff
  style webpackRun fill:#2d7d46,color:#fff
  style jestMap fill:#8b5cf6,color:#fff
  style svgMockFile fill:#8b5cf6,color:#fff
%% fig: Satu alias, tiga konsumen
%% desc: paths di tsconfig.json dipakai tsc dan webpack Next, sedangkan Jest memerlukan moduleNameMapper yang menyalin alias tersebut.
Fig. 2: Satu alias, tiga konsumenpaths di tsconfig.json dipakai tsc dan webpack Next, sedangkan Jest memerlukan moduleNameMapper yang menyalin alias tersebut.

⚠️ Menambah alias baru berarti menyentuh dua tempat. tsconfig.json saja tidak cukup karena Jest memakai moduleNameMapper sendiri (jest.config.js:22-26); alias yang hanya ada di paths akan gagal di pnpm test dengan Cannot find module.

Satu catatan kecil: moduleResolution sudah bernilai "node" di dalam compilerOptions (tsconfig.json:12), tetapi kunci bernama sama muncul lagi di level akar, di luar compilerOptions (tsconfig.json:30).

ESLint

Konfigurasi memakai .eslintrc.js format lama dengan tiga plugin, @typescript-eslint, simple-import-sort, dan unused-imports, yang dirangkai dari eslint:recommended, next, next/core-web-vitals, plugin:@typescript-eslint/recommended, dan prettier (.eslintrc.js:7-14).

Aturan yang paling terasa saat menulis kode (.eslintrc.js:15-38):

AturanNilaiAkibat
no-consolewarnconsole lolos lint, tetapi gagal lint:strict
unused-imports/no-unused-importswarnimpor tak terpakai wajib dibuang
unused-imports/no-unused-varswarnvariabel berawalan _ dikecualikan
@typescript-eslint/no-unused-varsoffcek impor diserahkan ke unused-imports
react/jsx-curly-brace-presencewarnkurung kurawal berlebih di JSX ditolak

Karena lint:strict memakai --max-warnings=0 (package.json:11) dan no-console hanya warn, satu console.log sudah cukup menggagalkan lint:strict. Urutan impor dipaksa oleh simple-import-sort/imports dengan sepuluh grup: pustaka eksternal, berkas CSS, @/lib dan @/hooks, @/data, @/components dan @/container, @/store, sisa @/, path relatif, @/types, lalu sisanya (.eslintrc.js:41-77). React dan JSX didaftarkan sebagai global agar tidak dilaporkan (.eslintrc.js:80-83).

Prettier

.prettierrc.js hanya menetapkan lima opsi: arrowParens: 'always', singleQuote: true, jsxSingleQuote: true, tabWidth: 2, dan semi: true (.prettierrc.js:1-7). Plugin prettier-plugin-tailwindcss terpasang sehingga kelas Tailwind dirapikan otomatis saat format dijalankan (package.json:55).

.prettierignore mengecualikan hasil build (.next, /out, /build, /coverage) sekaligus dua berkas yang diurus alat lain, yaitu CHANGELOG.md dan pnpm-lock.yaml (.prettierignore:39-41). Pada tahap lint-staged, berkas js/jsx/ts/tsx melewati eslint --max-warnings=0 lalu prettier -w, sedangkan json/css/scss/md/webmanifest cukup prettier -w (package.json:59-67). Rangkaian hook git dan CI yang memanggil ini dibahas di Otomasi Repository: Husky, Commitlint, dan CI.

Jest

jest.config.js tidak menulis konfigurasi dari nol: nextJest({ dir: './' }) membungkus config agar next.config.js dan berkas .env ikut termuat di lingkungan test (jest.config.js:4-7). Opsi kustomnya:

OpsiNilaiFungsi
setupFilesAfterEnv<rootDir>/jest.setup.jsmemuat matcher tambahan
moduleDirectories['node_modules', '<rootDir>/']mendukung baseUrl di akar
testEnvironmentjest-environment-jsdomDOM untuk Testing Library
moduleNameMapper@/, ~/, dan svgmenyalin alias tsconfig.json

Pemetaan ^.+\.(svg)$ mengarah ke src/__mocks__/svg.tsx (jest.config.js:22-26), yaitu komponen tiruan yang meneruskan ref dan props ke <svg> polos (src/mocks/svg.tsx:1-8). Dengan begitu impor SVG hasil @svgr/webpack tidak perlu benar-benar ditransformasi saat test. Sementara jest.setup.js memuat @testing-library/jest-dom/extend-expect dan mengganti next/router dengan next-router-mock (jest.setup.js:1-5). Isi test dan pola penulisannya ada di Pengujian dengan Jest.