Catégories
Astuces et Design

style9: CSS-in-JS au moment de la construction | Astuces CSS

En avril de l'année dernière, Facebook a révélé sa grande nouvelle refonte. Un projet ambitieux, c'était la reconstruction d'un grand site avec une quantité massive d'utilisateurs. Pour ce faire, ils ont utilisé plusieurs technologies qu'ils ont créées et open-source, telles que React, GraphQL, Relay et une nouvelle bibliothèque CSS-in-JS appelée stylex.

Cette nouvelle bibliothèque est interne à Facebook, mais ils ont partagé suffisamment d'informations à son sujet pour rendre possible une implémentation open source, style9.

Pourquoi une autre bibliothèque CIJ?

Il existe déjà de nombreuses bibliothèques CSS-in-JS (CIJ), il n'est donc pas évident de savoir pourquoi une autre est nécessaire. style9 présente les mêmes avantages que toutes les autres solutions CIJ, tels qu'articulés par Christopher Chedeau, y compris les sélecteurs de portée, l'élimination du code mort, la résolution déterministe et la possibilité de partager des valeurs entre CSS et JavaScript.

Il y a cependant quelques éléments qui rendent style9 unique.

Durée d'exécution minimale

Bien que les styles soient définis en JavaScript, ils sont extraits par le compilateur dans un fichier CSS normal. Cela signifie qu'aucun style n'est fourni dans votre fichier JavaScript final. Les seules choses qui restent sont les noms de classe finaux, que le runtime minimal appliquera conditionnellement, comme vous le feriez normalement. Cela se traduit par des ensembles de code plus petits, une réduction de l'utilisation de la mémoire et un rendu plus rapide.

Étant donné que les valeurs sont extraites au moment de la compilation, les valeurs réellement dynamiques ne peuvent pas être utilisées. Celles-ci ne sont heureusement pas très courantes et comme elles sont uniques, ne souffrez pas d’être définies en ligne. L’application conditionnelle de styles est plus courante, ce qui est bien entendu pris en charge. Il en va de même pour les constantes locales et les expressions mathématiques, grâce à Babel path.evaluate.

Sortie atomique

En raison du fonctionnement de style9, chaque déclaration de propriété peut être transformée en sa propre classe avec une seule propriété. Ainsi, par exemple, si nous utilisons opacity: 0 à plusieurs endroits de notre code, il n'existera qu'une seule fois dans le CSS généré. L'avantage de ceci est que le fichier CSS grandit avec le nombre de déclarations uniques, pas avec le montant total des déclarations. Étant donné que la plupart des propriétés sont utilisées plusieurs fois, cela peut conduire à des fichiers CSS considérablement plus petits. Par exemple, l'ancienne page d'accueil de Facebook utilisait 413 Ko de CSS gzippé. La refonte utilise 74 Ko pour tout pages. Encore une fois, une taille de fichier plus petite conduit à de meilleures performances.

Diapositive de Construire le nouveau Facebook avec React et Relay par Frank Yan, à 13:23 montrant l'échelle logarithmique du CSS atomique.

Certains peuvent se plaindre de cela, du fait que les noms de classes générés ne sont pas sémantiques, qu'ils sont opaques et ignorent la cascade. C'est vrai. Nous traitons CSS comme une cible de compilation. Mais pour une bonne raison. En remettant en question les meilleures pratiques précédemment supposées, nous pouvons améliorer l'expérience utilisateur et développeur.

De plus, style9 possède de nombreuses autres fonctionnalités intéressantes, notamment: des styles typés utilisant TypeScript, l'élimination des styles inutilisés, la possibilité d'utiliser des variables JavaScript et la prise en charge des requêtes multimédias, des pseudo-sélecteurs et des images clés.

Voici comment l'utiliser

Tout d'abord, installez-le comme d'habitude:

npm install style9

style9 a des plugins pour Rollup, Webpack, Gatsby et Next.js, qui sont tous basés sur un plugin Babel. Des instructions sur la façon de les utiliser sont disponibles dans le référentiel. Ici, nous allons utiliser le plugin webpack.

const Style9Plugin = require('style9/webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  module: {
    rules: (
      // This will transform the style9 calls
      {
        test: /.(tsx|ts|js|mjs|jsx)$/,
        use: Style9Plugin.loader
      },
      // This is part of the normal Webpack CSS extraction
      {
        test: /.css$/i,
        use: (MiniCssExtractPlugin.loader, 'css-loader')
      }
    )
  },
  plugins: (
    // This will sort and remove duplicate declarations in the final CSS file
    new Style9Plugin(),
    // This is part of the normal Webpack CSS extraction
    new MiniCssExtractPlugin()
  )
};

Définition des styles

La syntaxe de création de styles ressemble étroitement aux autres bibliothèques. Nous commençons par appeler style9.create avec des objets de styles:

import style9 from 'style9';

const styles = style9.create({
  button: {
    padding: 0,
    color: 'rebeccapurple'
  },
  padding: {
    padding: 12
  },
  icon: {
    width: 24,
    height: 24
  }
});

Parce que toutes les déclarations aboutiront à des classes atomiques, des raccourcis tels que flex: 1 et background: blue ne fonctionnera pas, car ils définissent plusieurs propriétés. Les propriétés qui peuvent être développées, telles que padding, margin, overflow, etc. seront automatiquement convertis en leurs variantes longues. Si vous utilisez TypeScript, vous obtiendrez une erreur lors de l'utilisation de propriétés non prises en charge.

Résolution des styles

Pour générer un nom de classe, nous pouvons maintenant appeler la fonction retournée par style9.create. Il accepte comme arguments les clés des styles que nous voulons utiliser:

const className = styles('button');

La fonction fonctionne de manière à ce que les styles de droite aient la priorité et soient fusionnés avec les styles de gauche, comme Object.assign. Ce qui suit donnerait un élément avec un rembourrage de 12px et avec rebeccapurple texte.

const className = styles('button', 'padding');

Nous pouvons appliquer conditionnellement des styles en utilisant l'un des formats suivants:

// logical AND
styles('button', hasPadding && 'padding');
// ternary
styles('button', isGreen ? 'green' : 'red');
// object of booleans
styles({
  button: true,
  green: isGreen,
  padding: hasPadding
});

Ces appels de fonction seront supprimés lors de la compilation et remplacés par une concaténation directe de chaînes. La première ligne du code ci-dessus sera remplacée par quelque chose comme 'c1r9f2e5 ' + hasPadding ? 'cu2kwdz ' : ''. Aucun runtime n'est laissé pour compte.

Combiner les styles

Nous pouvons étendre un objet de style en y accédant avec un nom de propriété et en le passant à style9.

const styles = style9.create({ blue: { color: 'blue; } });
const otherStyles = style9.create({ red: { color: 'red; } });

// will be red
const className = style9(styles.blue, otherStyles.red);

Tout comme pour l'appel de fonction, les styles de droite sont prioritaires. Dans ce cas, cependant, le nom de la classe ne peut pas être résolu statiquement. Au lieu de cela, les valeurs de propriété seront remplacées par des classes et seront jointes au moment de l'exécution. Les propriétés sont ajoutées au fichier CSS comme avant.

Résumé

Les avantages de CSS-in-JS sont bien réels. Cela dit, nous imposons un coût de performance lors de l'incorporation de styles dans notre code. En extrayant les valeurs lors de la construction, nous pouvons avoir le meilleur des deux mondes. Nous bénéficions de la co-localisation de nos styles avec notre balisage et de la possibilité d'utiliser l'infrastructure JavaScript existante, tout en étant en mesure de générer des feuilles de style optimales.

Si style9 vous semble intéressant, jetez un œil au repo et essayez-le. Et si vous avez des questions, n'hésitez pas à ouvrir un problème ou à nous contacter.

Remerciements

Merci à Giuseppe Gurgone pour son travail sur la feuille de style et le dss, Nicolas Gallagher pour react-native-web, Satyajit Sahoo et tout le monde chez Callstack pour linaria, Christopher Chedeau, Sebastian McKenzie, Frank Yan, Ashley Watkins, Naman Goel, et tout le monde qui a travaillé sur stylex chez Facebook pour avoir eu la gentillesse de partager ses leçons publiquement. Et quelqu'un d'autre que j'ai manqué.

Liens

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *