Utiliser Baseline dans votre projet

1. Introduction

Baseline est une initiative qui vise à communiquer plus clairement sur les fonctionnalités Web interopérables et sûres à utiliser aujourd'hui. Grâce aux avancées de l'outil Baseline, vous pouvez désormais l'utiliser directement dans vos projets en tant que requête Browserslist. Votre chaîne d'outils peut ainsi modifier le résultat du code en fonction de la cible Baseline que vous choisissez.

Dans cet atelier de programmation, vous apprendrez à utiliser Baseline dans un exemple de projet et à le configurer pour sélectionner une cible Baseline spécifique. Vous pourrez également observer comment la sortie de la chaîne d'outils du projet change en fonction de la cible de référence que vous avez sélectionnée.

2. Configurer la démo sur votre machine locale

Tout d'abord, accédez à l'application de terminal de votre choix, clonez le dépôt de démonstration, puis accédez au répertoire du projet :

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

À ce stade, la démo aura déjà intégré Baseline, mais vous devrez extraire un commit qui vous permettra de repartir de zéro :

git checkout 94f12e34

Une fois le dépôt cloné, la démo peut être lancée. Ce projet utilise nvm pour gérer le versionnage de Node. Si vous disposez d'une version relativement récente de Node installée globalement, vous n'avez probablement pas besoin d'effectuer cette étape. Toutefois, si vous utilisez nvm, exécutez les commandes suivantes :

nvm install
nvm use

Ensuite, installez les packages du projet :

npm install

Si vous souhaitez voir la démo, exécutez la commande suivante :

npm start

Accédez ensuite à http://localhost:8080. La démo elle-même est une liste de cartes filtrables à l'aide d'un champ de formulaire en haut de la page. L'application elle-même utilise un mélange de fonctionnalités ayant atteint un seuil de référence.

Lorsque vous avez terminé la démonstration, accédez à votre terminal et appuyez sur Ctrl+C pour arrêter l'exécution de la démonstration à tout moment.

3. Intégrer Baseline au projet

Cette démo ne spécifie pas de configuration Browserslist au début. Browserslist est une syntaxe de requête compacte qui indique aux chaînes d'outils les versions minimales des navigateurs qui doivent être prises en charge. Par exemple, la requête last 3 years spécifie un large éventail de cibles. Dans cette démo, nous allons utiliser un package npm nommé browserslist-config-baseline pour spécifier une requête Browserslist qui correspond aux cibles de référence que vous pouvez utiliser dans votre chaîne d'outils.

Pour commencer, installez browserslist-config-baseline comme suit :

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

Une fois installé, ce package vous permet de spécifier une requête Browserslist extends dans votre projet, qui est résolue en une liste de navigateurs de référence. Ces cibles de référence peuvent être les suivantes :

  • Les cibles mobiles, qui sont mises à jour au fil du temps à mesure que de nouveaux navigateurs sont publiés :
    • Baseline Newly available, qui aligne les fonctionnalités interopérables implémentées dans l'ensemble des navigateurs principaux à tout moment entre aujourd'hui et il y a 30 mois.
    • Baseline Widely available, qui inclut des fonctionnalités interopérables implémentées dans l'ensemble des navigateurs principaux depuis 30 mois ou plus.
  • Les cibles fixes, qui représentent les versions de navigateur à un moment précis. Elles sont exprimées en années, de 2016 à l'année en cours.

Pour commencer, nous allons utiliser browserslist-config-baseline pour sélectionner la cible "Baseline Widely available" (Baseline largement disponible) pour le projet. Pour ce faire, ouvrez package.json et ajoutez le code suivant :

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

4. Observer les modifications apportées au code en sélectionnant différentes cibles de référence

Vous venez de sélectionner "Baseline Widely available" (Ligne de base largement disponible) comme cible pour le projet de démonstration. Ensuite, vous devez créer le projet :

npm run build

La sortie est très détaillée, car l'option debug pour @babel/preset-env est spécifiée comme true dans le babel.config.js du projet. Tout d'abord, notez la taille des fichiers CSS et JavaScript dans les statistiques du 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]

Notez que le bundle JavaScript est de 208 Kio et que le CSS est de 3, 64 Kio. Ce projet utilise core-js pour les polyfills JavaScript et autoprefixer pour appliquer des préfixes spécifiques au fournisseur pour les propriétés CSS qui ne sont pas encore entièrement interopérables. core-js et autoprefixer sont tous deux affectés par browserslist-config-baseline.

Un autre élément de la sortie à prendre en compte est la façon dont votre requête Browserslist pour Baseline Widely available est traduite en requête Browserslist. Dans votre projet, cela se présentera comme suit :

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

Notez les polyfills injectés par core-js dans le résultat de la compilation :

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" }

Ce résultat peut changer si vous modifiez votre cible de référence. Supposons que votre application doive être compatible avec un ensemble de navigateurs beaucoup plus anciens en raison d'un SLA plus strict. Si c'est votre cas, vous choisirez probablement une cible plus conservatrice. Dans votre fichier package.json, modifiez la configuration de Browserslist pour qu'elle reflète ce qui suit :

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

Cela sélectionne "Baseline 2016" comme cible et sera traduit en requête Browserslist. Vous pouvez noter les différences dans la sortie de la chaîne d'outils après avoir réexécuté la compilation :

npm run build

Tout d'abord, notez la modification de la taille des fichiers JavaScript et CSS du projet dans les statistiques du 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]

Vous remarquerez que la taille du bundle JavaScript a augmenté de près de 30 Kio. Le CSS du projet n'est que légèrement plus volumineux, car autoprefixer ajoute davantage de préfixes de fournisseur en fonction de la cible de référence de 2016. Notez également la modification apportée à la requête Browserslist :

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

Par rapport à la cible de référence largement disponible, ces versions de navigateur sont beaucoup plus anciennes. La version d'Edge ciblée dans ce cas est antérieure à Chromium.

Les polyfills injectés par core-js changeront également, ce qui est beaucoup plus que lorsque "Baseline Widely available" (Référence largement disponible) était sélectionné comme cible :

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" }

Le point à retenir ici est que votre cible de référence peut avoir un impact significatif sur la façon dont votre application est transformée par la chaîne d'outils de votre projet. L'application de cet exemple est très basique et ne comporte pas beaucoup de fonctionnalités de pointe pour les développeurs, que ce soit dans React ou dans l'application elle-même. Pour les applications beaucoup plus complexes, vous pouvez vous attendre à des résultats très différents, peut-être même plus en termes de polyfills, de transformations et d'autres sources de code supplémentaire pour se conformer à la cible de référence que vous choisissez.

5. Cibler les navigateurs en aval avec <0x0A>browserslist-config-baseline

Pour rappel, l'ensemble de navigateurs de base ciblé par Baseline inclut les navigateurs suivants :

  • Chrome
  • Chrome pour Android
  • Firefox
  • Firefox sur Android
  • Edge
  • Safari sur macOS
  • Safari sur iOS

Toutefois, vous pouvez cibler ce que l'on appelle les "navigateurs en aval". Il s'agit des navigateurs dont les moteurs sont dérivés d'un navigateur de l'ensemble de navigateurs principaux, le plus souvent Chromium. Il peut s'agir de navigateurs tels qu'Opera, Samsung Internet, etc. Vous pouvez configurer browserslist-config-baseline pour les cibler dans votre fichier package.json comme suit :

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

Cela cible les navigateurs en aval conformément à la cible "Baseline Widely available" (Baseline largement disponible). Pour voir comment cela se traduit en requête Browserslist, recompilez le projet :

npm start

Notez ensuite la modification apportée à la requête Browserslist :

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

Vous pouvez également cibler les navigateurs en aval par année. Exemple :

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

Avec cette configuration, votre requête Browserslist changera en conséquence :

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

6. Linters et autres outils

browserslist-config-baseline est un outil pratique pour les bundlers et d'autres parties de votre chaîne d'outils, mais d'autres outils sont également utiles, tels que les linters qui ont adopté les cibles de référence dans leur configuration.

ESLint est un bon exemple de linter compatible avec Baseline. Il fournit une règle use-baseline dans son linting CSS à l'aide de @eslint/css, qui vous permet de cibler les fonctionnalités Baseline "Nouvellement disponibles", "Largement disponibles" ou "Années Baseline". Il existe également une règle similaire dans le package @html-eslint/eslint-plugin de la communauté qui vous permet de faire de même pour les fonctionnalités HTML de votre fichier 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"
      }]
    }
  }
];

Voici quelques points à noter dans cette configuration :

  1. Les packages de linting HTML et CSS utilisent une règle use-baseline, qui est définie sur "Largement disponible" à l'aide de l'option de configuration available: "widely".
  2. Pour les deux packages de linting, le niveau de journalisation des violations du linter est défini sur "warn". Cette valeur peut être définie sur "error" pour abandonner avec un code d'erreur afin d'empêcher la compilation.

Vous avez peut-être déjà vu la sortie du linter lorsque vous avez exécuté npm run build, mais pour voir la sortie du linter seule, vous pouvez exécuter la commande suivante :

npm run lint

Le résultat affiché met en évidence plusieurs avertissements dans le CSS du projet :

/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. Conclusion

Comme vous pouvez le voir, l'utilisation de browserslist-config-baseline dans votre projet nécessite une certaine compréhension des outils de compilation sous-jacents et de Browserslist, mais l'action de le placer dans vos projets devrait être possible avec un peu de travail. L'avantage principal de l'utilisation de Baseline est que vous n'avez plus besoin de réfléchir aux navigateurs que vous prenez en charge en termes de numéros de version, mais plutôt à une cible Baseline qui fait le gros du travail pour vous.

Il existe également une version de cette démo qui s'exécute sur Rollup. Vous pouvez également suivre cet atelier de programmation en grande partie à l'aide de cette démo.

La prise en charge de référence commence également à apparaître dans d'autres outils de regroupement. Vite, par exemple, qui utilise Rollup en coulisses, cible désormais les navigateurs Baseline largement disponibles par défaut depuis la version 7.

Quelle que soit la méthode que vous choisissez, l'introduction de browserslist-config-baseline dans la chaîne d'outils de votre projet et la sélection d'une cible de référence qui vous convient vous permettent de cibler les navigateurs de manière plus simple et plus fiable.