גם בצד השרת טייפסקריפט עובדת לא רע בכלל

27/01/2019

פוסט זה מכיל טיפ קצר על עבודה עם Node.JS. כדי ללמוד Node.JS הרבה יותר לעומק אני ממליץ לכם לבדוק את קורס Node.JS כאן באתר. הקורס כולל עשרות שיעורי וידאו מוקלטים והמון תרגול שילוו אתכם מהצעד הראשון בעבודה עם Node.JS ועד הנושאים המתקדמים.

הקומפיילר של טייפסקריפט מצליח להתמודד יפה גם עם יישומי צד שרת גדולים כולל כאלה שמורכבים ממספר קבצים. מאחר ו TypeScript ו JavaScript עובדות יפה יחד אנחנו יכולים בקלות להוסיף קבצי TypeScript לפרויקט צד שרת קיים. בפוסט זה ניקח יחד את הצעד הראשון.

1. התקנת הכלים

אם כבר יש לכם פרויקט אקספרס תוכלו להתחיל ממנו, אם לא אפשר ליצור אחד עם Express Generator. תחילה התקינו את Express Generator בהתקנה גלובלית עם:

$ npm install -g express-generator

ואז הפעילו אותו כדי ליצור פרויקט אקספרס חדש:

$ express hello-express-ts
$ cd hello-express-ts
$ npm install

נוסיף את TypeScript לפרויקט:

$ npm install --save typescript

ואנחנו מוכנים להתחיל.

2. עידכון הגדרות הפרויקט כך שישתמש ב TypeScript

הדרך הכי נוחה לשלב TypeScript בפרויקט קיים היא לבקש מ tsc לקמפל את כל הקבצים, כולל קבצי ה js שלכם, ולשים את התוצאה בתיקיה נפרדת למשל תיקיה בשם build. אחרי זה נעדכן את ההגדרות כדי שאקספרס ימצא את הקבצים שלנו וקבצי הנתיבים ימצאו את ה Views וכך נקבל תיקיה בשם build עם כל קבצי הקוד אחרי קומפליציה, וקבצי המקור יישארו איפה שהיו קודם.

תחילה בתיקיה הראשית של הפרויקט צרו קובץ tsconfig.json עם התוכן הבא:

{
    "compilerOptions": {
      "noImplicitAny": true,
      "module": "commonjs",
      "target": "es2017",
      "lib": ["es2017"],
      "allowJs": true,
      "esModuleInterop": true,
      "strictNullChecks": true,
      "moduleResolution": "node",
      "outDir": "build",
    },
    "include": ["**/*"],
    "exclude": ["node_modules", "build"]
  }

לאחר מכן עדכנו בקובץ bin/www כך שיטען את קובץ app מתיקיית build החדשה שלנו במקום מקובץ המקור. זה אומר לשנות את השורה הראשונה בקובץ איפה שכתוב:

var app = require('../app');

ולהחליף אותה ל:

var app = require('../build/app');

לסיום בתוך הקובץ app.js נרצה לשנות את הנתיב לתיקיית ה views כך שאקספרס יחפש אותה תיקיה אחת למעלה - כי הקוד שלנו ירוץ מתיקיית build החדשה במקום מהתיקיה הראשית. כלומר במקום השורה:

app.set('views', path.join(__dirname, 'views'));

יש לכתוב:

app.set('views', path.join(__dirname, '..', 'views'));

3. הוספת קובץ TypeScript לפרויקט

בשביל המשחק בואו נוסיף את קובץ ה TypeScript הבא לפרויקט המייצג מחלקה של מירוץ מכוניות:

// file: lib/race.ts
interface Car {
    color: string,
    speed: number,
}

class Race {
    cars: Car[];

    constructor() {
        this.cars = [];
    }

    addCar(color: string, speed: number) {
        this.cars.push({ color, speed });
    }

    findWinner(): (Car | null) {
        if (this.cars.length === 0) {
            return null;
        }

        return this.cars.reduce((a, b) => a.speed > b.speed ? a : b);
    }
}
module.exports = new Race();

אני שמרתי את הקובץ בתיקיה בשם lib וקראתי לו race.ts. מה שחשוב כאן זה רק הסיומת ts.

אנחנו יכולים לטעון את הקובץ מתוך קבצי js רגילים בפרויקט, לדוגמא נוכל לעדכן את קובץ הנתיבים כך שישתמש במחלקת המירוץ החדשה שלנו - למרות שקובץ הנתיבים הוא js רגיל והמירוץ הוא TS. כך נראה קובץ הנתיבים routes/index.js אחרי השינוי אצלי:

var express = require('express');
var router = express.Router();
var theRace = require('../lib/race');

/* GET home page. */
router.get('/', function(req, res, next) {
  console.dir(theRace);
  res.render('index', { title: 'Express', winner: theRace.findWinner() });
});

router.post('/', function(req, res, next) {
  const { color, speed } = req.body;
  theRace.addCar(color, speed);
  res.sendStatus(200);
});

module.exports = router;

4. בניה והפעלה

משורת הפקודה בתיקיית הפרויקט הראשית נכתוב:

$ tsc

מה שיוביל ליצירת תיקיית build עם הקבצים הבאים:

build/
├── app.js
├── lib
│   └── race.js
└── routes
    ├── index.js
    └── users.js

הכלי tsc העתיק את כל קבצי ה js לאותו עץ תיקיות תחת התיקיה build, והפך כל קובץ ts ל js כך ש node יוכל להפעיל קבצים אלה.

ואם הכל הלך כמו שצריך תוכלו להפעיל את הפרויקט עם:

$ node bin/www

ולהנות מהקוד המעורבב שיצרתם.

קוד פרויקט הדוגמא שלי במלואו זמין בגיטהאב בקישור:

https://github.com/ynonp/express-ts-demo