איך משתמשים ב-Baseline בפרויקט

1. מבוא

Baseline היא יוזמה שמטרתה לספק מידע ברור יותר על תכונות אינטרנט שניתן להשתמש בהן היום באופן בטוח ועם יכולת פעולה הדדית. הודות להתקדמות בכלי Baseline, עכשיו אפשר להשתמש ב-Baseline ישירות בפרויקטים כשאילתת Browserslist, כך ששרשרת הכלים יכולה לשנות את פלט הקוד על סמך יעד ה-Baseline שתבחרו.

בשיעור הזה תלמדו איך להשתמש ב-Baseline בפרויקט לדוגמה, ואיך להגדיר אותו כדי לבחור יעד ספציפי של Baseline. תוכלו גם לראות איך הפלט של שרשרת הכלים של הפרויקט משתנה בהתאם ליעד הבסיסי שבחרתם.

2. הגדרת ההדגמה במחשב המקומי

קודם כל, עוברים לאפליקציית המסוף המועדפת, משכפלים את מאגר ההדגמה ואז נכנסים לספריית הפרויקט:

git clone git@github.com:GoogleChromeLabs/baseline-demos.git
cd baseline-demos/tooling/webpack-browserslist-config-baseline

בשלב הזה, ההדגמה כבר תכלול את Baseline, אבל כדאי לבדוק קומיט שמתחיל מאפס:

git checkout 94f12e34

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

nvm install
nvm use

מכאן, מתקינים את החבילות של הפרויקט:

npm install

כדי לראות את ההדגמה, מריצים את הפקודה הבאה:

npm start

עוברים אל http://localhost:8080. ההדגמה עצמה היא רשימה של כרטיסים שאפשר לסנן באמצעות שדה טופס בחלק העליון של הדף. האפליקציה עצמה משתמשת בשילוב של תכונות שהגיעו לסף של Baseline.

בסיום ההדגמה, עוברים לטרמינל ומקישים על Ctrl+C כדי להפסיק את ההדגמה בכל שלב.

3. איך משלבים את Baseline בפרויקט

בהדגמה הזו לא מצוינת הגדרת Browserslist בהתחלה. ‫Browserslist היא תחביר קומפקטי של שאילתות שמציין לשרשרות כלים אילו גרסאות מינימליות של דפדפנים צריכות להיות נתמכות. לדוגמה, שימוש בשאלת last 3 years יגדיר טווח רחב של יעדים. בהדגמה הזו נשתמש בחבילת npm בשם browserslist-config-baseline כדי לציין שאילתת Browserslist תתאים ליעדי Baseline שאפשר להשתמש בהם בשרשרת הכלים.

כדי להתחיל, מתקינים את browserslist-config-baseline כך:

npm install browserslist-config-baseline --save-dev

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

  • יעדים משתנים, שמתעדכנים לאורך זמן ככל שיוצאות גרסאות חדשות של דפדפנים:
    • Baseline Newly available, שמתאים לתכונות שניתנות להפעלה הדדית ומיושמות בכל סט הדפדפנים המרכזיים בכל זמן מהיום ועד לפני 30 חודשים.
    • Baseline Widely available, שכולל תכונות שניתנות להפעלה הדדית והוטמעו בסט הליבה של הדפדפנים לפני 30 חודשים או יותר.
  • טירגוטים קבועים, שמייצגים גרסאות של דפדפנים בנקודת זמן קבועה. הם מופיעים כשנים מ-2016 עד השנה הנוכחית.

כדי להתחיל, נשתמש ב-browserslist-config-baseline כדי לבחור את יעד הבסיס הנרחב שזמין לפרויקט. כדי לעשות את זה, פותחים את package.json ומוסיפים את הפרטים הבאים:

"browserslist": "extends browserslist-config-baseline"

4. בחירה ביעדי בסיס שונים כדי לראות שינויים בפלט של הקוד

בחרתם ב-Baseline Widely available כיעד לפרויקט ההדגמה. בשלב הבא, צריך ליצור את הפרויקט:

npm run build

יש הרבה פלט נוסף כי האפשרות debug של @babel/preset-env מוגדרת כ-true ב-babel.config.js של הפרויקט. קודם כול, מציינים את הגודל של ה-CSS ושל ה-JavaScript בנתונים הסטטיסטיים של ה-bundler:

assets by status 213 KiB [emitted]
  asset js/home.5f3c5480.js 208 KiB [emitted] [immutable] [minimized] (name: home) 2 related assets
  asset css/home.20db50ef.css 3.64 KiB [emitted] [immutable] (name: home) 1 related asset
  asset index.html 564 bytes [emitted]

שימו לב שחבילת ה-JavaScript היא 208 KiB, וקובץ ה-CSS הוא 3.64 KiB. הפרויקט הזה משתמש ב-core-js כדי להחיל polyfills של JavaScript וב-autoprefixer כדי להחיל קידומות ספציפיות לספקים על מאפייני CSS שעדיין לא ניתנים להפעלה הדדית באופן מלא. ההשפעה של browserslist-config-baseline היא על core-js וגם על autoprefixer.

עוד דבר שחשוב לשים לב אליו בפלט הוא איך השאילתה שלכם ב-Browserslist לגבי תכונות בסיסיות שזמינות באופן נרחב מתורגמת לשאילתה ב-Browserslist. בפרויקט, זה ייראה בערך כך:

Using targets: {
  "chrome": "108",
  "edge": "108",
  "firefox": "108",
  "ios": "16",
  "safari": "16"
}

שימו לב ל-polyfills שמוזרקים על ידי core-js בפלט של ה-build:

The corejs3 polyfill added the following polyfills:
  es.iterator.constructor { "chrome":"108", "edge":"108", "firefox":"108", "ios":"16", "safari":"16" }
  es.iterator.filter { "chrome":"108", "edge":"108", "firefox":"108", "ios":"16", "safari":"16" }
  es.iterator.map { "chrome":"108", "edge":"108", "firefox":"108", "ios":"16", "safari":"16" }

הפלט הזה יכול להשתנות אם תשנו את יעד הבסיס. נניח שהאפליקציה שלכם צריכה לתמוך בקבוצה ישנה יותר של דפדפנים בגלל הסכם רמת שירות (SLA) מחמיר יותר. אם זה המצב אצלכם, סביר להניח שתבחרו ביעד שמרני יותר. בקובץ package.json, משנים את ההגדרות של Browserslist כך שישקפו את הפרטים הבאים:

"browserslist": "extends browserslist-config-baseline/2016"

הפעולה הזו בוחרת ב-Baseline 2016 כיעד, והיא תתורגם לשאילתת Browerslist. אחרי שמריצים מחדש את הבנייה, אפשר לראות את ההבדלים בפלט של כלי הפיתוח:

npm run build

קודם כל, שימו לב לשינוי בגודל הקובץ של JavaScript ו-CSS של הפרויקט בנתוני הסטטיסטיקה של ה-bundler:

assets by status 237 KiB [emitted]
  asset js/home.b228612d.js 232 KiB [emitted] [immutable] [minimized] (name: home) 2 related assets
  asset css/home.0c3e4fd7.css 3.91 KiB [emitted] [immutable] (name: home) 1 related asset
  asset index.html 564 bytes [emitted]

אפשר לראות שגודל חבילת ה-JavaScript גדל בכמעט 30KiB. קובץ ה-CSS של הפרויקט גדול רק במעט, כי autoprefixer הוסיף עוד קידומות ספקים על סמך היעד הבסיסי משנת 2016. שימו לב גם לשינוי בשאילתת Browserslist:

Using targets: {
  "chrome": "53",
  "edge": "14",
  "firefox": "49",
  "ios": "10",
  "safari": "10"
}

בהשוואה ליעד הבסיסי שזמין באופן נרחב, גרסאות הדפדפן האלה הן מוקדמות בהרבה – מוקדמות מספיק כדי שגרסת Edge שהוגדרה כיעד במקרה הזה תהיה גרסה שלפני Chromium.

גם ה-polyfills שמוזרקים על ידי core-js ישתנו, וזה הרבה יותר מאשר אם נבחר היעד Baseline Widely available:

The corejs3 polyfill added the following polyfills:
  es.array.filter { "edge":"14" }
  es.iterator.constructor { "chrome":"53", "edge":"14", "firefox":"49", "ios":"10", "safari":"10" }
  es.iterator.filter { "chrome":"53", "edge":"14", "firefox":"49", "ios":"10", "safari":"10" }
  es.object.to-string { "edge":"14", "firefox":"49" }
  es.array.includes { "firefox":"49" }
  es.string.includes { "edge":"14" }
  es.array.map { "firefox":"49" }
  es.iterator.map { "chrome":"53", "edge":"14", "firefox":"49", "ios":"10", "safari":"10" }
  es.symbol { "edge":"14", "firefox":"49" }
  es.symbol.description { "chrome":"53", "edge":"14", "firefox":"49", "ios":"10", "safari":"10" }
  es.array.iterator { "chrome":"53", "edge":"14", "firefox":"49" }
  web.dom-collections.iterator { "chrome":"53", "edge":"14", "firefox":"49", "ios":"10", "safari":"10" }
  es.array.push { "chrome":"53", "edge":"14", "firefox":"49", "ios":"10", "safari":"10" }
  es.regexp.to-string { "edge":"14" }
  es.array.from { "edge":"14", "firefox":"49" }
  es.regexp.exec { "chrome":"53", "edge":"14", "firefox":"49", "ios":"10", "safari":"10" }
  es.regexp.test { "edge":"14" }
  es.error.cause { "chrome":"53", "edge":"14", "firefox":"49", "ios":"10", "safari":"10" }

הנקודה החשובה כאן היא שיעד הבסיס יכול להשפיע באופן משמעותי על האופן שבו האפליקציה משתנה על ידי שרשרת הכלים של הפרויקט. האפליקציה בדוגמה הזו היא בסיסית מאוד, ואין בה הרבה תכונות מתקדמות של חוויית פיתוח, לא ב-React ולא באפליקציה עצמה. באפליקציות מורכבות בהרבה, התוצאות יכולות להיות שונות מאוד – יכול להיות שיהיו אפילו יותר polyfills, טרנספורמציות ומקורות אחרים של קוד נוסף כדי להתאים ליעד הבסיסי שתבחרו.

5. טירגוט דפדפנים במורד הזרם באמצעות browserslist-config-baseline

לסיכום, קבוצת הדפדפנים העיקרית שאליה מכוונת Baseline כוללת את הדפדפנים הבאים:

  • Chrome
  • ‫Chrome ב-Android
  • Firefox
  • ‫Firefox ב-Android
  • Edge
  • ‫Safari ב-macOS
  • ‫Safari ב-iOS

עם זאת, אפשר לטרגט דפדפנים שנקראים 'דפדפנים במורד הזרם'. הדפדפנים האלה הם דפדפנים שהמנועים שלהם נגזרים מדפדפן שנכלל בקבוצת הדפדפנים המרכזיים – לרוב Chromium. הדפדפנים האלה כוללים את Opera,‏ Samsung Internet ועוד. אפשר להגדיר את browserslist-config-baseline כך שיהיה טירגוט שלהם בקובץ package.json באופן הבא:

"browserslist": "extends browserslist-config-baseline/with-downstream"

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

npm start

אחר כך מציינים את השינוי בשאילתת Browserslist:

Using targets: {
  "android": "108",
  "chrome": "108",
  "edge": "108",
  "firefox": "108",
  "ios": "16",
  "opera": "94",
  "opera_mobile": "80",
  "safari": "16",
  "samsung": "21"
}

אפשר גם לטרגט דפדפנים במורד הזרם לפי שנה. לדוגמה:

"browserslist": "extends browserslist-config-baseline/with-downstream/2016"

בהגדרה הזו, השאילתה של Browserslist תשתנה בהתאם:

Using targets: {
  "android": "53",
  "chrome": "53",
  "edge": "14",
  "firefox": "49",
  "ios": "10",
  "opera": "40",
  "opera_mobile": "80",
  "safari": "10",
  "samsung": "6.2"
}

6. כלי Linter וכלים אחרים

browserslist-config-baseline הוא כלי נוח לצרור ולחלקים אחרים בשרשרת הכלים, אבל יש ערך גם בכלים אחרים, כמו כלי לינטר (linter) שאימצו יעדי בסיס כחלק מההגדרה שלהם.

דוגמה טובה לתמיכה של כלי Linter ב-Baseline היא ESLint, שבמסגרת בדיקת ה-CSS שלו מספק כלל use-baseline באמצעות @eslint/css שמאפשר לכם לטרגט את Baseline Newly,‏ Baseline Widely available או Baseline years. יש גם כלל דומה בחבילה של קהילת @html-eslint/eslint-plugin שמאפשר לעשות את אותו הדבר לתכונות HTML בקובץ eslint.config.js:

export default [
  /* Omitted JS linting rules ... */
  // Lint CSS files for Baseline:
  {
    files: ["**/*.css"],
    plugins: {
      css
    },
    language: "css/css",
    rules: {
      "css/no-duplicate-imports": "error",
      // Lint CSS files to make sure they are using
      // only Baseline Widely available features:
      "css/use-baseline": ["warn", {
        available: "widely"
      }]
    },
  },
  // Lint HTML and JSX files for Baseline:
  {
    files: ["**/*.html"],
    ...html.configs["flat/recommended"],
    rules: {
      // Lint HTML files to make sure they are using
      // only Baseline Widely available features:
      "@html-eslint/use-baseline": ["warn", {
        available: "widely"
      }]
    }
  }
];

יש כמה דברים שחשוב לשים לב אליהם בהגדרה הזו:

  1. גם חבילות ה-linting של HTML וגם חבילות ה-linting של CSS משתמשות בכלל use-baseline, והן מוגדרות כזמינות באופן נרחב באמצעות אפשרות ההגדרה available: "widely".
  2. בשני חבילות ה-linting, רמת היומן להפרות של ה-linter מוגדרת ל-"warn". אפשר להגדיר את הערך "error" כדי להפסיק את התהליך עם קוד שגיאה, וכך למנוע את הבנייה.

יכול להיות שראיתם את הפלט של ה-linter כשמריצים את npm run build, אבל כדי לראות רק את הפלט של ה-linter, אפשר להריץ את הפקודה הבאה:

npm run lint

בפלט שיוצג יודגשו כמה אזהרות לגבי ה-CSS של הפרויקט:

/var/www/baseline-demos/tooling/webpack-browserslist-config-baseline/src/css/normalize.css
  222:3  warning  Property 'outline' is not a widely available baseline feature  css/use-baseline

/var/www/baseline-demos/tooling/webpack-browserslist-config-baseline/src/css/styles.css
  62:3   warning  Property 'outline' is not a widely available baseline feature                                css/use-baseline
  81:23  warning  Value 'subgrid' of property 'grid-template-rows' is not a widely available baseline feature  css/use-baseline

7. סיכום

כמו שאפשר לראות, כדי להשתמש ב-browserslist-config-baseline בפרויקט צריך להבין קצת בכלי בנייה וב-Browserslist, אבל אפשר להוסיף אותו לפרויקטים עם קצת עבודה. היתרון העיקרי בשימוש ב-Baseline הוא שלא צריך יותר לחשוב על הדפדפנים שאתם תומכים בהם במונחים של מספרי גרסאות, אלא על יעד Baseline שמבצע את העבודה הקשה בשבילכם.

בנוסף, יש גרסה של ההדגמה הזו שפועלת ב-Rollup, ואפשר להשתמש בהדגמה הזו כדי לבצע את רוב השלבים ב-Codelab הזה.

תמיכה ב-Baseline מתחילה להופיע גם בכלי חבילות אחרים. לדוגמה, Vite, שמשתמש ב-Rollup מתחת לפני השטח, מכוון עכשיו לדפדפנים בסיסיים שזמינים באופן נרחב כברירת מחדל החל מגרסה 7.

לא משנה איך תבחרו לעשות את זה, אם תשתמשו ב-browserslist-config-baseline בשרשרת הכלים של הפרויקט שלכם – ותבחרו יעד של Baseline שמתאים לכם – תוכלו לטרגט דפדפנים בצורה פשוטה ואמינה יותר.