בפרק זה נלמד על הדברים הבאים:
- כמה מילים על סביבת העבודה (IDE)
- הסבר על שפת הפיתוח (Type script)
- יצירת פרויקט ראשון (Hello World)
- הוספת הקבצים הרלוונטיים. (עם טיפה הסבר על כל אחד מהם)
- הסבר על החלקים המינימליים ביותר שצריך לכתוב.
- הרצת הפרויקט
כמה מילים על סביבת העבודה
בדרך כלל אני עובד עם Visual Studio 2015, בהקשר זה חשוב לציין, שנכון להיום – עבודה עם Visual Studio קצת פחות נוחה (אני מאמין שבהמשך הם יפתרו את כל הבעיות), אז כרגע לפעמים אני עובד עם Web Storm.
הסבר על שפת הפיתוח (Type script)
צריך לדעת להפריד בין שפת פיתוח לבין תשתית לפיתוח, אם נקח לדוגמה את עולם ה – .net, שפת הפיתוח תהיה #C או VB.Net, לעומת זאת עבודה מול טכנולוגיה כגון DB, יכולה להתבצע במספר תשתיות, Ado.net או Entity Framework.
אנגולר 2, היא תשתית פיתוח כמו אנגולר 1 או KO ואחרים שמנסים לתת לנו את הכלים הנכונים כיצד לפתח, Type Script לעומתה היא שפת פיתוח חדשה שמנסה לתת לנו את היכולות של פיתוח עתידני בצד לקוח, בעזרת שפת הפיתוח החדשה נוכל לפתח כאילו אנחנו מפתחים בתקן הבא של Javascript, בנוסף יש לנו את הכלים של עבודה עם Types, מה שמאפשר לנו לעשות “קומפילציה” לקוד JS.
כמובן שנכון להיום עדיין אין תמיכה בדפדפנים בתקן החדש, מה שגורם לכך שבזמן “קומפילציה” הקוד עובר תרגום לקוד JS עדכני, כאשר בהמשך (בעוד מספר שנים) לא נצטרך לעשות את ההמרה הזו.
typescript הוא של מיקרוסופט, אנגולר 2 (של גוגל, כזכור) אימצה אותו לחלוטין ולמעשה כל הדוקמנציה שלה יוצאת מתוך הנחה שנשתמש ב – typescript, אפשר לפתח כמובן ב – JS ישירות, אך זה הרבה יותר מורכב ומסובך, ולכן עדיף ונכון יותר לעבוד עם typescript.
כחלק מסדרה זו לא נתמקד ב – typescript, אך מידי פעם כאשר זה יהיה רלוונטי נגיד כמה מילים על הנושא.
נקודה אחת חשובה להבנה, קבצי typescript שאנחנו נכתוב הינם קבצים עם סיומות ts, אשר עוברות “קומפילציה” ומומרות ל – js, לעומת זאת יש קבצים עם סיומת d.ts, אלו קבצי definition עבור ספריות שונות שנרצה להשתמש בהם ולא בהכרח כתובות ב – typescript, לדוגמא – אם נרצה מתוך קוד ts שלנו להשתמש ב – jQuery, לא נוכל כיון שב – ts אי אפשר “סתם” לכתוב $ ולהפעיל פונקציות, (JS זאת שפה דינמית אשר יוצאת מתוך הנחה שבזמן ריצה jQuery יהיה קיים), לכן ניתן להוריד קבצי d.ts עבור jQuery אשר מכילים את כל “ההגדרות” עבור הספרייה, זה אינו קוד אבל זה מאפשר לקוד ה – ts שלנו לעבור “קומפילציה” וכמובן לתת לנו השלמה אוטומטית וכדו’.
יצירת פרויקט ראשון (Hello World)
בשלב ראשון ניצור פרויקט ריק, ונוסיף ארבע קבצים:
- package.json
- tsconfig.json
- typings.json
- systemjs.config.js
תפקיד package.json, הוא להוריד את כל התלויות שנצטרך כדי לכתוב את הפרויקט, כאן הקובץ טיפ טיפה ישתנה לפי סביבת העבודה, עבור VS2015 יהיה לנו קובץ אחד, ועבור Web Storm יהיה לנו קובץ קצת שונה.
הקובץ עבור VS ייראה כך: (ההנחה היא שהתקנתם npm + node)
"version": "1.0.0",
"name": "MyAngular2Test",
"private": true,
"license": "ISC",
"scripts": {
"postinstall": "typings install",
"typings": "typings"
},
"dependencies": {
"@angular/common": "2.0.0",
"@angular/compiler": "2.0.0",
"@angular/core": "2.0.0",
"@angular/forms": "2.0.0",
"@angular/http": "2.0.0",
"@angular/platform-browser": "2.0.0",
"@angular/platform-browser-dynamic": "2.0.0",
"@angular/router": "3.0.0",
"@angular/upgrade": "2.0.0",
"core-js": "^2.4.1",
"reflect-metadata": "^0.1.3",
"rxjs": "5.0.0-beta.12",
"systemjs": "0.19.27",
"zone.js": "^0.6.23",
"angular2-in-memory-web-api": "0.0.20",
"bootstrap": "^3.3.6"
},
"devDependencies": {
"typings": "^1.3.2"
}
}
נעבור על החלקים הרלוונטיים.
- scripts אלו הגדרות עבור מנגנון ה – npm, אנחנו מבקשים ממנו שלאחר התקנת התלויות, שיריץ סקריפט נוסף שיתקין את typings (מה שמוגדר בקובץ typings.json)
- dependencies אלו ספריות שהוא צריך להוריד, בדרך כלל ישים אותם תחת תיקיית node_modules.
- devDependencies אלו תוספות לפיתוח, אנחנו צריכים כאן הורדה של קבצי d.ts (אלו קבצי הגדרות עבור type script) שאינם מגיעים יחד עם שפת typescript ישירות.
במידה ונעבוד עם Web Storm, נצטרך עוד מספר דברים, כגון הורדה של “שרת” (ב – VS יש לנו את IISExpress), ונצטרך את “הקומפיילר” של קבצי ts, אשר קיים ב – VS (אם הורדתם אותו מהלינק כאן), תוכלו לראות את הקובץ הרלוונטי, כאן (חפשו את package.json)
קובץ tsconfig, משמש את הקומפיילר של typescript להבנה כיצד “לקמפל” את הקוד ל – js, ישנם הרבה מאוד אופציות, כרגע לא נרחיב עליהם, אלא פשוט נעתיק את הקוד.
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": false,
"noImplicitAny": false
}
}
קובץ typings.json, כפי שציינתי לעיל מכיל הורדה של קבצי d.ts אשר אינם מגיעים עם הבסיס
"globalDependencies": {
"core-js": "registry:dt/core-js#0.0.0+20160725163759",
"node": "registry:dt/node#6.0.0+20160909174046"
}
}
אחרון חביב לפני שנוכל להתחיל לעבוד הינו קובץ systemjs.config.js, בשונה מהקבצים הקודמים שהינם עבור הפיתוח, קובץ זה הינו עבור זמן ריצה, בעזרתו נגדיר בזמן ריצה מהיכן להביא את קבצי ה – js הרלוונטיים עבורנו.
systemjs הינו מנגנון module loader, אשר מאפשר לנו להגדיר תלויות של קבצי js, סביר להניח שמי שכתב בעבר קוד, יודע עד כמה מתסכל לדאוג להביא את כל עשרות (או מאות) קבצי ה – js וגם לדאוג לסדר הנכון.
אחד הפתרונות המקובלים בעבר היה ספריית requirejs, ספרייה נהדרת אך עם מספר חסרונות, אנגולר בחרו שנשתמש (לא חובה) בספריית systemjs.
כדי שבזמן ריצה משהו יעבוד חייבים להגדיר את מיקום הקבצים, כך שבזמן פיתוח נוכל להגדיר תלויות, ובזמן ריצה המנגנון ידע מהיכן להוריד את הקבצים.
System.config({
paths: {
'npm:': 'node_modules/'
},
map: {
app: 'app',
'@angular/core': 'npm:@angular/core/bundles/core.umd.js',
'@angular/common': 'npm:@angular/common/bundles/common.umd.js',
'@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
'@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'@angular/http': 'npm:@angular/http/bundles/http.umd.js',
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
'rxjs': 'npm:rxjs',
'angular2-in-memory-web-api': 'npm:angular2-in-memory-web-api',
},
packages: {
app: { main: './main.js', defaultExtension: 'js' },
rxjs: { defaultExtension: 'js' },
'angular2-in-memory-web-api': { main: './index.js', defaultExtension: 'js' }
}
});
})(this);
היות שאנחנו לא לומדים כרגע את systemjs, אני רוצה להסביר “בפשטות” את הדבר הבא
- map מכיל אוסף של שמות, כאשר כל שם ממופה לו היכן נמצא קובץ ה – js הראשי שלו
- packages מכיל אוסף של ספריות כאשר לא מוגדר ב – map ניתוב סופי, איזה קובץ לחפש ומה הסיומת ברירת המחדל
לאחר שיש לנו את ארבעת הקבצים, נוכל לפתוח Command line בתיקייה שבה הקבצים נמצאים ולהריץ את npm install.
הרצת הקוד תגרום להורדת הרבה מאוד ספריות מהרשת, כך שנוכל להתחיל בכלל לעבוד.
הסבר על החלקים המינימליים ביותר שצריך לכתוב.
כעת נרצה להתחיל לכתוב קוד אמיתי כדי לראות Hello על המסך,.
כדי לעשות זאת ניצור תיקייה בשם app, ותחתיה שלוש קבצים
- app.component.ts
- app.module.ts
- main.ts.
נתחיל עם קובץ app.component.ts, אנגולר מבוסס על מושג הנקרא “קומפננטה”, מושג זה מתייחס לחלק כלשהו בתצוגה שלו + הניהול שלו, כעת אנחנו רוצים להגדיר קומפוננטה פשוטה למדי
@Component({
selector: 'my-app',
template: '<h1>My First Angular App</h1>'
})
export class AppComponent { }
ראשית יש לנו פקודת import, פקודה זו “מייבאה” בעזרת systemjs בזמן ריצה את הקובץ הרלונטי לפי מה שהוגדר ב – systemjs.config, שורה זו גם מאפשרת להשלמה האוטומטית של typescript להבין מה אנחנו רוצים לכתוב.
כעת אנחנו מייבאים את המושג Component מתוך angular/core (די דומה ל – using)
נדלג לרגע לסוף, יש לנו הגדרה של מחלקה בשם AppComponent, אשר מוגדרת בעזרת export (מאפשרת לאנגולר לקבל את המחלקה), היות שאנחנו כותבים קוד לוגי (Object Oriented ולא Event Oriented), כל דבר צריך להיות מחלקה, אמנם בשלב זה אין לנו שום לוגיקה, אבל המחלקה צריכה להיות קיימת.
בנוסף נגדיר מחלקה זו כ – Component, נעשה זאת בעזרת הסימון המיוחד @ מעל המחלקה (די דומה ל – Attributes ב – #C, עם הסוגריים המרובעות), נגדיר כאן את ה – selector (כלומר, כאשר יימצא ב- html, צמד המילים my-app, הוא יטען את ה – Component) ואת ה – template (כלומר את התוכן ה – html שאמור להיות כתוב) בנוסף ייוצר מופע של המחלקה (כרגע ללא שום לוגיקה)
נמשיך עם app.module.ts, בקובץ זה נגדיר את ההגדרות הראשונות של הפרויקט שלנו (זהו ה – Entry point שלנו), בו נכתוב את הקוד הבא (לעת עתה ללא הסברים נוספים)
import { BrowserModule } from "@angular/platform-browser";
import { AppComponent } from "./app.component";
@NgModule({
imports: [BrowserModule],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule {
}
בקובץ זה נגדיר את המודול הראשי שלנו (לא נדבר במהלך מדריך זה על מודולים, ולכן לא נסביר את הקובץ הזה לעת עתה)
כעת נסתכל על קובץ main.ts
import { AppModule } from './app.module';
const platform = platformBrowserDynamic();
platform.bootstrapModule(AppModule);
בקובץ זה אנחנו משתמשים במנגון של platformBrowserDynamic, אך שכמו שאפשר לשים לב הפונקציה בשורה האחרונה מקבלת בסופו של דבר את המודול שלנו (ניתן לחבר את שני הקבצים האחרונים לקובץ אחד, מומלץ יותר לפרק אחד עובר כתיבת בדיקות)
הקוד שכתבנו הינו הקוד המינימלי ביותר עבור פרויקט באנגולר 2.
הרצת הפרויקט
לפני שנוכל להריץ, נוסיף קובץ index.html, אשר ייראה כך:
<html>
<head>
<title></title>
<meta charset="utf-8" />
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="systemjs.config.js"></script>
<script>
System.import('app').catch(function(err){ console.error(err); });
</script>
</head>
<body>
<my-app>Loading…</my-app>
</body>
</html>
הקובץ הראשון (shim) נועד כדי לאפשר לדפדפנים ישנים גם כן לעבוד.
שני הספריות הבאות, אלו תלויות של אנגולר (לא נרחיב לעת עתה עליהם)
הספרייה הבאה (system.js) היא עבור הורדת הקבצים, וכמובן נייבא את קובץ הקונפיג שכתבנו עבורו, בשורת סקריפט אחרונה נייבא את קובץ app שלנו, כדי שכל התהליך יתחיל לנגן.
בתוך ה – html, כל מה שצריך לכתוב זה את ה – selector, ואם עשיתם את מה שצריך, בגלישה לדף index צריך להופיע הדבר הבא: