Pertanyaan yang Sering Diajukan
Mengapa folder node_modules
saya menggunakan ruang penyimpanan jika paket disimpan di store global?
pnpm membuat hard link (tautan keras) dari store global ke folder node_modules
proyek. Hard link mengarah ke tempat yang sama pada penyimpanan dimana berkas asli berada. Ambil contoh, jika Anda memiliki foo
di proyek Anda sebagai dependensi dan itu menempati ruang 1MB, maka itu akan terlihat seperti menempati 1MB ruang di folder node_modules
proyek dan jumlah ruang yang sama di store global. Namun, 1MB itu adalah ruang yang sama pada penyimpanan yang dialamatkan dari dua lokasi berbeda. Jadi total foo
menempati 1MB, bukan 2MB.
Untuk lebih lanjut tentang hal ini:
- Mengapa hard link tampaknya mengambil ruang yang sama dengan aslinya?
- Sebuah utas dari ruang obrolan pnpm
- Sebuah issue di repositori pnpm
Apakah hard link bekerja pada Windows?
Singkatnya ya. Menggunakan symbolic link (tautan simbolis) pada Windows bisa dikatakan bermasalah, namun pnpm punya solusinya. Untuk Windows, kami menggunakan junction sebagai gantinya.
Tetapi pendekatan node_modules
bersarang tidak kompatibel dengan Windows?
Versi awal npm memiliki masalah karena menyarangkan semua node_modules
(lihat issue ini). Namun, pnpm tidak membuat folder yang dalam, ia menyimpan semua paket secara datar dan menggunakan symbolic link untuk membuat struktur pohon dependensi.
Bagaimana dengan symlink melingkar?
Meskipun pnpm menggunakan penautan untuk meletakkan dependensi ke dalam folder node_modules
, symlink melingkar dihindari karena paket induk ditempatkan ke folder node_modules
yang sama di mana dependensinya berada. Jadi, dependensi milik foo
tidak akan ada di foo/node_modules
, tetapi dependensi-dependensi itu berada di node_modules
bersamaa dengan foo
itu sendiri.
Kenapa lebih banyak menggunakan hard link? Kenapa tidak menggunakan symlink langsung ke store global?
Satu paket bisa saja memiliki seperangkat dependensi yang berbeda pada satu mesin.
Dalam proyek A foo@1.0.0
dapat memiliki dependensi yang diselesaikan menjadi bar@1.0.0
, tetapi dalam proyek B dependensi yang sama dari foo
mungkin diselesaikan menjadi bar@1.1.0
; jadi, pnpm menggunakan hard link untuk foo@1.0.0
ke setiap proyek di mana ia digunakan, untuk membuat seperangkat dependensi yang berbeda.
Melakukan symlink langsung ke store global akan bekerja dengan tanda Node --preserve-symlinks
. Namun, pendekatan itu datang dengan sejumlah masalah besar. Jadi kami memutuskan untuk tetap menggunakan hard link. Untuk detail lebih lanjut tentang mengapa keputusan ini dibuat, lihat issue ini.
Apakah pnpm berfungsi di banyak drive atau di banyak filesystem?
Store paket harus berada di drive dan filesystem yang sama dengan instalasi. Jika tidak, paket akan disalin, tidak ditautkan. Hal ini karena keterbatasan dalam cara kerja hard link, di mana berkas pada satu filesystem tidak dapat dialamatkan di lokasi lain di filesystem yang berbeda. Lihat issue #712 untuk lebih jelasnya.
pnpm berfungsi secara berbeda dalam 2 kasus di bawah ini:
Jalur store ditentukan
Jika jalur store ditentukan melalui konfigurasi store, maka penyalinan akan dilakukan antara store dan proyek apa pun yang berada di disk yang berbeda.
Jika Anda menjalankan pnpm install
pada disk A
, maka store pnpm harus pada disk A
. Jika pnpm store terletak di disk B
, maka semua paket yang diperlukan akan disalin langsung ke lokasi proyek alih-alih ditautkan. Ini sangat menghambat manfaat penyimpanan dan kinerja dari pnpm.
Jalur store TIDAK ditentukan
Jika jalur store tidak diatur, maka beberapa store akan dibuat (satu per drive atau filesystem).
Jika instalasi dijalankan pada disk A
, penyimpanan akan dibuat pada .pnpm-store
di bawah akar filesystem disk A
. Jika nantinya instalasi dijalankan pada disk B
, toko independen akan dibuat pada B
di .pnpm-store
. Proyek masih akan mempertahankan manfaat pnpm, tetapi setiap drive mungkin memiliki paket yang berlebihan.
Apa kepanjangan dari pnpm
?
pnpm
adalah singkatan untuk performant npm
(npm yang berperforma). @rstacruz yang memberi nama itu.
pnpm
tidak bekerja dengan <PROYEK-ANDA-DISINI>?
Dalam kebanyakan kasus, hal ini berarti salah satu dependensi memerlukan paket yang tidak dideklarasikan dalam package.json
. Ini adalah kesalahan umum yang disebabkan oleh struktur node_modules
yang datar. Jika ini terjadi, ini adalah kesalahan dalam dependensi, dan dependensi tersebut harus diperbaiki. Mungkin membutuhkan waktu untuk memperbaikinya, jadi pnpm mendukung solusi untuk membuat paket buggy tersebut tetap berfungsi.
Solusi 1
Jika ada masalah, Anda dapat menggunakan pengaturan node-linker=hoisted
. Membuat struktur node_modules
datar, mirip dengan npm
.
Solusi 2
Dalam contoh berikut, sebuah dependensi tidak memiliki modul iterall
dalam daftar dependensinya sendiri.
The easiest solution to resolve missing dependencies of the buggy packages is to add iterall
as a dependency to our project's package.json
.
You can do so, by installing it via pnpm add iterall
, and will be automatically added to your project's package.json
.
"dependencies": {
...
"iterall": "^1.2.2",
...
}
Solusi 3
One of the solutions is to use hooks for adding the missing dependencies to the package's package.json
.
An example was Webpack Dashboard which wasn't working with pnpm
. It has since been resolved such that it works with pnpm
now.
It used to throw an error:
Error: Cannot find module 'babel-traverse'
at /node_modules/inspectpack@2.2.3/node_modules/inspectpack/lib/actions/parse
The problem was that babel-traverse
was used in inspectpack
which was used by webpack-dashboard
, but babel-traverse
wasn't specified in inspectpack
's package.json
. It still worked with npm
and yarn
because they create flat node_modules
.
The solution was to create a .pnpmfile.cjs
with the following contents:
module.exports = {
hooks: {
readPackage: (pkg) => {
if (pkg.name === "inspectpack") {
pkg.dependencies['babel-traverse'] = '^6.26.0';
}
return pkg;
}
}
};
After creating a .pnpmfile.cjs
, delete pnpm-lock.yaml
only - there is no need to delete node_modules
, as pnpm hooks only affect module resolution. Then, rebuild the dependencies & it should be working.