File manifest untuk proyek Node
Setiap proyek Node.js punya package.json di root-nya. File JSON biasa ini menjelaskan proyekmu, yaitu nama, versi, apa saja yang dibutuhkan, dan perintah apa yang disediakan, dan inilah yang dibaca npm setiap kali ia melakukan sesuatu. Hapus file ini, maka npm tidak tahu apa-apa tentang proyekmu.
Cara tercepat untuk membuatnya adalah npm init:
npm init -y
Flag -y melewati semua pertanyaan dan menerima default. Hasilnya kira-kira seperti ini:
{
"name": "my-app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
Itulah kerangka dasarnya. Sebagian besar field itu tidak banyak berguna kalau berdiri sendiri; mereka baru bermanfaat saat kamu menambahkan dependency dan script.
Dependencies vs devDependencies
Dua field mengerjakan hampir semua pekerjaan berat: dependencies dan devDependencies. Keduanya berupa pemetaan nama package ke rentang versi.
Pemisahan ini penting karena satu alasan: dependencies adalah package yang dibutuhkan kodemu untuk berjalan. devDependencies adalah package yang hanya kamu butuhkan selama pengembangan: test runner, linter, alat build, type checker. Saat seseorang meng-install package-mu sebagai dependency proyek mereka, npm mengunduh dependencies milikmu dan melewati devDependencies milikmu.
npm memperbarui field ini secara otomatis. npm install express menambahkan satu baris ke dependencies. npm install --save-dev vitest menambahkan satu baris ke devDependencies. Kamu jarang mengeditnya sendiri.
Rentang versi: ^, ~, dan versi persis
String versi seperti ^4.19.0 bukan versi persis, melainkan rentang. npm mengikuti semver, yang membagi versi menjadi MAJOR.MINOR.PATCH:
- Kenaikan MAJOR merusak kompatibilitas dengan versi lama.
- Kenaikan MINOR menambah fitur tanpa merusak apa pun.
- Kenaikan PATCH memperbaiki bug.
Dua operator yang akan kamu lihat di mana-mana:
"express": "^4.19.0" // >= 4.19.0 and < 5.0.0 (any 4.x.x at or above 4.19.0)
"express": "~4.19.0" // >= 4.19.0 and < 4.20.0 (any 4.19.x at or above 4.19.0)
"express": "4.19.0" // exactly 4.19.0
^ adalah default yang dipakai npm saat kamu meng-install package. Ia percaya bahwa kenaikan minor dan patch tetap kompatibel. ~ lebih hati-hati: hanya update patch. Versi polos menguncinya secara persis.
Masalahnya: "yang baru saja aku install" dan "yang diizinkan rentangnya" bukan hal yang sama. Kalau kamu meng-install express@4.19.0 hari ini dan rekan timmu meng-install proyekmu sebulan lagi, ^4.19.0 bisa saja menjadi 4.19.5. Di sinilah package-lock.json berperan: ia mencatat versi persis yang dipakai, sehingga semua orang mendapat pohon dependency yang sama. Commit file itu.
Scripts: kumpulan perintah proyekmu
Field scripts adalah tempat kamu mendefinisikan pintasan untuk perintah yang sering dipakai. Apa pun yang kamu taruh di sana bisa dijalankan dengan npm run <name>:
Beberapa hal yang perlu kamu tahu tentang scripts:
npm start,npm test, dan segelintir nama lain bisa dijalankan tanpa katarun. Selain itu, semuanya butuhnpm run <name>.- Script dijalankan di shell dengan
node_modules/.binada diPATH, jadi kamu bisa memanggil binary dari package yang ter-install secara langsung."test": "vitest"tetap berjalan walaupunvitesttidak ter-install secara global. - Kamu bisa merangkai script:
"build": "npm run lint && npm run compile". Pakai&&untuk "jalankan berurutan, berhenti kalau gagal." - Script
pre<name>danpost<name>berjalan otomatis. Kalau kamu punyaprebuild, ia berjalan sebelumbuildtanpa pengaturan tambahan.
Scripts adalah kumpulan perintah proyekmu. package.json yang baik berarti kontributor baru bisa clone, menjalankan npm install, lalu npm run dev / npm test tanpa harus membaca wiki.
Entry point: main, exports, type
Field-field ini memberi tahu Node (dan bundler) cara memuat package-mu.
typemenentukan cara file.jsdi-parse."module"berarti ESM (import/export). Hapus field ini atau isi"commonjs"untuk CommonJS (require). Lihat dokumen CommonJS vs ESM untuk penjelasan lengkapnya.mainadalah entry point versi lama, yaitu hasil resolusirequire("my-lib"). Masih dihormati oleh alat-alat lama.exportsadalah penggantinya yang modern dan lebih ketat. Ia menentukan persis file mana yang bisa di-import oleh pemakai dan lewat subpath apa. Kalau sebuah file tidak tercantum di sini, meng-import-nya akan gagal, dan itu fitur, bukan bug. Kamu yang mengendalikan API publiknya.
Kalau kamu hanya membuat aplikasi (bukan menerbitkan package), type kemungkinan satu-satunya field di sini yang perlu kamu pedulikan.
package.json yang realistis
Kalau digabungkan, beginilah kira-kira package.json sebuah aplikasi Node kecil dalam praktiknya:
Perhatikan engines.node. Sifatnya hanya anjuran: npm memberi peringatan (atau error dengan engine-strict) kalau versi Node milik pengguna tidak cocok. Kebiasaan yang baik untuk apa pun yang kamu terbitkan.
Field yang perlu kamu kenal
Beberapa field lain yang akan kamu temui:
private: true: mencegahmu menerbitkan package ke npm secara tidak sengaja. Pasang di setiap proyek yang memang tidak untuk diterbitkan.license: identifier SPDX seperti"MIT"atau"ISC". Penting untuk apa pun yang publik.repository,bugs,homepage: ditampilkan di halaman registry npm.bin: kalau package-mu menyertakan CLI, petakan nama perintah ke file script di sini. Setelah install, perintah itu bisa dijalankan.workspaces: untuk monorepo; memberi tahu npm agar memperlakukan subfolder sebagai package yang saling terhubung.
Kamu tidak butuh semuanya. Kamu butuh yang tepat untuk apa yang sedang kamu kerjakan.
Kesalahan umum
Beberapa hal yang sering menjebak orang:
- Commit
node_modules. Jangan. Tambahkan ke.gitignore.package.jsonditambahpackage-lock.jsonsudah cukup bagi siapa pun untuk membangunnya ulang dengannpm install. - Tidak commit
package-lock.json. Commit file itu. Tanpa lockfile, "jalan di komputerku" jadi kemungkinan nyata karena rentang semver bisa menghasilkan versi yang berbeda seiring waktu. - Menaruh dependency runtime di
devDependencies. Aplikasimu mungkin jalan di lokal karena dev dependency ter-install, lalu rusak di production yang melewatinya. Kalau kode yang kamu kirim memakainya, tempatnya didependencies. - Mengedit versi secara manual tanpa install ulang. Ubah versi di
package.jsonlalu jalankannpm install; kalau tidak,node_modulesdan lockfile jadi tidak sinkron.
Berikutnya: runtime Node
package.json memberi tahu Node apa proyekmu. Runtime Node menentukan bagaimana proyek itu berjalan: resolusi module, module bawaan, global, dan event loop di balik layar. Itulah halaman berikutnya.
Pertanyaan yang sering diajukan
Untuk apa package.json dipakai?
package.json adalah file manifest untuk proyek Node.js. Isinya mencatat nama dan versi proyek, package apa saja yang dibutuhkan, script yang bisa kamu jalankan dengan npm run, dan metadata seperti entry point dan tipe module. npm install membacanya untuk menentukan apa yang perlu diunduh.
Apa bedanya dependencies dan devDependencies?
dependencies adalah package yang dibutuhkan kodemu saat runtime, misalnya express atau react. devDependencies hanya dibutuhkan selama pengembangan atau build: test runner, bundler, linter. Saat seseorang meng-install package-mu sebagai dependency proyek mereka, npm melewati devDependencies milikmu.
Apa arti ^ dan ~ pada versi di package.json?
Keduanya adalah operator rentang semver. ^1.2.3 mengizinkan versi 1.x.x apa pun yang sama dengan atau di atas 1.2.3 (major yang sama). ~1.2.3 lebih ketat: ia mengizinkan 1.2.x yang sama dengan atau di atas 1.2.3 (minor yang sama). Versi polos 1.2.3 mengunci versi persisnya. package-lock.json mencatat versi persis yang dipakai supaya hasil install selalu bisa diulang.
Bagaimana cara membuat file package.json?
Jalankan npm init di folder kosong lalu jawab pertanyaannya, atau jalankan npm init -y untuk menerima semua default dan langsung mendapat file-nya. Kamu juga bisa menulisnya sendiri, karena isinya hanya JSON. Field yang benar-benar wajib hanyalah name dan version.