בעבר, כשהיינו כותבים לקליינט, החיים היו פשוטים (ומרגיזים) – היינו כותבים פשוט CSS ו-HTML. כשהיינו צריכים לדבג? בתקופת ימי הפלמ"ח העליזים, לא היו הרבה כלים ואז הגיעו כלי המפתחים – אופרה עם Dragonfly ופיירפוקס עם פיירבאג שאיפשרו לכל מפתח להסתכל על צד הלקוח בנוחות וביעילות ואף לשנות אותו. כל דפדפן מאז, אפילו אקספלורר העקום ואדג' המחליא, מתהדרים בכלי מפתחים משלהם.
מה שהשתנה הוא ה-JS וה-CSS עצמם. היום יש לנו LESS ו-SASS, וה-CSS שהם מייצרים עובר תהליך מיניפיקציה ודחיסה. קבצי ה-JS גם הם עוברים תהליך של uglify ודחיסה ועוד לא התחלנו לדבר על coffescript או GWT ושאר הקללות שמוסיפות עוד שכבת אבסטרקציה בינינו לבין קובץ ה-JS או ה-CSS המקומפל.
נשאלת השאלה איך מדבגים את זה. איך למען השם אני יכול לדעת עם כלי המפתחים מה השורה המקורית והקובץ המקורי של קובץ CSS שעבר קומפליציה, אגליפיקציה, מיניפיקציה והקבר-השחור-של-סבתא-שלך-קציה? אם יש לי כמה קבצי SCSS בודדים, אין בעיה -אני יכול באמצעות דדוקציה והרבה search טוב למצוא את השורה המקורית. אבל מה עם פרויקטים גדולים?
בדיוק בשביל זה יש לי את sourcemap שמקשר בין הקבצים המקומפלים לקבצי המקור הנקיים שעליהם אני עובד, ולא משנה מה עבר על הקבצים האלו במהלך הקימפול.
הכנסו לדף הדוגמה שלי כאן. הדף הזה הוא דף HTML פשוט, אך קובץ ה-CSS שלו קומפל מקבצי SASS. הפעילו את כלי המפתחים בכרום או בפיירפוקס (לא פיירבאג אלא כלי המפתחים הדיפולטיבי של פיירפוקס) וסמנו את אחד האייטמים ברשימה. תוכלו לראות שהמקור של העיצוב לא מופיע כקובץ CSS אלא כקובץ SCSS, שהוא הקובץ המקורי שממנו קומפל ה-SCSS!
הנה הדוגמה למי שמתעצל לבדוק בעצמו:
איך זה עובד? ראשית, הנה מבנה ה'פרויקט' שלי:
├── Gruntfile.js ├── package.json ├── public │ ├── index.html │ ├── mystyle.css │ └── mystyle.css.map └── source-scss ├── _list.scss └── mystyle.scss
הסבר על ה-Grunt שמקמפל את כל הסיפור הזה
אם זה לא מעניין אתכם, דלגו לכותרת הבאה: ה-sourcemap
מה שמעניין אותנו הוא כמובן שני דברים עיקריים. קובץ ה-package.json שמאפשר לי להתקין את כל המודולים של Grunt (כולל זה של Grunt כמובן) בקלות באמצעות npm install. על קובץ package.json סיפרתי במדריך על node.js. הקובץ השני שמעניין אותנו הוא ה-Grunt.js שמכיל שתי הוראות – הוראת sass שמקמפלת את קבצי המקור ששוכנים להם לבטח ב-source-scss. והוראת watch שמבצעת את הקימפול בכל פעם שאני נוגע בקבצי המקור.
module.exports = function(grunt) { grunt.initConfig({ sass: { dist: { files: [{ cwd: 'source-scss', //start in THIS direcory expand: true, //descent into directories src: ['*.scss'], //patttern for files dest: 'public', //destination folder ext: '.css' //destination file extension }] } }, watch: { scripts: { files: ['source-scss/*.scss'], tasks: ['sass'], options: { spawn: false, }, }, } }); grunt.loadNpmTasks('grunt-contrib-sass'); grunt.loadNpmTasks('grunt-contrib-watch'); };
על קובץ ה-Grunt.js הזה הסברתי בפירוט במאמר שמספר על קימפול אוטומטי של SASS. מה שלא הסברתי הוא שבאופן אוטומטי, grunt-sass-contrib מייצר גם sourcemap. כמעט כל המודולים של grunt שעושים קומפילציה של CSS או JS מכילים גם את האפשרות ליצור sourcemap באופן אוטומטי. כאשר אנחנו משתמשים במודול לביצוע משימת קומפילציה, חשוב לוודא שהמשימה ב-Grunt (או ב-gulp) מייצרת לנו sourcemap. בדרך כלל הם עושים את זה אוטומטית.
מה שחשוב, מבחינת אבטחת מידע, הוא לא לתת ל-sourcemaps להיות זמינים לגולשים רגילים. בדרך כלל בתהליך ה-build בפרודקשן לא נותנים ל-sourcemap להיבנות כלל בשרת הפרודקשן.
Sourcemaps
בת'כלס, מה שמעניין אותנו בפרויקט הזה שקבצי ה-CSS, שנמצאים ב-public, הם קבצים 'מלאכותיים', שנוצרו מקימפול כלשהו. איך אנו יודעים שקובץ ה-CSS מכיל הפניה ל-sourcemap? בקובץ ה-CSS הזה, אם תסתכלו עליו, תוכלו לראות שיש שורה אחת בקובץ ה-CSS שמצביעה על ה-sourcemap:
/*# sourceMappingURL=mystyle.css.map */
נוכל לראות גם בעץ הפרויקט שאכן יש לנו קובץ בשם mystyle.css.map. הקובץ הזה הוא-הוא ה-sourcemap שמאפשר לכלי המפתחים לקשר בינו לבין קבצי המקור. כאשר אנו עוסקים בקבצי CSS שג'ונרטו מקבצים אחרים, חובה לוודא שהשורה הזו מופיע שם וגם שהקישור אליה ולידי ומכיל קבצים. כמובן אם אנו רוצים לדבג את הסיפור הזה.
בגדול? זה הכל. בניגוד לשנים עברו, כל כלי המפתחים תומכים בזה. אפילו אקספלורר 11 העלוב תומך בזה (בגרסה המותקנת בחלונות 8.1). למרבה הצער פיירבאג עדיין לא תומך בזה, אבל כלי המפתחים האינהרנטי של פיירפוקס תומך בזה.