npm-shrinkwrap ככלי לנעילת גרסאות

ביצוע version pinning למודולים ב-npm ושימוש ב-npm-shrinkwrap.json כדי לנעול גרסאות גם במודולים שמותקנים על ידי משתמשים באמצעות npx או npm install.
Node.js Logo

במאמר הקודם על נעילת גרסאות וניהול dependencies, הסברתי על package-lock.json ועל ההבדל בין npm install ל-npm ci. במאמר הזה אני מרחיב ומלמד על npm-shrinkwrap, כלי שמאפשר לנו נעילת גרסאות ב-npm ומסייע לכל מי שמפרסם מודולים שמפובלשים ממש ב-npm (או במקבילה פרטית שלו).

שני סוגי תוכנות על בסיס Node.js

ב-Node.js יש לנו שני סוגי תוכנות (ממש בהכללה). הראשונה היא אתר או אפליקציה שבנויות עם Node.js. השניה היא מודול שמופיע ב-npm ממש ואמור להיות מותקן כחלק מאפליקציה.

אם אתם רוצים דוגמה – אז אתר התרגילים שבניתי עבור hebdevbook.com, זה דוגמה לאתר שבנוי על בסיס Node.js. יש לו package.json, יש לו מודולים שהוא מתקין כדי לעבוד ולייצר לי בסוף בילד ותוצר. ההפעלה של npm install או npm ci נעשית רק במהלך הבילד או התקנה על ידי מפתח שרוצה להמשיך ולפתח את האתר.

דוגמה למודול היא למשל המודול branch-lint ששחררתי ל-npm. מדובר במודול שאמור להיות מותקן על ידי המשתמש. ה-npm install\npm ci שלו נעשים ברגע ההתקנה או בכל בילד. זה מודול של npm.

Version pinning במודול

כמו אתר, גם במודול אני נדרש לעשות version pinning. אבל הבעיה היא שכשאני עושה npm publish (מאמר המסביר על זה פה), אי אפשר להכניס את package-lock.json כחלק מה-publish. הוא לא עובד עם הקובץ package-lock כי הקובץ הזה מיועד למפתחים שמפתחים אפליקציה/אתר – לא למי שמתקין מודול. כשמישהו עושה npm install למודול שפיבלשנו, ה- package-lock.json שלנו לא יכובד.

ואז אנו בבעיה. כי אנו חושפים את כל מי שעושה npm install ל-npm package שלנו לבעיות אבטחה ובעיות אחרות שנובעות מהעדר version pinning. אז איך עושים version pinning למודולים? עם npm-shrinkwrap.json.

npm-shrinkwrap.json

מדובר בקובץ שזהה אחד לאחד ל-package-lock.json. גם הוא מכיל את כל התלויות. ההבדל המרכזי ביניהם? הוא כן נכנס ל npm publish וכאשר משתמשים אחרים מתקינים את המודול שלנו באמצעות npx או npm install, מה שיש בקובץ הזה יכובד והתלויות שהמשתמשים יתקינו יהיו זהות אחד לאחד למה שיש בו.

בתוכנה שלנו אמור להיות package-lock או npm-shrinkwrap.json (אחד מהם, תלוי בסוג התוכנה כפי שהסברתי לעיל) והם אמורים להכנס לגיט (או לכל ניהול גרסאות שאנו משתמשים בו). npm ci יכבד את npm-shrinkwrap.json.

איך מייצרים את npm-shrinkwrap.json? באמצעות הרצת הפקודה:

npm shrinkwrap

הפקודה הזו ממירה את package-lock.json לקובץ npm-shrinkwrap.json. את הקובץ הזה אנו מכניסים לגיט, npm ci יעבוד לפיו וכשאנו עושים npm publish, הוא יקח את הקובץ הזה. כשמישהו יעשה npm install\npx למודול שלכם – התלויות יהיו לפי npm-shrinkwrap.json ולפיו בלבד.

למה בדיוק צריך את זה? המקרה של is-promise יכול ללמד את כולם לקח חשוב. מדובר במודול של npm בן שורה אחת שנועד לוודא שאובייקט מסוים הוא promise. הוא עודכן בעדכון ששבר אותו. המפתח שעשה את התיקון פשוט טעה ב-semantic version ובטעות עדכן גרסת מיינור בעדכונים שוברים.

למה צריך את זה?

כמובן שלא מעט מודולים השתמשו במודול הזה ואחד מהמודולים האלו הוא create react app המפורסם. ברגע שהמודול is promise נשבר, כל מי שהתקין את create react app באמצעות npx, לא הצליח לבצע את ההתקנה כיוון שב-create react app לא היה version pinning ולא היה npm-shrinkwrap.json. כל המשתמשים שניסו להתקין את create react app התקינו את המודול המעודכן. בום, שבירות המוניות, בלגן, כאוס ורצח ברחובות. לירן טל פירט באופן מאוד נאה על התקרית הזו כאן.

לסיכום – package-lock.json אם אתם מפתחים תוכנה ב-Node.js. השתמשו ב-npm-shrinkwrap.json אם אתם מפתחים מודול ל-npm.

פינת משתמשי ה-yarn – במקרה הזה yarn.lock משמש הן כ-npm-shrinkwrap.json והן כ-package-lock.json. אז רק תקפידו שיהיה את הקובץ הזה. יאללה, הרווחתם את ההתנשאות שלכם הפעם.

⚠️ תזכורת – המדריכים האלו הם רק טעימה, בספר שלי "ללמוד Node.js בעברית" יש הסברים מלאים ומקיפים על השפה המיועדים ללימוד עצמי. עם תרגילים והסברים. הספר יצא לאור בשיתוף הקריה האקדמית אונו ובתמיכת החברות אלמנטור, ו-Iron source ונערך טכנית על ידי בנג'י גרינבאום (מפתח ליבה של Node.js), גיל פינק ומתכנתים מעולים נוספים. 

פוסטים נוספים שכדאי לקרוא

מיקרו בקרים

בית חכם עם ESPHome ו Home Assistant

הסבר על הום אסיסטנט, מערכת הקוד הפתוח לבית חכם ואיך לחבר אליה מיקרובקרים.

גלילה לראש העמוד