מבנה פרויקט Node.JS
ב Node.JS יש שלושה סוגים מרכזיים של פרויקטים שאנחנו עשויים לפגוש: פרויקטי CommonJS, פרויקטי ESM ופרויקטי TypeScript.
1. למה שלושה סוגי פרויקטים
כש Node.JS נוצר JavaScript היתה במצב הרבה פחות מתקדם ממה שהיא היום, ו TypeScript עדיין לא נוצרה. לכן ריאן דל היה צריך להיות יצירתי ולהמציא הרבה מבנים שהשפה צריכה ופשוט לא היו קיימים. לימים במיוחד עם יצירת התקן של ES Modules ויצירת TypeScript מתכנתים רצו להשתמש בכלים אלה כדי ליצור פרויקטי Node.JS וכך גם Node עצמה היתה צריכה להתפתח. היום אנחנו מדברים על שלושה סוגים מרכזיים של פרויקטי Node.JS שאנחנו עשויים למצוא, כשההבדל המרכזי ביניהם הוא שיטת ההרצה והקשר בין קבצים בתוך הפרויקט:
-
פרויקט Node קלאסי עליו נלמד בשיעור זה, ישתמש בכתיב מודולים שנקרא CommonJS ובמילה require כדי לטעון קבצים אחרים בפרויקט.
-
פרויקט ES Modules עליו נלמד בשיעור הבא, ישתמש בכתיב מודולים שנקרא ESM ובמילה import כדי לטעון קבצים אחרים בפרויקט.
-
פרויקט TypeScript. אלה הפרויקטים המורכבים ביותר מבחינת מנגנון הבנייה שכן הם משתמשים בכלי בשם TypeScript Compiler כדי לבנות את קבצי ה CommonJS של Node מתוך קבצי ה TypeScript שאנחנו כותבים. אפשר למצוא הסבר על פיתוח פרויקט TypeScript ב node.js בקורס טייפסקריפט בקישור: https://www.tocode.co.il/bundles/typescript/lessons/typescript-node-js?tab=text
בנוסף לאלה יש גם תבניות פרויקט ספציפיות לפריימוורקים מסוימים, למשל ל Next.JS יש תבנית פרויקט משלהם המבוססת על טייפסקריפט. ברוב הקורס אני משתמש בכתיב ה CommonJS הקלאסי בשביל לכתוב את תוכניות הדוגמה כי זה הכתיב שיש לו את התאימות הטובה ביותר למודולים חיצוניים ולא דורש קומפילציה בשביל להריץ. בפרויקטים שלכם אני ממליץ לבחור את סוג הפרויקט שהכי מתאים לצרכים שלכם, ואם אתם יכולים TypeScript הוא בעיניי מבנה הפרויקט הטוב ביותר היום לפרויקט Node.JS.
2. יצירת הפרויקט
צרו תיקיה חדשה על המחשב בשם myapp. פיתחו את מסך ה cmd וכנסו עם cd לתיקיה. כשאתם בתוך התיקיה כתבו:
$ npm init -y
והכלי אוטומטית ייצור לכם קובץ בשם package.json
בתיקייה עם התוכן הבא:
{
"name": "myapp",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
את שם הפרויקט npm לקח אוטומטית משם התיקיה. כל השאר הם ברירות מחדל. בהמשך נראה איך לרשום ערכים בשדה scripts שיעזרו לנו בהרצה.
בינתיים פיתחו ב VS Code לעריכה קובץ חדש בשם index.js ובו כתבו את התוכן:
console.log('Hello World');
המשיכו לערוך את הקובץ package.json ועדכנו אותו כך שיכיל את התוכן הבא:
{
"name": "myapp",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
בחזרה ל cmd ושם נכתוב:
PS C:\Users\ynonp\demo1> npm start
> demo1@1.0.0 start
> node index.js
Hello World
PS C:\Users\ynonp\demo1>
PS C:\Users\ynonp\demo1>
בתגובה המחשב באופן אוטומטי הריץ עבורנו את הפקודה שרשמנו בשדה scripts.start שהיא הפקודה שהפעילה את הפרויקט.
3. טעינת פונקציה מקובץ אחר בפרויקט
ניצור בפרויקט תיקייה חדשה בשם src
ובתוכה קובץ חדש בשם utils.js
ובתוכו נכתוב את התוכן הבא:
exports.twice = function(x) {
return x * 2;
}
אל תהיו מודאגים אם אתם לא מבינים מאיפה הגיע המשתנה exports, יש לנו שיעור עליו בהמשך הקורס. בגדול משתנה זה מאפשר לנו לשתף פונקציות ומשתנים בין קבצים שונים בפרויקט. נחזור לקובץ index.js
ושם נכתוב:
const {twice} = require('./src/utils');
console.log(`6 * 2 = ${twice(6)}`);
עכשיו כשאני מריץ את התוכנית אני מקבל את התוצאה 12 כי הקובץ index טען את הפונקציה שהוגדרה בקובץ utils.
4. טעינת פונקציה מספריה חיצונית
פרויקט node יכול להשתמש במאגר עצום של חבילות חופשיות מהרשת שנקרא npm. חזרה ל cmd ושם כתבו:
> npm add express
נ.ב. לפעמים אתם תראו בהוראות התקנה פקודות כמו npm install
, npm install --save
או npm add --save
. בגירסאות עדכניות של node.js כל הפקודות האלה זהות. אני משתמש ב add בדוגמה כאן כי הוא הכי קצר, אבל במקומות אחרים בקורס משתמש גם בפקודות האחרות, חלק מתוך הרגל וחלק כי אלה שיעורים שהוקלטו כשעוד היה הבדל בין האפשרויות.
אחרי קצת עבודת חשיבה המחשב יחזיר אתכם לשורת הפקודה והפעם עם קצת דברים חדשים. הקובץ package.json השתנה והוא כעת נראה כך:
{
"name": "myapp",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.16.4"
}
}
בנוסף נוצרה לכם תיקיה חדשה בשם node_modules
שמכילה די הרבה תתי ספריות, אחת מהן נקראת express.
מנגנון שילוב מודולים חיצוניים בפרויקט משתמש בקובץ בשם package.json כדי לתאר את התלויות בין הפרויקט למודולים החיצוניים. השדה dependencies בקובץ מתאר את כל המודולים החיצוניים והגירסאות שלהם שהפרויקט שלנו צריך. אבל הקובץ package.json לא כולל את קוד המודולים עצמם - בשביל זה יש את הספריה node_modules
. בספריה זו תמצאו את הספריה express
החדשה שביקשנו להתקין, וגם את כל הספריות ש express
צריכה כדי לעבוד כמו שצריך.
בנוסף נוצר לכם קובץ בשם package-lock.json
. קובץ זה הרבה יותר ארוך וכולל את הגירסאות הספציפיות של כל התלויות שהותקנות בספריית node_modules
. כשתגיעו להפיץ את הפרויקט אתם לא צריכים להפיץ איתו גם את כל תיקיית node_modules
שהיא ענקית. אם יש למישהו את הקבצים package.json
ו package-lock.json
הוא תמיד יכול להפעיל משורת הפקודה:
> npm install
בלי פרמטרים ולקבל עותק חדש של ספריית node_modules
עם כל המודולים שמוזכרים בקבצים אלה.
בואו ננסה את זה! מחקו את התיקיה node_modules
לחלוטין ואז הריצו:
> npm install
ותוכלו לראות ש npm הלך לרשת והביא מחדש את כל התוכן שהיה קודם ב node_modules
.
בהמשך הקורס נדבר יותר לעומק על package.json, על משמעות המספרים ליד החבילות ועל שידרוג חבילות. בינתיים בואו נלך לעדכן את התוכנית שלנו כך שתשתמש במודול החדש שהתקנו ותריץ שרת ווב.
5. עדכון התוכנית והפעלת שרת ווב
החליפו את תוכן הקובץ index.js בקוד הבא:
const express = require('express')
const app = express()
const port = 3000
app.get('/', (req, res) => {
res.send('Hello World!')
});
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
חזרו ל cmd והפעילו את הפרויקט עם:
> npm start
עכשיו אפשר להפעיל דפדפן ולהיכנס לכתובת localhost:3000 כדי לראות את הודעת ה Hello World שלנו.
שרת Express שומר על הרוח של node.js:
-
הקוד בנוי בתור יצירת רצף של Event Handlers: כל פעם שמשתמש מגיע לנתיב מסוים יש לקרוא לפוקנצית טיפול מתאימה.
-
כל פונקציית Event Handler מקבלת אוביקט בקשה ואוביקט תשובה. היא יכולה להשתמש באוביקט הבקשה כדי לבחון את המידע שהלקוח שלח ועליה לכתוב תשובה לאוביקט התשובה.
-
השרת ממשיך לרוץ עד שנעצור אותו כי Express דואג להשאיר תהליך אסינכרוני פתוח: תהליך ההמתנה לגולש חדש.
שימו לב-
בוידאו השתמשתי ב npm add כדי להתקין מודול וכדי ליצור פרויקט באותה פקודה. זה עובד רק בתנאי שאתם עובדים בתיקייה שלא קיים בה פרויקט node וגם שבאף תיקייה מעליה לא קיים פרויקט node (אם כבר קיים פרויקט באחת התיקיות במעלה העץ, ה add רק יוסיף את המודול לפרויקט הקיים שהוא מצא). בשביל ליצור פרויקט חדש בתיקייה שגם מעליה יש פרויקט יש להפעיל את הפקודה:
npm init -y
משורת הפקודה בתיקיית העבודה שלכם ורק לאחר מכן להפעיל:
npm add express