Di Chapter sebelumnya, berkas package.json telah dua kali muncul tanpa dibedah: sebagai penentu format berkas .js lewat field type, dan sebagai penentu pintu masuk package lewat field main. Saatnya memberi perhatian penuh pada berkas yang menjadi pusat setiap proyek Node.js ini. package.json adalah kartu identitas sekaligus kontrak: npm membacanya untuk mengetahui nama dan versi proyek, Node.js membacanya untuk aturan module, dan sesama anggota tim membacanya untuk mengetahui perintah apa saja yang tersedia. Chapter ini membahas cara membuatnya dengan npm init lalu membedah field-field utamanya satu per satu.

Kartu Identitas di Akar Proyek #

Satu folder yang memuat package.json otomatis menjadi akar proyek — titik acuan bagi seluruh alat yang bekerja di ekosistem Node.js. Kita sudah melihat dua perilaku yang mengalir dari posisi berkas ini: resolusi type berlaku untuk berkas .js di folder itu dan seluruh subfoldernya, dan pencarian package berjenjang berhenti begitu node_modules milik akar proyek ditemukan. Karena perannya yang sentral, hampir semua perintah npm — install, run, test — wajib dijalankan dari akar proyek atau folder di bawahnya.

Berkas ini tetap berupa JSON biasa yang dapat kita sunting dengan editor mana pun. Menulis ulang satu nilai versi atau menambah satu baris script lewat tangan adalah hal yang wajar dilakukan; npm sendiri menyediakan perintah npm pkg untuk membaca dan mengubah field tertentu tanpa membuka editor.

Membuat package.json dengan npm init #

Perintah npm init menanyakan beberapa hal lalu menuliskan package.json untuk kita:

bash
npm init

npm akan menanyakan nama proyek, versi, deskripsi, titik masuk, dan beberapa field lain — setiap pertanyaan menyediakan nilai bawaan dalam kurung yang bisa kita terima dengan menekan Enter. Untuk proyek latihan yang ingin dibuat cepat, flag -y menerima seluruh nilai bawaan tanpa satu pun pertanyaan:

bash
npm init -y

Kedua perintah di atas tidak dijalankan pada chapter ini karena bundle chapter sudah berisi satu package.json yang akan kita bedah langsung. Setelah berkas tercipta, langkah berikutnya biasanya adalah melengkapi field-field yang nilainya belum dikenali npm init.

Field-field Utama #

Inilah berkas yang menjadi contoh utama Chapter ini, tersimpan di bundle chapter dan dapat diunduh utuh:

json
{
  "name": "aplikasi-catatan",
  "version": "0.1.0",
  "description": "Aplikasi pencatat kegiatan harian",
  "type": "module",
  "main": "src/utama.mjs",
  "scripts": {
    "start": "node src/utama.mjs",
    "uji": "node --test"
  },
  "dependencies": {
    "express": "^5.1.0"
  },
  "devDependencies": {
    "prettier": "^3.6.2"
  },
  "license": "MIT"
}

Tabel berikut merangkum peran setiap field:

FieldPeran
nameNama proyek; huruf kecil tanpa spasi, boleh memakai tanda hubung
versionVersi proyek mengikuti format semantic versioning
descriptionRingkasan satu kalimat untuk manusia dan pencarian npm
typeFormat module untuk berkas .js: "module" atau "commonjs"
mainPintu masuk saat proyek dipakai sebagai package oleh proyek lain
scriptsDaftar perintah pintasan yang dijalankan lewat npm run
dependenciesPackage yang dibutuhkan aplikasi saat berjalan di produksi
devDependenciesPackage yang hanya dibutuhkan saat pengembangan
licenseJenis lisensi kode; "MIT" adalah pilihan longgar yang umum

Field name dan version membentuk identitas unik — pada registry npm, tidak boleh ada dua package dengan kombinasi keduanya yang sama. Nama boleh diberi awalan scope seperti @organisasi/nama-paket untuk mengelompokkan package milik satu tim atau satu akun. Field main dan type baru terasa manfaatnya ketika proyek dikonsumsi proyek lain; aplikasi yang dijalankan langsung lewat node src/utama.mjs tidak memerlukan keduanya, tetapi mengisinya tetap kebiasaan yang baik.

Field type dan Ekstensi .js #

Field type mengatur bagaimana Node.js menafsirkan berkas .js di dalam proyek:

KondisiBerkas .js diperlakukan sebagai
"type": "module"ES Modules — import dan export aktif
"type": "commonjs"CommonJS — require dan module.exports aktif
Field type tidak adaCommonJS — nilai bawaan sejak 2009

Ekstensi eksplisit selalu menang atas field ini: .mjs tetap ESM dan .cjs tetap CommonJS di proyek mana pun. Karena itu proyek "type": "module" yang masih memuat satu berkas warisan CommonJS tidak perlu menulis ulang berkas tersebut — cukup ganti ekstensinya menjadi .cjs. Perlu diingat bahwa field type berlaku per proyek: dua proyek bersebelahan boleh memilih format yang berbeda tanpa saling ganggu, karena pencarian package.json terdekat berhenti pada akar masing-masing.

Membaca package.json dari Kode #

package.json adalah JSON biasa, sehingga bisa dimuat langsung dari kode dengan teknik impor JSON pada Chapter ES Modules:

js
import paket from "./package.json" with { type: "json" };

const baris = [
  ["name", paket.name],
  ["version", paket.version],
  ["type", paket.type],
  ["main", paket.main],
  ["scripts", Object.keys(paket.scripts).join(", ")],
  ["dependencies", Object.keys(paket.dependencies).join(", ")],
  ["devDependencies", Object.keys(paket.devDependencies).join(", ")],
];

for (const [nama, nilai] of baris) {
  console.log(`${nama.padEnd(16)}: ${nilai}`);
}

Output yang Dihasilkan:

text
name            : aplikasi-catatan
version         : 0.1.0
type            : module
main            : src/utama.mjs
scripts         : start, uji
dependencies    : express
devDependencies : prettier

Impor default menghasilkan object JavaScript utuh, dan Object.keys() dipakai untuk merangkum isi object bersarang scripts dan dependencies menjadi satu baris. Pola seperti ini lazim pada tooling — menampilkan versi aplikasi saat dijalankan dengan flag --versi, atau membaca konfigurasi khusus yang kebetulan tersimpan di package.json. npm sendiri menyediakan jalur resmi untuk hal yang sama:

bash
npm pkg get name version

Output yang Dihasilkan:

text
{
  "name": "aplikasi-catatan",
  "version": "0.1.0"
}

Perintah npm pkg get membaca field apa pun dari package.json tanpa memuat Node.js secara manual — cukup sebutkan nama field, boleh lebih dari satu, dan hasilnya dicetak sebagai JSON. Dua field yang paling sering menjadi sorotan setelah ini adalah dependencies dengan tanda sirkonfleks ^ di depan angka versinya, serta scripts dengan daftar perintahnya. Keduanya masing-masing mendapat chapter sendiri — dimulai dari cara npm memasang dan mencatat dependencies.