Node.js memproyeksikan lebih baik tidak menggunakan file kunci

Penulis materi, terjemahan yang kami terbitkan hari ini, mengatakan bahwa salah satu masalah yang harus dihadapi oleh programmer adalah bahwa kode mereka berfungsi untuk mereka, dan itu memberikan kesalahan kepada orang lain. Masalah ini, mungkin salah satu yang paling umum, muncul karena fakta bahwa dependensi yang berbeda yang digunakan program diinstal dalam sistem pembuat dan pengguna program. Untuk mengatasi fenomena ini, file kunci yang disebut ada di manajer paket benang dan npm . Mereka berisi informasi tentang versi dependensi yang tepat. Mekanisme ini bermanfaat, tetapi jika seseorang mengembangkan paket yang direncanakan akan diterbitkan dalam npm, ia lebih baik tidak menggunakan file kunci. Materi ini didedikasikan untuk kisah mengapa demikian.



Singkatnya, hal terpenting


File kunci sangat berguna ketika mengembangkan aplikasi Node.js seperti server web. Namun, jika Anda berbicara tentang membuat perpustakaan atau alat baris perintah dengan tujuan penerbitan di npm, Anda perlu tahu bahwa file kunci di npm tidak dipublikasikan. Ini berarti bahwa jika file-file ini digunakan selama pengembangan, maka pembuat paket npm, dan mereka yang menggunakan paket ini, akan menggunakan versi dependensi yang berbeda.

Apa itu file kunci?


File kunci menjelaskan pohon ketergantungan lengkap dalam bentuk yang diperolehnya selama pekerjaan pada proyek. Deskripsi ini juga termasuk dependensi bersarang. File tersebut berisi informasi tentang versi spesifik dari paket yang digunakan. Dalam manajer paket npm, file seperti itu disebut package-lock.json , di thread - yarn.lock . Di kedua manajer, file-file ini terletak di folder yang sama dengan package.json .

Inilah yang terlihat seperti package-lock.json .

 { "name": "lockfile-demo", "version": "1.0.0", "lockfileVersion": 1, "requires": true, "dependencies": {  "ansi-styles": {    "version": "3.2.1",    "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",    "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",    "requires": {      "color-convert": "^1.9.0"    }  },  "chalk": {    "version": "2.4.2",    "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",    "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",    "requires": {      "ansi-styles": "^3.2.1",      "escape-string-regexp": "^1.0.5",      "supports-color": "^5.3.0"    }  } } } 

Berikut ini contoh file yarn.lock . Itu tidak dirancang seperti package-lock.json , tetapi itu berisi data serupa.

 # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. # yarn lockfile v1 ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies:       color-convert "^1.9.0" chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== dependencies:       ansi-styles "^3.2.1"       escape-string-regexp "^1.0.5"       supports-color "^5.3.0" 

Kedua file ini mengandung beberapa informasi ketergantungan kritis:

  • Versi persis dari setiap ketergantungan yang diinstal.
  • Ketergantungan informasi untuk setiap ketergantungan.
  • Informasi tentang paket yang diunduh, termasuk checksum yang digunakan untuk memverifikasi integritas paket.

Jika semua dependensi terdaftar di file kunci, mengapa mereka menambahkan informasi tentang itu ke package.json ? Mengapa dua file dibutuhkan?

Perbandingan package.json dan file kunci


Tujuan dari bidang dependencies dari file package.json adalah untuk menunjukkan dependensi proyek yang harus diinstal agar dapat berfungsi dengan baik. Tetapi ini tidak termasuk informasi tentang dependensi dari dependensi ini. Informasi ketergantungan dapat mencakup versi paket yang tepat atau rentang versi tertentu yang ditentukan sesuai dengan aturan versi semantik . Saat menggunakan npm atau rentang benang, versi paket yang paling cocok dipilih.

Misalkan perintah npm install dijalankan untuk menginstal dependensi dari proyek tertentu. Selama proses instalasi, npm mengambil paket yang sesuai. Jika Anda menjalankan perintah ini lagi, setelah beberapa saat, dan jika versi baru dependensi dirilis selama waktu ini, mungkin saja kedua kalinya versi lain dari paket yang digunakan dalam proyek dimuat. Misalnya, jika Anda menginstal dependensi, seperti twilio , menggunakan npm install twilio , entri berikut ini mungkin muncul di bagian dependencies file package.json :

 { "dependencies": {    "twilio": "^3.30.3" } } 

Jika Anda melihat dokumentasi versi semantik npm, Anda dapat melihat bahwa tanda ^ menunjukkan bahwa versi paket mana pun yang cocok, jumlah yang lebih besar dari atau sama dengan 3.30.3 dan kurang dari 4.0.0. Akibatnya, jika tidak ada file kunci dalam proyek dan versi baru dari paket dilepaskan, perintah npm install atau yarn install akan secara otomatis menginstal versi baru paket ini. Informasi dalam package.json tidak akan diperbarui. Saat menggunakan file kunci, semuanya terlihat berbeda.

Jika npm atau benang menemukan file kunci yang sesuai, mereka akan menginstal paket berdasarkan file ini, dan bukan pada package.json . Ini sangat berguna, misalnya, ketika menggunakan sistem Continuous Integration (CI) pada platform di mana Anda perlu memastikan pengoperasian kode dan pengujian yang seragam di lingkungan yang karakteristiknya diketahui sebelumnya. Dalam kasus seperti itu, Anda dapat menggunakan perintah atau bendera khusus ketika memanggil manajer paket yang sesuai:

 npm ci #   ,    package-lock.json yarn install --frozen-lock-file #  ,    yarn.lock,     

Ini sangat berguna jika Anda mengembangkan proyek seperti aplikasi web atau server, karena di lingkungan CI Anda perlu mensimulasikan perilaku pengguna. Akibatnya, jika kami menyertakan file kunci dalam repositori proyek (misalnya, dibuat menggunakan alat git), kami dapat memastikan bahwa setiap pengembang, setiap server, setiap sistem pembangunan kode dan setiap lingkungan CI menggunakan versi yang sama ketergantungan.

Mengapa tidak melakukan hal yang sama ketika menerbitkan perpustakaan atau alat perangkat lunak lain di registri npm? Sebelum menjawab pertanyaan ini, kita perlu berbicara tentang bagaimana proses penerbitan paket bekerja.

Proses Penerbitan Paket


Beberapa pengembang percaya bahwa apa yang diterbitkan dalam npm adalah persis apa yang disimpan dalam repositori git, atau apa yang diubah proyek setelah penyelesaian pekerjaan di dalamnya. Ini sebenarnya tidak demikian. Saat menerbitkan paket, npm mengetahui file mana yang akan diterbitkan dengan mengakses kunci files di file package.json dan file .npmignore . Jika tidak ada yang dapat dideteksi, file .gitignore digunakan. Selain itu, beberapa file selalu dipublikasikan, dan beberapa tidak pernah dipublikasikan. Anda dapat mengetahui apa file-file ini di sini . Sebagai contoh, npm selalu mengabaikan folder .git .

Setelah itu, npm mengambil semua file yang sesuai dan mengemasnya menjadi file tarball menggunakan perintah npm pack . Jika Anda ingin melihat apa sebenarnya yang dimasukkan ke dalam file seperti itu, Anda dapat menjalankan npm pack --dry-run perintah di folder proyek dan melihat daftar bahan di konsol.


Npm pak --dry-run perintah output

File tarball dihasilkan kemudian diunggah ke registri npm. Ketika Anda menjalankan npm pack --dry-run Anda dapat memperhatikan fakta bahwa jika ada file package-lock.json dalam proyek, itu tidak termasuk dalam file tarball. Ini disebabkan oleh fakta bahwa file ini, sesuai dengan aturan npm, selalu diabaikan.

Hasilnya adalah jika seseorang menginstal paket orang lain, file package-lock.json tidak akan terlibat. Apa yang ada di file ini yang dimiliki oleh pengembang paket tidak akan diperhitungkan saat menginstal paket oleh orang lain.

Ini bisa, kebetulan kebetulan, mengarah ke masalah yang kita bicarakan di awal. Dalam sistem pengembang, kodenya berfungsi dengan baik, dan di sistem lain ia menghasilkan kesalahan. Tetapi kenyataannya adalah bahwa pengembang proyek dan mereka yang menggunakan proyek menggunakan versi paket yang berbeda. Bagaimana cara memperbaikinya?

Penolakan file kunci dan penggunaan teknologi shrinkwrap


Pertama, Anda perlu mencegah dimasukkannya file kunci dalam repositori proyek. Saat menggunakan git, Anda harus memasukkan yang berikut ini dalam file .gitignore proyek Anda:

 yarn.lock package-lock.json 

Dokumentasi benang mengatakan bahwa yarn.lock perlu ditambahkan ke repositori bahkan jika itu menyangkut pengembangan perpustakaan yang Anda rencanakan untuk diterbitkan. Tetapi jika Anda ingin Anda dan pengguna perpustakaan Anda bekerja dengan kode yang sama, saya akan merekomendasikan memasukkan yarn.lock dalam file .gitignore .

Anda dapat menonaktifkan pembuatan otomatis file package-lock.json dengan .npmrc file .npmrc dengan konten berikut ke folder proyek:

 package-lock=false 

Saat bekerja dengan benang, Anda dapat menggunakan perintah yarn install --no-lockfile , yang memungkinkan Anda untuk menonaktifkan pembacaan file yarn.lock .

Namun, fakta bahwa kami menyingkirkan file package-lock.json tidak berarti bahwa kami tidak dapat menangkap informasi tentang dependensi dan dependensi bersarang. Ada file lain yang disebut npm-shrinkwrap.json .

Secara umum, ini adalah file yang sama dengan package-lock.json , ini dibuat oleh perintah npm shrinkwrap . File ini masuk ke registri npm ketika paket diterbitkan.

Untuk mengotomatiskan operasi ini, perintah npm shrinkwrap dapat ditambahkan ke bagian deskripsi skrip dari file package.json sebagai skrip prabayar. Anda dapat mencapai efek yang sama menggunakan hook komit git. Sebagai hasilnya, Anda dapat yakin bahwa dalam lingkungan pengembangan Anda, dalam sistem CI Anda, dan pengguna proyek Anda menggunakan dependensi yang sama.

Perlu dicatat bahwa teknik ini direkomendasikan untuk digunakan secara bertanggung jawab. Dengan membuat file shrinkwrap, Anda mengkomit versi dependensi tertentu. Di satu sisi, ini berguna untuk memastikan operasi proyek yang stabil, di sisi lain, ini dapat mencegah pengguna memasang tambalan penting, yang, jika tidak, akan dilakukan secara otomatis. Bahkan, npm sangat menyarankan untuk tidak menggunakan file shrinkwrap ketika mengembangkan perpustakaan, membatasi penggunaannya untuk sesuatu seperti sistem CI.

Mencari paket dan informasi ketergantungan


Sayangnya, dengan semua kekayaan informasi tentang manajemen ketergantungan dalam dokumentasi npm, terkadang sulit untuk menavigasi informasi ini. Jika Anda ingin tahu apa yang sebenarnya diinstal selama instalasi dependensi atau paket sebelum mengirim paket ke npm, Anda dapat, dengan perintah yang berbeda, menggunakan flag --dry-run . Penggunaan bendera ini mengarah pada fakta bahwa tim tidak mempengaruhi sistem. Sebagai contoh, perintah npm install --dry-run tidak benar-benar menginstal dependensi, dan perintah npm publish --dry-run tidak memulai proses penerbitan paket.

Berikut beberapa perintah serupa:

 npm ci --dry-run #  ,   package-lock.json   npm-shrinkwrap.json npm pack --dry-run #     ,       npm install <dep> --verbose --dry-run #            

Ringkasan


Banyak hal yang kita bicarakan di sini bergantung pada spesifikasi melakukan berbagai operasi menggunakan npm. Kita berbicara tentang pengemasan, penerbitan, pemasangan paket, bekerja dengan dependensi. Dan mengingat fakta bahwa npm terus berkembang, kita dapat mengatakan bahwa semua ini dapat berubah di masa depan. Selain itu, kemungkinan aplikasi praktis dari rekomendasi yang diberikan di sini tergantung pada bagaimana pengembang paket merasakan masalah menggunakan berbagai versi dependensi di lingkungan yang berbeda.

Semoga materi ini telah membantu Anda lebih memahami bagaimana ekosistem ketergantungan npm bekerja. Jika Anda ingin mempelajari lebih dalam tentang pertanyaan ini - di sini Anda dapat membaca tentang perbedaan antara perintah npm install npm ci dan npm install . Di sini Anda dapat menemukan apa yang sebenarnya masuk ke file package-lock.json dan npm-shrinkwrap.json . Ini adalah halaman dokumentasi npm tempat Anda dapat mengetahui file proyek mana yang termasuk dan tidak termasuk dalam paket.

Pembaca yang budiman! Apakah Anda menggunakan file npm-shrinkwrap.json di proyek Anda?

Source: https://habr.com/ru/post/id453582/


All Articles