Vincent Barrault

Faire une bibliothèque React avec Typescript et Rollup

Faire une bibliothèque React avec Typescript et Rollup

Table des matières

Contexte

Souvent, quand on a plusieurs projets au sein d'une même entreprise, on ne veut pas avoir à recopier les mêmes composants encore et encore lorsqu'il s'agit de choses basiques comme des boutons, des élements de formulaires, etc...

Je vais donc m'atteler à l'execice de créer une bibliothèque de composants React.

Pour cela, je vais utiliser Rollup, que j'ai déjà utilisé dans le passé pour faire un script IIFE

Création du nouveau projet

Comme la dernière fois, je commence par créer le projet et par installer les dépendances dont j'aurais besoin par la suite.

mkdir hello-react-rollup
cd hello-react-rollup/
yarn init
yarn add -D rollup rollup-plugin-typescript2 tslib typescript react react-dom

Je modifie ensuite le fichier package.json pour y ajouter 3 points d'entrée:

Je rajoute aussi le script build pour exécuter la compilation de sources plus facilement.

Enfin, je rajoute des peerDependencies, pour spécifier au projet qui va installer cette bibliothèque d'avoir une version identique de react et de react-dom

./package.json
{
    "name": "hello-react-rollup",
    "version": "1.0.0",
    "main": "dist/index.js",
    "module": "dist/index.esm.js",
    "types": "dist/index.d.ts",
    "license": "MIT",
    "scripts": {
        "build": "rollup -c"
    },
    "peerDependencies": {
        "react": "^17.0.2",
        "react-dom": "^17.0.2"
    },
    "devDependencies": {
        "@types/react": "^17.0.20",
        "react": "^17.0.2",
        "rollup": "^2.56.3",
        "rollup-plugin-typescript2": "^0.30.0",
        "tslib": "^2.3.1",
        "typescript": "^4.4.3"
    }
}

Rollup

Pour que Rollup puisse fonctionner correctement, je dois créer un fichier de configuration rollup.config.js à la racine du projet.

./rollup.config.js
import typescript from 'rollup-plugin-typescript2';
import pkg from './package.json';

const input = 'src/index.ts';

const plugins = [
    typescript(),
];

const external = [
    ...Object.keys(pkg.dependencies || {}),
    ...Object.keys(pkg.peerDependencies || {}),
];

export default [
    {
        input,
        output: {
            file: pkg.module,
            format: 'esm',
            sourcemap: true,
        },
        plugins,
        external,
    },
    {
        input,
        output: {
            file: pkg.main,
            format: 'cjs',
            sourcemap: true,
        },
        plugins,
        external,
    },
];

Ce fichier de configuration possède 2 tâches de compilations, contrairement au fichier de configuration pour le script IIFE. Les deux formats générés seront tous les deux ajoutés au projet compilé, et serviront tous les deux dans des cas bien spécifiques.

Typescript

Pour que le plugin typescript puisse fonctionner, il faut aussi que je lui fournisse un fichier de configuration tsconfig.json:

./tsconfig.json
{
    "include": [
        "src/**/*"
    ],
    "compilerOptions": {
        "target": "es5",
        "module": "es2015",
        "moduleResolution": "node",
        "sourceMap": true,
        "declaration": true,
        "esModuleInterop": true,
        "forceConsistentCasingInFileNames": true,
        "strict": true,
        "skipLibCheck": true,
        "jsx": "react"
    }
}

Créer un composant

Pour avoir quelque chose à compiler, je vais créer un simple composant Hello qui retournera un template avec une chaîne de caractère Hello { name } !.

./src/components/Hello.tsx
import React from 'react'

export interface HelloProps {
    name: string;
}

export const Hello = ({ name }: HelloProps) => {
    return (
        <div>Hello { name } !</div>
    )
}

Sans oublier le point d'entrée de Rollup

./src/index.ts
export * from './components/Hello'

Et voilà, la bibliothèque React est prête à accueillir de nouveaux composants.