7 septembre 2022
Créer un package avec TSDX
4 minutes de lecture
Introduction
Dans le cadre d’un partage de nombreux composants entre différents applicatifs React, nous avons réalisé une bibliothèque de composants UI et haut niveau avec l’aide du package TSDX. De la documentation aux tests, découvrez les problèmes rencontrés et leurs solutions pour rendre accessible la création de package TypeScript au plus grand nombre.
Le package TSDX est maintenu par Jared Palmer, lead open source chez Vercel, et créateur du projet https://turborepo.org/, il apporte une attention particulière à la DX et les outils dans l'écosystème JavaScript et TypeScript. D'ailleurs la promesse de cet outil est de ne pas avoir besoin de configuration et de faire marcher un ensemble d'outils efficacement et de manière transparente.
Initialisation
Pour initialiser notre projet nous allons utiliser le template le plus complet avec React et Storybook.
npx tsdx create mylib
Cette commande va préparer un projet avec une base complète pour démarrer :
.github
contient les scripts pour l'intégration continue avec Github actions (lint, lancer les tests, vérifier le build...)example
est une application React minimaliste d'exemple utilisant le bundler Parcel.src
est le code de votre packagestories
contient les stories de Storybook pour faire des démos unitaires de vos composants et les documentertest
pour les tests Jest de votre code
Développement
Avec Storybook
Dans notre contexte de la création d'un SDK avec de nombreux composants d'UI en React, nous développons majoritairement avec Storybook (yarn storybook
).
La création d'un nouveau composant implique la création d'une story associée avec plusieurs cas d'utilisations via les templates de Storybook.
Exemple pour le composant Bouton
:
import React from 'react'
import { Meta, Story } from '@storybook/react'
import { Button, ButtonProps } from './'
const meta: Meta = {
title: 'Button',
component: Button,
argTypes: {
children: {
control: {
type: 'text',
},
},
},
parameters: {
controls: { expanded: true },
},
}
export default meta
const Template: Story<ButtonProps> = ({ ref, ...args }) => <Button {...args} />
export const SimpleButton = Template.bind({})
SimpleButton.args = {
children: 'Simple button',
}
export const IconButton = Template.bind({})
IconButton.args = {
iconOnly: true,
icon: 'cog',
children: <span className="u-hidden">Icon button</span>,
}
export const DisabledButton = Template.bind({})
DisabledButton.args = {
children: 'Simple button',
disabled: true,
}
Avec une application cliente
Il est parfois intéressant de développer les composants directement avec leur contexte d'utilisation finale.
Pour ce cas nous allons utiliser la commande link
de yarn.
Dans le répertoire de la lib avec yarn link
et dans le répertoire du projet avec yarn add mylib
.
Ces commandes vont inclure la dépendance avec un lien symbolique.
Il ne reste plus qu'à lancer les commandes de build des 2 projets (pour tsdx yarn start
).
Plusieurs versions de React peuvent se retrouver incluses par votre bundler, cela a été le cas pour webpack et il a été nécessaire de forcer les dépendances avec des alias pour éviter des soucis au runtime.
const path = require('path')
module.exports = {
//...
resolve: {
alias: {
react: path.resolve(__dirname, './node_modules/react'),
},
},
}
Tests
Pour les tests de composants visuels, l'ajout de storyshots permet d'automatiser des tests de snapshots jest de toutes les stories dans un seul fichier test/storybook.test.tsx
import initStoryshots from '@storybook/addon-storyshots'
import { render } from '@testing-library/react'
import '@testing-library/jest-dom'
initStoryshots({
renderer: render,
})
Pour les autres tests, l'API de Jest est très complète et permet de gérer l'ensemble des tests nécessaires pour votre package.
Documentation
Dans le contexte d'un UI kit, la documentation la plus importante est pour nous le Storybook, idéalement il peut être hébergé statiquement pour présenter aux développeurs ce qu'il est possible d'utiliser, via des cas concrets d'exemple et l'auto documentation des props.
Un fichier de README rappelant comment installer dans le projet, les commandes ou encore comment contribuer est recommandé.
Enfin nous avons mis en place plusieurs règles dans notre processus de développement et release :
- Conventional commits pour uniformiser le format des commits du projet
- Standard Version pour la montée en version et la génération automatique d'un CHANGELOG
Ces outils se retrouvent dans les scripts du package.json
, un yarn release
va automatiquement générer une nouvelle version mineure ou majeure selon l'historique des commits.
"scripts": {
"release": "standard-version",
"postrelease": "npm run release:tags && npm run release:github",
"release:tags": "git push --follow-tags origin master",
"release:github": "conventional-github-releaser -p angular"
Conclusion
L'outil TSDX a répondu à la plupart de nos attentes : démarrer un package avec des outils bien sélectionnés, un template de base complet et une documentation fournie.
Nous avons pu y ajouter facilement nos nouveaux comportements comme la compilation SASS ou encore notre processus de release. Enfin la plupart des soucis ou questionnements rencontrés avaient déjà été détaillés dans des issues Github ou noté dans la documentation de l'outil.