זה מאמר שמלמד על grunt. אם אתם לא יודעים מה זה grunt, כדאי שתעיינו במאמר המלמד על Grunt.js ומסביר על ההתקנה ומה זה בכלל.
כשאני משתמש ב-uglify לקבצי ה-JavaScript שלי, autoprefixer לקבצי ה-CSS שלי ודברים נוספים (כמו csslint ו-jshint) אז אני לא רוצה לשנות את קבוץ ה-CSS או ה-JS ואז להריץ את ה-grunt בכל פעם כדי שיריץ את כל התהליכים שאני צריך כמו להוסיף תחיליות, לכווץ ולנקות. אני רוצה שכל התהליכים האלו ירוצו ברגע שאני משנה את אחד מקבצי ה-JS או ה-CSS. ואז כשאני ארפרש את האפליקציה אני אוכל לראות את השינוי שעשיתי.
את זה עושים באמצעות grunt watch. מדובר במודול של grunt שיושב ומאזין לקבצים שאני אומר לו להקשיב – לצורך העניין לקבצי המקור של CSS ו-JS. ברגע שיש שינוי כלשהו, הוא יריץ את המשימות שאני אומר לו.
איך זה עובד? קודם כל… התקנה של המודול
npm install grunt-contrib-watch
עכשיו צריך לומר ל-grunt בפרויקט שהמודול הזה קיים. ניכנס ל-Gruntfile.js ונכניס את השורה הזו שבעצם מודיעה ל-Grunt לטעון את המודול.
grunt.loadNpmTasks('grunt-contrib-watch');
כל מה שנותר הוא להוסיף משימה ל-Grunt. במקרה הזה watch:
watch: { scripts: { files: ['source/*.css'], tasks: ['postcss'], options: { spawn: false, }, }, }
מה יש לנו כאן? הגדרתי watch. שלושת הדברים היחידים שאני צריך להגדיר הוא files – אחרי אלו קבצים או תיקיות אני צריך לעקוב. במקרה הזה הגדרתי שהוא יעקוב אחר כל קבצי ה-CSS. אבל אני יכול להוסיף גם קבצי JS או בכלל להכניס את כל תיקית הפרויקט.
הדבר השני הוא אילו משימות ירוצו כאשר יהיה שינוי. במקרה הזה בחרתי רק במשימה אחת: postcss, אבל אני יכול להכניס משימות רבות נוספות כמו uglify ו-lint.
ב-options כדאי להשאיר את spawn כ-false כי זה יבטיח עבודה יותר מהירה.
אם אתם סקרנים לדעת, כך נראה הקובץ השלם:
module.exports = function(grunt) { grunt.initConfig({ postcss: { options: { processors: [ require('autoprefixer-core')({ browsers: ['last 2 versions', 'Android >= 2.3'] }), // add vendor prefixes ] }, main: { expand: true, flatten: true, src: 'source/*.css', dest: 'css/' } }, watch: { scripts: { files: ['source/*.css'], tasks: ['postcss'], options: { spawn: false, }, }, } }); grunt.loadNpmTasks('grunt-postcss'); grunt.loadNpmTasks('grunt-contrib-watch'); grunt.registerTask('default', ['postcss']); };
מה יש לנו פה? בגדול קובץ Gruntfile.js סטנדרטי לחלוטין. ב-initConfig אני מגדיר 2 משימות. הראשונה היא postcss שעליה דיברתי במאמר על תחיליות ב-CSS3. השניה היא משימת watch שאותה הראיתי קודם. בסוף הקובץ אני משתמש ב-loadNpmTasks על מנת לטעון את מודול postcss ואת contrib-watch. אני משתמש ב- grunt.registerTask('default', ['postcss']); על מנת להגדיר את postcss כ-default.
מה ש-watch עושה הוא לעקוב אחר קבצי ה-CSS שיש בתיקית source וברגע שמישהו מהם משתנה, הוא יפעיל את postcss.
איך זה נראה בפועל? ככה:
$ grunt watch Running "watch" task Waiting... >> File "source/transform2d.css" changed. Running "postcss:main" (postcss) task >> 1 processed stylesheet created. Running "watch" task Completed in 0.117s at Sat Jul 11 2015 20:41:11 GMT+0300 (IDT) - Waiting...
זה הכל! פשוט וקל ובלי להתאמץ. למי שמשתמש ב-yeoman או בדומיו ולא הבין איך בדיוק האפליקציה יודעת להפעיל את ה-build בכל שינוי – זה נעשה כך.
במאמר הבא על Grunt אני מסביר איך לטעון מודולים אוטומטית ב-Grunt ללא כתיבה של loadNpmTasks שוב ושוב ושוב בכל פעם שאני משתמש במודול חדש.