Génération d'icônes multi-plateformes multi-marques avec Sketch et un script Node.js - Partie # 1



TL; DR


À l'aide d'un script de construction personnalisé dans Node JS, il est possible de manipuler une série de fichiers Sketch, puis, à l'aide d'un outil Sketch interne, d'exporter automatiquement leurs actifs, pour générer plusieurs bibliothèques d'icônes, pour plusieurs plates-formes et différentes marques, qui prennent en charge la dynamique colorisation des actifs via des jetons de conception, et également test AB des actifs via la convention de dénomination. Peasy facile :)


Eh bien, en fait, ce n'est pas si simple, mais cela peut certainement être fait. Ce message est une explication détaillée de la façon dont nous l'avons fait et de ce que nous avons découvert en cours de route.

Le problème que nous essayions de résoudre


Chez Badoo, nous construisons une application de rencontres. En fait, plusieurs applications de rencontres. Pour plusieurs plateformes ( iOS , Android , Web mobile, Web de bureau ), à travers plusieurs équipes .

Nous utilisons des centaines d'icônes dans nos applications. Certains d'entre eux sont les mêmes dans différentes applications, certains sont très spécifiques aux marques que les applications reflètent. Les icônes évoluent en permanence, en phase avec l'évolution du design. Parfois, de nouvelles icônes sont ajoutées, tandis que d'autres sont mises à jour et d'autres encore supprimées (bien qu'elles restent souvent dans la base de code).

Notre équipe de conception conçoit et entretient les icônes, et jusqu'à présent, la seule façon pour elles de fournir les actifs appropriés aux différentes équipes, plates-formes et applications, était de les envoyer par e-mail, chat ou dropbox. Non seulement cela prend du temps, mais c'est presque toujours sujet aux erreurs. En fait, nous avons constaté que des erreurs se produisaient à chaque fois (nous sommes humains!): Les icônes seraient mises à jour sur une plate-forme mais pas sur une autre; ou les icônes seraient manquantes ou au format ou à la taille incorrects. Donc, il y avait un va-et-vient constant entre les concepteurs et les développeurs; les développeurs exportaient les icônes directement à partir du fichier Sketch, et les icônes étaient ajoutées à la base de code, mais sans vérifier si des icônes similaires existaient déjà (et étaient disponibles pour une réutilisation). Je suis sûr que vous savez de quoi je parle.

Chez Badoo, nous avons un système de conception, appelé Cosmos , et nous avons récemment introduit une bibliothèque de jetons de conception sur plusieurs plates-formes (Web mobile, Android et iOS) à la fois pour notre application principale et ses marques blanches. Essentiellement, nous sommes maintenant en mesure de communiquer les décisions de conception (comme la bordure d'un bouton, la couleur d'arrière-plan d'une page de fonctionnalité particulière, la taille de police de l'en-tête 1 ou la durée d'une animation pour une fenêtre contextuelle) à l'aide de valeurs de conception élémentaires, tous traités et livrés automatiquement à toutes les applications et à toutes les plates-formes consommant ces jetons de conception dans leurs applications.

La façon dont nous sommes maintenant en mesure de transformer une idée de design, comme par exemple un changement de couleur, en un vrai code en production, en quelques clics et presque jamais, a vraiment impressionné les chefs de produit et les designers.

Donc, leur prochaine question (et demande) était: pouvez-vous faire quelque chose de similaire pour les actifs? Et notre réponse a été: oui, nous le pouvons (probablement)!

C'était tout un acte de foi à l'époque, je dois l'admettre. Nous avions quelques idées sur la façon de le faire, mais nous ne savions pas du tout si c'était techniquement faisable, avec toutes les restrictions que nous appliquons. Nous avons convenu de commencer avec un projet MVP, mais à la fin, tout s'était si bien passé qu'il est devenu notre produit final, avec toutes les fonctionnalités nécessaires.

Les exigences


Les exigences du MVP étaient très claires: créer un pipeline pouvant prendre un fichier Sketch et exporter toutes les icônes incluses dans le fichier, dans différents formats, pour différentes plates-formes, chaque icône pouvant être utilisée dans les tests AB.

Cela est compliqué car, dans nos produits, une icône peut avoir de nombreuses couleurs et / ou formes différentes pour différentes marques / étiquettes blanches (bien que la base de code de l'application soit la même, ainsi que le nom de l'icône).

Regardez certaines des icônes utilisées dans nos applications et vous remarquerez que certaines sont identiques, certaines sont très similaires les unes aux autres mais pour quelques détails, tandis que d'autres sont assez différentes, tant dans leurs formes que dans leurs couleurs:


Une comparaison de l'icône pour les différentes marques

Maintenant, les couleurs utilisées dans les icônes ne sont pas seulement des couleurs unies, mais correspondent aux couleurs exactes indiquées dans les jetons de conception pour cette marque et ses caractéristiques spécifiques:


Comparaison des couleurs entre différentes marques. Les valeurs de couleur sont spécifiées en tant que jetons de conception.

Ainsi, notre objectif avec ce nouveau pipeline d'actifs n'était pas seulement d'automatiser le processus de génération et de livraison des icônes, pour toutes les différentes plateformes et marques, mais plutôt de pouvoir colorer "dynamiquement" les icônes en fonction de la marque / blanc -label.

Sketch et sketchtool


Sketch est le principal outil de conception utilisé par notre équipe de conception. Même si nous avons envisagé d'autres options ( Figma , principalement), nous savions que Sketch était le format des fichiers source que nous allions utiliser pour ce projet (simplement parce que c'est l'outil que nos concepteurs maîtrisent le mieux, et c'est le format des fichiers dans lesquels les icônes / ressources existantes sont utilisées, entre autres raisons).

Le fait est qu'au début du projet, nous n'étions même pas sûrs des formats finaux attendus par les plateformes. Dans notre esprit, le processus allait être assez basique comme celui-ci: exporter les icônes au format SVG à partir du fichier Sketch puis consommer les fichiers SVG dans Mobile Web et Android, et pour iOS trouver une bibliothèque qui peut convertir des SVG en PDF. Et c'est tout. C'était le plan lorsque nous avons commencé, bien que nous ne sachions pas si cela fonctionnerait, ni à propos des inconnues inconnues que nous pourrions rencontrer (d'où le MVP pour voir si c'était même faisable et, si oui, combien d'efforts cela pourrait impliquer. )

Je ne sais pas si vous avez déjà travaillé avec des "convertisseurs PDF" mais d'après mon expérience, ils sont généralement pénibles. Ils font "presque" le travail, mais jamais au 100% dont vous avez vraiment besoin. Donc, au fond de mon esprit, je sentais que nous empruntions un chemin dangereux.

Sketch a une façon d'exporter des actifs qui est à peu près parfaite, je n'ai jamais eu de problème avec ça (que ce soit SVG, PDF ou d'autres formats). Je voulais donc voir s'il y avait d'autres façons d'interagir avec Sketch, d'utiliser son moteur pour exporter des actifs directement via Sketch, peut-être de manière programmatique (je me demandais également si un plugin personnalisé pouvait être construit, bien que cela aurait signifié beaucoup de travail pour moi, pas seulement parce que je n'ai aucune expérience dans ce domaine!).

Je savais qu'en interne, Sketch n'est plus qu'un fichier zip (si vous renommez un fichier .sketch en .zip , double-cliquez pour le décompresser et ouvrez le dossier résultant, vous voyez une liste de fichiers JSON et un bitmap utilisé comme aperçu):


Structure interne d'un fichier d'esquisse, une fois non compressé

J'ai donc commencé à explorer les différents fichiers JSON, en essayant de comprendre les connexions et les dépendances entre eux.

J'ai réalisé qu'en quelque sorte, malgré les fichiers JSON profondément imbriqués (et assez volumineux!), Les relations entre les différentes entités à l'intérieur de leurs objets ne sont pas trop compliquées: vous avez des pages, des plans de travail et des calques; à l'intérieur des couches, vous avez les chemins, et vous pouvez avoir des styles partagés entre eux; chacune de ces entités a un ID unique qui est utilisé pour conserver une référence entre les différents fichiers; et tous les objets "page" sont enregistrés dans des fichiers JSON, stockés dans un sous-dossier appelé pages , avec l'ID de la page utilisé comme nom du fichier.

Une découverte importante que j'ai faite, au cours de cette exploration, a été que les noms des calques, des pages et des styles ne sont que des étiquettes et peuvent être modifiés à tout moment, sans compromettre le fonctionnement interne du fichier Sketch. Ce qui compte, c'est l'ID unique qui leur est attribué, et cela n'est jamais exposé à l'utilisateur final (bien qu'il puisse être lu et référencé dans les fichiers JSON). Voici un exemple de l'apparence de l'ID unique d'un style:

{ "_class": "sharedStyle", "do_objectID": "49BA4E98-8D63-435C-81D9-E2F6CDB63136", "name": "name-of/the-style", "value": {     "_class": "style",     "endMarkerType": 0,     "fills": [         {             "_class": "fill",             "isEnabled": true,             "color": {                 "_class": "color",                 "alpha": 1,                 "blue": 0.7176470588235294,                 "green": 0.4627450980392159,                 "red": 0             },             "fillType": 0,             "noiseIndex": 0,             "noiseIntensity": 0,             "patternFillType": 1,             "patternTileScale": 1         }     ],     "miterLimit": 10,     "startMarkerType": 0,     "windingRule": 1 } } 

Cela m'a donné une idée: que nous pourrions peut-être utiliser des conventions spécifiques sur les noms des plans de travail et des pages, pour déclarer une sorte de méta-informations sur les relations entre les différents actifs, et les utiliser par programme au moment de la construction.

Sketchtool


À ce stade, à la fin des explorations initiales, le plan était passé de «exportons les icônes en SVG puis convertissons-les» en «construisons un plugin qui, dans Sketch, nous permet d'exporter directement les icônes dans leur version finale format " . Mais même alors, le plan était encore très flou (et la faisabilité technique était encore incertaine).

C'est pendant que je regardais les plugins existants, en particulier leur code source, pour voir si et comment ils pouvaient interagir avec les API d'exportation Sketch, que je suis tombé sur un outil dont je n'avais jamais entendu parler auparavant: Sketchtool.

Sketchtool est un outil Sketch officiel (officiel comme dans: développé par Bohemian Coding), qui selon la documentation :
... est un utilitaire de ligne de commande fourni avec Sketch, qui vous permet d'effectuer certaines opérations avec des documents Sketch, comme les inspecter ou exporter des actifs. Il vous permet également de contrôler Sketch à partir de la ligne de commande pour effectuer certaines actions (comme exécuter des plugins, par exemple).

Accrochez-vous ... un utilitaire de ligne de commande pour effectuer des opérations telles que l' exportation d'actifs ? Juste ce que je cherchais! De plus, étant un outil officiel, il n'y aurait pas de problèmes de versions, d'obsolescence, de maintenance, etc.

J'ai commencé à l'examiner immédiatement et à lire la documentation, qui progressivement sur une seule page du site Web Sketch (je n'ai trouvé pratiquement aucune autre ressource ou page à ce sujet, il est donc compréhensible que je n'en ai jamais entendu parler ça)

Sketchtool est fourni directement avec Sketch, et vous pouvez le trouver dans Sketch à ce chemin: Sketch.app/Contents/Resources/sketchtool/

Lorsque vous le lancez dans votre CLI avec la commande:
$ /Applications/Sketch.app/Contents/Resources/sketchtool/bin/sketchtool

c'est la sortie que vous voyez sur votre terminal (je l'ai un peu simplifiée):

 Usage: sketchtool <command> [<args>] [--formats=<string>] [--use-id-for-name{=YES|NO}] [--export-page-as-fallback{=YES|NO}] [--serial{=YES|NO}] [--context=<string>] [--application=<path>] [--without-activating{=YES|NO}] [--item=<string>] [--items=<string>] [--safemode{=YES|NO} | --no-safemode | -S {<YES|NO>}] [--max-size=<float> | -m <float>] [--background=<string> | -g <string>] [--compression=<float> | -c <float>] [--new-instance{=YES|NO}] [--reveal{=YES|NO}] [--timeout=<float>] [--include-symbols{=YES|NO}] [--bounds=<rectangle>] [--outputJSON=<path>] [--filename=<string>] [--wait-for-exit{=YES|NO}] [--scales=<path>] [--overwriting{=YES|NO}] [--group-contents-only{=YES|NO}] [--trimmed{=YES|NO}] [--help] [--progressive{=YES|NO}] [--save-for-web{=YES|NO}] [--output=<path>] Commands: dump               Dump out the structure of a document as JSON. export artboards  Export one or more artboards export layers     Export one or more layers export pages      Export an area from one or more pages export preview    Export a preview image for a document export slices     Export one or more slices help              Show this help message. list artboards    List information on the document's artboards. list formats      List the supported export formats. list layers       List information on all of the document's layers. list pages        List information on the document's pages. list slices       List information on the document's slices. metadata          List the metadata for a document. run               Run a command from a plugin, inside Sketch. show              Show the location of the various sketch folders. See 'sketchtool help <command>' for more information on a specific command. 


Comme vous pouvez le voir, l'outil a quatre fonctions principales: lire / sauvegarder les métadonnées des fichiers internes JSON; pour lister les entités dans un fichier; exporter ces entités; et pour exécuter une commande exposée par un plugin. De plus, chaque commande dispose de nombreuses options . Dans le cas de la commande d'exportation, presque toutes les options que vous trouvez dans le panneau d'exportation sont également disponibles via la ligne de commande de Sketchtool:


Panneau "Exporter" dans Sketch, avec les options disponibles

Cela signifie que Sketch peut être utilisé directement comme "moteur" d'exportation via sketchtool , sans avoir besoin de convertisseurs externes (de SVG en PNG ou PDF, par exemple). Gros problème!

Un test rapide utilisant sketchtool et un simple fichier Sketch avec quelques icônes à l'intérieur, a confirmé toutes les suppositions initiales: en utilisant simplement cet outil simple, nous pouvons éviter à la fois d'utiliser des exportateurs tiers et de construire nos propres exportateurs personnalisés: Sketch fait tout!

Le ou les fichiers d'esquisse


Une fois que nous avons su que Sketch était l'outil que nous allions utiliser, à la fois pour stocker et exporter les icônes, il était temps de collecter les icônes utilisées dans nos applications dans un fichier Sketch.

Au départ, nous n'avions prévu de travailler qu'avec un ensemble limité d'icônes, celles du projet MVP, mais nous nous sommes vite rendu compte qu'il aurait été préférable de les collecter toutes en même temps, pour pouvoir détecter immédiatement les doublons, les incohérences, les omissions, etc.

Nos concepteurs ont fait un travail incroyable et en quelques jours seulement, une grande partie des ressources utilisées dans leurs fichiers Sketch a été collectée et organisée en un seul fichier. À ce stade, le fichier Sketch ressemblait à ceci:


Vue d'ensemble du fichier Sketch contenant les icônes utilisées dans notre application.

Dans le fichier, chaque icône a son propre plan de travail, nommé avec le nom souhaité de l'icône (qui sera ensuite utilisé par Sketch comme nom de fichier lors de l'exportation des actifs).

Tous les chemins sont convertis en contours et les chemins combinés (généralement sous forme d' union ou de soustraction ) sont aplatis en une seule forme. Cela garantit que les actifs générés conservent l'apparence visuelle parfaite qu'ils ont dans le fichier source et une compatibilité optimale avec les différentes plates-formes.



Exemple de la façon dont les icônes (et leurs calques) sont organisées dans le fichier Sketch d'actifs. Le fond rose clair appliqué aux plans de travail crée un contraste visuel avec les zones blanches.

Coloration dynamique des icônes avec des styles partagés (et des jetons de conception)


Une fois que nous avons rassemblé les icônes, l'étape suivante consistait à leur appliquer les bonnes couleurs. Ce que nous avons fait, c'est créer un ensemble de styles partagés prédéfinis dans Sketch , avec des noms qui correspondent à ceux des jetons de conception utilisés dans notre système de conception, puis les utiliser pour appliquer des couleurs aux icônes.

Voici comment un style est appliqué à un calque:


Calque dans Sketch avec un style prédéfini (couleur de remplissage).

Et voici comment les styles sont déclarés puis appliqués à un élément:


Comment nous avons décidé d'organiser les styles dans Sketch

La convention de dénomination est très importante ici. Les concepteurs peuvent organiser les styles dans n'importe quel sous-dossier, à condition que le nom du style lui-même corresponde au nom du jeton de conception correspondant pour cette couleur. C'est le cas, il peut donc être référencé par programme par le script de construction plus tard.

Pages et noms de plan de travail utilisés pour les tests AB



À ce stade, il était temps de comprendre comment s'assurer que les concepteurs seraient en mesure d'effectuer des tests AB sur les icônes. Encore une fois, nous avons finalement décidé de nous appuyer sur les conventions de nommage (grand fan de KISS ici).

Dans ce cas, nous avons utilisé les noms de page pour détecter quand un ensemble d'icônes était un test / expérience AB (en utilisant " XP_" comme préfixe) et les noms de plan de travail pour détecter à quel actif le test AB faisait référence, et ses différentes variantes ( entre crochets).


Comment la convention de dénomination sur les pages et les plans de travail est utilisée pour "déclarer" un test AB. Remarque: les icônes ne sont que des exemples créés spécialement à des fins de test, ce ne sont pas de vraies icônes utilisées dans un produit :)

Les noms utilisés pour les tests et les options ne sont pas des noms génériques: ils doivent correspondre aux identifiants de nom unique attribués aux expériences / options dans notre outil interne de partage d'utilisateurs. De cette façon, les actifs peuvent ensuite être correctement associés au bon groupe d'utilisateurs de test AB.

Plusieurs fichiers pour plusieurs marques


La dernière pièce du puzzle était: comment pouvons-nous prendre en charge différentes formes de la même icône, pour différentes marques?



C'était une exigence très importante pour les chefs de produit , et nous avions différentes options à utiliser. Au début, nous avons pensé utiliser différentes pages dans le même fichier Sketch, avec des noms de page différents pour chaque marque; mais nous nous sommes vite rendu compte que cela rendrait beaucoup plus complexe et plus difficile pour les concepteurs de synchroniser les icônes entre les différentes marques. Nous avons donc conclu que la solution consistait à avoir plusieurs fichiers: un fichier "commun" , où nous stockions toutes les icônes identiques pour les différentes marques, et des fichiers spécifiques à la marque pour les icônes qui remplaçaient les icônes "de base" dans le commun. fichier.



À ce stade, les fichiers Sketch étaient prêts. Nous étions prêts à commencer à écrire du code.

À suivre.

Source: https://habr.com/ru/post/fr441040/


All Articles