npm adalah alat manajemen paket yang banyak digunakan oleh pengembang front-end. Dalam proyek ini, package.json digunakan untuk mengelola konfigurasi paket npm yang menjadi sandaran proyek. package.json adalah file json. Selain menjelaskan dependensi paket proyek, ini juga memungkinkan kita menggunakan "aturan pembuatan versi semantik" untuk menunjukkan versi paket dependen proyek Anda, sehingga build Anda dapat dibagikan dengan lebih baik kepada pengembang lain agar lebih mudah. digunakan kembali. Artikel ini terutama dimulai dari praktik terkini, dikombinasikan dengan versi npm dan node terbaru, untuk memperkenalkan beberapa konfigurasi umum di package.json dan cara menulis package.json standar
Dalam proyek nodejs, package.json adalah file konfigurasi yang mengelola dependensinya. Biasanya saat kita menginisialisasi proyek nodejs, kita akan meneruskan:
npm init
dan kemudian 3 akan dihasilkan direktori/file Anda, node_modules, package.json dan package.lock.json. Isi dari package.json adalah:
{ "nama": "Nama proyek Anda", "versi": "1.0.0", "deskripsi": "Deskripsi proyek Anda", "utama": "app.js", "skrip": { "test": "echo "Kesalahan: tidak ada pengujian yang ditentukan" && keluar 1", }, "penulis": "Nama penulis", "lisensi": "ISC", "ketergantungan": { "ketergantungan1": "^1.4.0", "ketergantungan2": "^1.5.2" } }
Seperti yang dapat dilihat di atas, package.json berisi metadata proyek itu sendiri, serta informasi sub-dependensi proyek (seperti dependensi, dll.).
Kami menemukan bahwa selama npm init, tidak hanya file package.json yang dibuat, tetapi file package-lock.json juga dibuat. Jadi mengapa kita masih perlu membuat file package-lock.json saat menghapus package.json? Pada dasarnya, file package-lock.json adalah untuk mengunci versi. Paket sub-npm yang ditentukan dalam package.json adalah seperti: react: "^16.0.0". bereaksi, package.json memenuhi persyaratan. Artinya, menurut file package.json yang sama, versi sub-dependensi yang diinstal dua kali tidak dapat dijamin konsisten.
File kunci paket seperti yang ditunjukkan di bawah ini, dan sub-dependensi dependency1 menentukan versinya secara detail. Memainkan peran versi kunci.
{ "nama": "Nama proyek Anda", "versi": "1.0.0", "lockfileVersion": 1, "membutuhkan": benar, "ketergantungan": { "ketergantungan1": { "versi": "1.4.0", "terselesaikan": "https://registry.npmjs.org/dependency1/-/dependency1-1.4.0.tgz", "integritas": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" }, "ketergantungan2": { "versi": "1.5.2", "terselesaikan": "https://registry.npmjs.org/dependency2/-/dependency2-1.5.2.tgz", "integritas": "sha512-WOn21V8AhyE1QqVfPIVxe3tupJacq1xGkPTB4iagT6o+P2cAgEOOwIxMftr4+ZCTI6d551ij9j61DFr0nsP2uQ==" } } }
Bab ini akan membahas tentang atribut konfigurasi yang umum digunakan di package.json. Atribut seperti nama, versi, dan sebagainya terlalu sederhana dan tidak akan diperkenalkan satu per satu. Bab ini terutama memperkenalkan properti skrip, bin, dan ruang kerja.
menggunakan tag skrip di npm untuk mendefinisikan skrip. Setiap kali npm run ditentukan, skrip shell akan otomatis dibuat. Yang perlu diperhatikan di sini adalah shell baru yang dibuat oleh npm run akan menyimpan node_modules/.bin di direktori lokal. Tambahkan subdirektori ke variabel PATH.
Artinya semua skrip di subdirektori node_modules/.bin dari direktori saat ini dapat dipanggil langsung dengan nama skrip tanpa menambahkan jalur. Misalnya, jika dependensi proyek saat ini menyertakan esbuild, tulis saja esbuild xxx secara langsung.
{ // ... "skrip": { "build": "esbuild index.js", } }
{ // ... "skrip": { "build": "./node_modules/.bin/esbuild index.js" } }
Dua cara penulisan di atas adalah setara.
Atribut bin digunakan untuk memuat file yang dapat dieksekusi ke lingkungan global. Setelah paket npm dengan bidang bin ditentukan, paket tersebut akan dimuat ke lingkungan global dan file dapat dieksekusi melalui alias.
Misalnya, paket npm @bytepack/cli:
"bin": { "bytepack": "./bin/index.js" },
Setelah @bytepack/cli diinstal secara global, Anda dapat langsung menjalankan perintah terkait melalui bytepack, seperti
bytepack -v //Tampilkan 1.11.0.
Jika tidak diinstal secara global, maka secara otomatis akan terhubung ke direktori node_module/.bin proyek. Konsisten dengan apa yang disebutkan pada tag skrip yang diperkenalkan sebelumnya, tag ini dapat digunakan langsung dengan alias.
Ketika proyek terlalu besar, monorepo menjadi semakin populer akhir-akhir ini. Ketika berbicara tentang monorepo, kami tidak melihat ruang kerja. Pada awalnya, kami akan menggunakan ruang kerja benang. Sekarang npm secara resmi mendukung ruang kerja memecahkan masalah bagaimana mengelola beberapa sub-paket di bawah paket root tingkat atas dalam sistem file lokal. Di direktori deklarasi ruang kerja, paket akan ditautkan secara lunak ke node_modules dari paket root tingkat atas.
Mari kita ilustrasikan langsung dengan contoh dari situs resminya:
{ "nama": "proyek saya", "ruang kerja": [ "paket/a" ] }
Dalam paket npm bernama proyek saya, terdapat direktori yang dikonfigurasi oleh ruang kerja.
. +-- paket.json +-- indeks.js `-- paket +-- sebuah |.`-- package.json
dan paket root tingkat atas bernama proyek saya memiliki paket/sub-paket. Saat ini, jika kita menginstal npm, maka paket npm a yang diinstal di node_modules di paket root menunjuk ke paket lokal/a
. +-- node_modules |.`-- paket/a -> ../paket/a +-- paket-lock.json +-- paket.json `-- paket +-- sebuah |. `-- package.json
di atas--
paket/a -> ../packages/a
mengacu pada tautan lunak dari a di node_modules ke paket npm lokal
Lingkungan umum dengan atribut terkait lingkungan package.json, pada dasarnya The di atas dibagi menjadi dua kategori: browser dan lingkungan node. Selanjutnya, mari kita lihat properti konfigurasi yang terkait dengan lingkungan di package.json. Pengertian lingkungan secara sederhana dapat dipahami sebagai berikut:
js mencakup modul commonjs, CMD, UMD, AMD dan ES. Pada awalnya, hanya bidang commonjs yang didukung di node. Namun, mulai dari node13.2.0, node secara resmi mendukung spesifikasi modul ES bidang dapat digunakan di package.json untuk mendeklarasikan spesifikasi modular yang diikuti paket npm.
//paket.json { nama: "beberapa paket", ketik: "modul"||"commonjs" }
Perlu dicatat bahwa
ketika tipe tidak ditentukan, nilai default tipe adalah commonjs. Namun, disarankan agar semua paket npm menentukan tipe.
Ketika bidang tipe menentukan nilai sebagai modul, spesifikasi ESModule
digunakan bidang tipe ditentukan, semua .js dalam direktori akan digunakan. File yang diakhiri dengan akhiran mengikuti spesifikasi modularisasi yang ditentukan berdasarkan jenis.
Selain tipe, yang dapat menentukan spesifikasi modularisasi, spesifikasi modularisasi yang diikuti oleh file ditentukan melalui akhiran file. File yang diakhiri dengan .mjs adalah spesifikasi ESModule yang digunakan. Akhiran .cjs mengikuti spesifikasi commonjs
3.2 main
untuk menentukan file entri paket npm.
kita lihat skenario penggunaan ketiga bidang ini dan prioritasnya ketika ketiga bidang ini ada secara bersamaan. Misalkan ada paket npm bernama demo1,
----- dist |-- indeks.browser.js |-- indeks.browser.mjs |-- indeks.js |--
package.json dari index.mjs menetapkan tiga bidang main, modul dan browser secara bersamaan,
"main": "dist/index.js", // main "modul": "dist/index.mjs", // modul // browser dapat didefinisikan sebagai objek pemetaan yang sesuai dengan bidang utama/modul, atau dapat langsung didefinisikan sebagai string "browser": { "./dist/index.js": "./dist/index.browser.js", // browser+cjs "./dist/index.mjs": "./dist/index.browser.mjs" // browser+mjs }, // "browser": "./dist/index.browser.js" // Browser
dibuat dan digunakan secara default. Misalnya, jika kita mereferensikan paket npm ini dalam proyek:
impor demo dari 'demo'
Setelah membuat yang di atas kode melalui alat build, modul Urutan pemuatannya adalah:
browser
+mjs > module > browser+cjs > main.
Urutan pemuatan ini dapat diubah melalui konfigurasi yang sesuai, namun dalam sebagian besar skenario, kami akan tetap mengikuti urutan pemuatan default.
Jika bidang ekspor ditentukan di package.json, maka konten yang ditentukan dalam bidang ini adalah ekspor paket npm yang nyata dan lengkap, dan prioritasnya akan lebih tinggi daripada bidang utama dan file.
Misalnya:
{ "nama": "pkg", "ekspor": { ".": "./main.mjs", "./foo": "./foo.js" } }
import { sesuatu } dari "pkg"; // dari "pkg/main.mjs"
const { sesuatu } = require("pkg/foo"); // require("pkg/foo.js")
dari contoh di atas Tampaknya ekspor dapat mendefinisikan ekspor dengan jalur yang berbeda-beda. Jika ekspor ada, direktori file yang sebelumnya valid akan menjadi tidak valid di semua tempat, seperti require('pkg/package.json'), karena tidak ditentukan dalam ekspor, dan kesalahan akan dilaporkan.
Fitur ekspor terbesar lainnya adalah referensi bersyarat. Misalnya, kita dapat menentukan paket npm untuk mereferensikan file entri yang berbeda berdasarkan metode referensi atau tipe modular yang berbeda.
// paket.json { "nama":"pkg", "utama": "./main-require.cjs", "ekspor": { "impor": "./main-module.js", "membutuhkan": "./main-require.cjs" }, "tipe": "modul" }
Pada contoh di atas, jika kita
merujuk ke "./main-require.cjs"
melaluiconst p = require('pkg').
Jika Anda meneruskan:
import p from 'pkg',
referensinya adalah "./main-module.js"
. Hal terakhir yang perlu diperhatikan adalah: jika atribut ekspor ada, atribut ekspor tidak hanya memiliki prioritas lebih tinggi daripada main, tetapi juga lebih tinggi dari bidang modul dan browser.
Properti konfigurasi terkait dependensi di package.json mencakup dependensi, devDependencies, peerDependencies, peerDependenciesMeta, dll.
Dependensi adalah ketergantungan proyek, dan devDependencies adalah modul yang diperlukan untuk pengembangan, sehingga kami dapat menginstalnya sesuai kebutuhan selama proses pengembangan untuk meningkatkan efisiensi pengembangan. Yang perlu diperhatikan di sini adalah mencoba menggunakannya sestandar mungkin dalam proyek Anda sendiri. Misalnya, webpack, babel, dll. adalah dependensi pengembangan, bukan dependensi dari proyek itu sendiri.
dependencies Selain dependensi dan devDependencies, artikel ini berfokus pada peerDependencies dan peerDependenciesMeta.
peerDependencies adalah dependensi di package.json, yang dapat memecahkan masalah perpustakaan inti yang diunduh beberapa kali dan menyatukan versi perpustakaan inti.
//paket/pkg -----node_modules |-- npm-a -> Tergantung pada reaksi, reaksi-dom |-- npm-b -> Tergantung pada reaksi, reaksi-dom |-- index.js
Misalnya, pada contoh di atas, jika paket sub-npm a dan b sama-sama berasal dari react dan react-dom, maka jika kita mendeklarasikan PeerDependicies di package.json dari paket sub-npm a dan b, Dependensi yang sesuai tidak akan diinstal ulang.
Ada dua hal yang perlu diperhatikan:
18
"peerDependencies": { "bereaksi": "^16.8.3 || ^17 || ^18" }, "peerDependenciesMeta": { "reaksi-dom": { "opsional": benar }, "reaksi-asli": { "opsional": benar } }
"react-dom" dan "react-native" ditentukan di sini di peerDependenciesMeta dan bersifat opsional, jadi jika "react-dom" dan "react-native" tidak diinstal dalam proyek, tidak ada kesalahan yang akan dilaporkan.
Perlu dicatat bahwa kami memang telah mencabut pembatasan melalui peerDependenciesMeta, namun sering kali ada skenario yang mana batasannya adalah A atau B. Misalnya, pada contoh di atas, yang kami perlukan adalah "react-dom" dan "react-native" dan kita perlu menginstalnya, tetapi Faktanya, kita tidak dapat mencapai prompt ini melalui pernyataan di atas.
Ada juga banyak atribut tiga pihak di package.json, seperti tipe yang digunakan di tsc, sideEffects yang digunakan di alat build, husky yang digunakan di git, dan eslintIgnore yang digunakan di eslint ekstensi ditujukan untuk alat Pengembangan tertentu yang bermakna dan saya tidak akan memberikan contoh di sini.