במאמרים הקודמים על Grunt.js למדנו איך עובדים עם מודולים שונים ואיך עושים כל מיני דברים מאוד מגניבים עם Grunt כמו למשל לבדוק את קבצי ה-JS שלי עם תתי משימות – פעם אחת עבור קבצי הסרבר ופעם שניה עבור קבצי הקליינט. כך למשל, מודול jshint מאפשר לי לכלול קבצים שונים וסטנדרטים שונים עבור מטרות שונות – jshint:client ו-js:server.
אבל נניח שאני רוצה ליצור משימה משל עצמי, למשל grunt lint שיריץ מספר תהליכים בו זמנית – כמו למשל scsslint, jshint ו-phpcs (שזה בדיקת תקינות קוד של PHP). איך אני עושה את זה? באמצעות מתודה שנקראת registerTask. היא מקבל שלושה ארגומנטים – הארגומנט הראשון הוא שם המשימה (במקרה שלנו lint), הארגומנט שלנו הוא תיאור (לא חייבים להשתמש בו) והארגומנט השלישי יכול להיות מערך של משימות. למשל, במקרה שלנו, אני אוכל לעשות משהו כזה:
grunt.registerTask('lint', [ 'jshint', 'phpcs' ]);
מה יקרה כשאני אריץ את grunt lint? ירוצו שתי המשימות: jshint ו-phpcs ואקבל דיווח עליהן.
אבל מה קורה למשל אם אני צריך שני סוגי lint? יש לי למשל אפליקציה שיש לה lint מסוג אחד על צד הלקוח ו-lint מצד שני על צד השרת. לכל lint יש את הכללים שלו. למשל, אם אני מריץ lint על צד הלקוח, חשוב לי שהוא יעמוד בסטנדרטים של ECMAScript 5, אבל בצד השרת אני רוצה שהוא יהיה כבר ב-ECMAScript 6. בצד הלקוח console הוא משתנה גלובלי וגם document, אבל בצד השרת לא. בגלל זה מקובל במשימת jshint להריץ שתי מטרות: jshint:client עבור צד הלקוח ו jshint:server עבור צד השרת ודיברתי על זה במאמר על תתי משימות.
נניח ואני רוצה ליצור משימה של lint:server ו-lint:client שכל אחד מהם יריץ task אחר. אם כך, אין בעיה כלל. הארגומנט השלישי יהיה פונקצית callback שהארגומנטים שלהם מורכבים מהמטרות שאנו כותבים בשורת הפקודה.
נשמע מבלבל? ממש ממש לא! שימו לב לדוגמה הקטנה שתבהיר את הכל:
grunt.registerTask('validate', function(arg1) { switch (arg1) { case 'client': grunt.task.run('jshint:client'); break; case 'server': grunt.task.run('jshint:server'); break; default: grunt.warn('server or client please'); } });
מה קורה פה? אני מעביר פונקציה שהארגומנט שלה הוא בעצם המשימה שלי. למשל אם כתבתי grunt validate:client אז הארגומנט הוא client. אם כתבתי grunt validate:ahla, אז הארגומנט הוא ahla. מפה זה רק JavaScript בסיסי – אני בודק מה המשתמש הכניס בשורת הפקודה ופועל לפי זה. אני כמובן יכול לקבוע שבמידה ואין לי ארגומנט או שהארגומנט הוא לא client או server, אני יכול להריץ את כל המשימות יחדיו.
שימו לב לשתי פקודות מעניינות – הראשונה היא grunt.task.run שמריצה בעצם משימות והשניה היא grunt.warn שצועקת ומפילה את הבילד.
ה-API של grunt מאוד מעניין ואפשר לעשות איתו עוד דברים. למשל, אם אין לנו ידע מוקדם על המשימות, אנו יכולים להשתמש ב-registerMultiTask. אבל זה כבר סיפור אחר. למשימות בסיסיות, אפשר להשתמש בקוד שנמצא לעיל.