npm מול Yarn מול pnpm - מה ההבדל¶
אם כבר עבדתם עם Node.js, כבר הרצתם npm install מאות פעמים בלי לחשוב פעמיים. אבל אם תסתכלו על ריפואים של פרויקטים אחרים, תגלו שלא כולם משתמשים ב-npm - חלקם עובדים עם Yarn, חלקם עם pnpm. השאלה הטבעית היא למה בכלל יש שלושה כלים שעושים כאילו את אותה עבודה, ומה בפועל משתנה כשבוחרים אחד על פני השני.
למה בכלל קמו אלטרנטיבות ל-npm¶
npm הוא מנהל החבילות שמגיע מובנה עם Node.js, וזו הסיבה שהוא עדיין הכלי הכי נפוץ בעולם - הוא פשוט שם, בלי צורך להתקין שום דבר נוסף. אבל בגרסאות המוקדמות שלו היו לו כמה בעיות אמיתיות - התקנות היו איטיות יחסית, ותהליך פתירת התלויות לא תמיד היה דטרמיניסטי, כלומר שני מפתחים שהתקינו את אותו פרויקט יכלו לקבל עצי תלויות שונים במקצת, מה שגרם לבאגים שקשה לשחזר.
הפער הזה פתח מקום לאלטרנטיבות שניסו לפתור את אותן בעיות בצורה טובה יותר.
Yarn - הדור הראשון של השיפור¶
Yarn יצא כתגובה ישירה לחולשות הראשוניות של npm, והביא איתו כמה שיפורים משמעותיים - התקנות מהירות יותר בזכות caching חכם יותר, וקובץ נעילה - lock file - מפורש שמבטיח שכל מי שמתקין את הפרויקט מקבל בדיוק את אותן גרסאות. Yarn גם הביא תמיכה נוחה ב-workspaces, כלומר ניהול של כמה חבילות בתוך ריפו אחד - monorepo - מה שהפך אותו לפופולרי מאוד בארגונים עם קוד בסיס גדול ומפוצל למודולים.
חשוב לזכור ש-npm עצמו התקדם משמעותית עם השנים ואימץ חלק גדול מהרעיונות האלה, כולל קובץ נעילה משלו וworkspaces. חלק מהיתרון ההיסטורי של Yarn כבר לא כזה משמעותי היום כמו שהיה כשהוא יצא לראשונה.
pnpm - שינוי הגישה מהיסוד¶
pnpm בוחר גישה שונה לגמרי מהבעיה. ב-npm וב-Yarn המסורתי, כל פרויקט מקבל תיקיית node_modules משלו, עם עותק מלא של כל חבילה שהוא צריך. אם יש לכם עשרה פרויקטים על המחשב שכולם משתמשים באותה ספרייה, יש לכם עשרה עותקים זהים שלה, תופסים מקום שוב ושוב.
pnpm פותר את זה עם מחסן מרכזי אחד - content-addressable store - שבו כל גרסה של כל חבילה נשמרת פעם אחת בלבד במחשב. כשפרויקט צריך את החבילה, pnpm לא מעתיק אותה, אלא יוצר קישורים - symlinks או hard links - מתיקיית node_modules של הפרויקט אל המחסן המרכזי. התוצאה - חיסכון ענק בשטח דיסק, במיוחד למי שעובד על הרבה פרויקטים במקביל, וגם התקנות מהירות משמעותית כי לרוב אין צורך להוריד ולהעתיק את החבילה מחדש, רק ליצור קישור אליה.
בנוסף, pnpm מחמיר יותר במבנה node_modules שהוא יוצר, מה שמונע תופעה מוכרת בעייתית שנקראת "תלויות רפאים" - phantom dependencies - מצב שבו קוד משתמש בחבילה שהוא בכלל לא הצהיר עליה כתלות, רק כי היא במקרה הותקנה כתלות של תלות אחרת.
אז מה בוחרים היום¶
כל אחד מהכלים עדיין רלוונטי, בהקשר משלו:
- npm - הבחירה הטבעית כשרוצים אפס הגדרה נוספת. הוא כבר מותקן עם Node, הוא עבד את רוב הבעיות ההיסטוריות שלו, וזו הבחירה הכי פשוטה לפרויקט קטן, ללמידה, או לכל מי שלא רוצה להתעסק עם עוד כלי.
- pnpm - הופך יותר ויותר לברירת המחדל למי ששם לב לביצועים ולשטח דיסק, במיוחד במחשב עם הרבה פרויקטים או בסביבות CI שבהן מהירות התקנה משנה. הרבה פרויקטים חדשים בוחרים בו כברירת מחדל היום.
- Yarn - עדיין נפוץ מאוד בקוד בסיס גדולים וקיימים, במיוחד ב-monorepos שכבר נבנו סביבו. אם אתם מצטרפים לפרויקט קיים שכבר משתמש ב-Yarn, אין סיבה טובה לעבור סתם, ה-workspaces שלו עדיין עובדים מצוין.
מה חשוב יותר מהבחירה עצמה¶
הכלים האלה כולם פותרים את אותה בעיה - התקנה עקבית ואמינה של תלויות. ההבדלים ביניהם משמעותיים בעיקר בביצועים ובניהול שטח דיסק, אבל התהליך הבסיסי - install, קובץ נעילה, package.json - נשאר דומה מאוד בין כולם. אם אתם מבינים איך אחד עובד, קל מאוד לעבור לאחר.
אם עדיין אתם בונים את היסודות של JavaScript ו-Node.js, שווה קודם להבין טוב את הרעיון הבסיסי של חבילות ותלויות לפני שמתעמקים בהבדלים בין הכלים. בקורס תכנות בסיסי אנחנו נותנים את הבסיס הזה, כדי שכל כלי ניהול חבילות, לא משנה איזה, ירגיש הגיוני.
בסוף, npm תמיד יהיה שם כי הוא מגיע מובנה, אבל אם שטח דיסק או מהירות התקנה מטרידים אתכם, שווה לתת ל-pnpm הזדמנות אמיתית.