Skip to content

Storybook: Wiederverwendbare Komponenten dokumentieren

Tech Blog: Storybook - Documenting reusable components

Bei der Front-End-Entwicklung ist die Erstellung konsistenter und wiederverwendbarer User-Interface-Komponenten (UI) entscheidend für die Erstellung skalierbarer Anwendungen. Storybook hat sich als ein Tool herauskristallisiert, das es verschiedenen Teams ermöglicht, bei der Erstellung von UI-Komponenten effektiv zusammenzuarbeiten. In einem Szenario, in dem mehrere Entwicklerteams an derselben Front-End-Anwendung arbeiten, können doppelte Komponenten mit ähnlicher Funktionalität erstellt werden. Dies kann zu inkonsistentem Verhalten und einem schlechten Benutzererlebnis führen. Außerdem erhöhen sich die Wartungskosten der Anwendung aufgrund von Code-Duplikaten.

Um die Zusammenarbeit zwischen verschiedenen Teams zu verbessern und Code-Duplizierung zu reduzieren, verwenden wir bei Nitrobox Storybook. Es stellt sicher, dass die UI-Komponenten in der gesamten Anwendung konsistent sind, sowohl in Bezug auf den Stil als auch auf die Funktionalität. Beginnen wir damit, uns anzuschauen, was Storybook ist und was seine Hauptmerkmale sind.

Inhaltsverzeichnis

Was ist Storybook? 5 Key Feature

Storybook ist ein Open-Source-Tool für die isolierte Entwicklung und Dokumentation von UI-Komponenten. Es bietet eine Sandbox-Umgebung, in der Entwickler Komponenten unabhängig von der Hauptanwendung erstellen, testen und präsentieren können. Zu den wichtigsten Funktionen von Storybook gehören:

Key Feature 1: Component isolation

Storybook ermöglicht es Entwicklern, an UI-Komponenten zu arbeiten, ohne sich um Anwendungslogik, Backend-Dienste oder komplexe Abhängigkeiten kümmern zu müssen. Diese Isolierung macht es einfacher, sich auf Styling, Interaktivität und Verhalten zu konzentrieren.

Key Feature 2: Live component preview

Entwickler können Komponenten in verschiedenen Zuständen rendern und in Echtzeit mit ihnen interagieren, um sicherzustellen, dass sie in verschiedenen Anwendungsfällen wie erwartet funktionieren.

Key Feature 3: Docs & add-ons

Storybook bietet integrierte Dokumentationsfunktionen, mit denen Teams eine interaktive Komponentendokumentation erstellen können. Darüber hinaus erweitert sein umfangreiches Ökosystem von Add-ons die Funktionalität, wie z. B. Zugänglichkeitstests, Tests für responsives Design und UI-Tests.

Key Feature 4: Automated testing

Mit Integrationen wie Jest, Chromatic und React Testing Library ermöglicht Storybook automatisierte UI-Tests, um Regressionen aufzuspüren und die Konsistenz des Designs über verschiedene Umgebungen hinweg zu wahren.

Key Feature 5: Design & development collaboration

Designer, Entwickler und andere Beteiligte können nahtlos zusammenarbeiten, indem sie Storybook als eine einzige Quelle der Wahrheit für UI-Komponenten verwenden. Es ermöglicht Diskussionen über die Erweiterung oder Überarbeitung der spezifischen Funktionalität oder des Designs von Komponenten.

Wie funktioniert Storybook?

Storybook durchsucht das Repository nach allen Dateien, die mit
.stories.js|ts|jsx|tsx und fügt die Komponenten und ihre Geschichten zu der Sammlung hinzu, die im Browser gerendert werden kann. Storybook beschreibt eine Story als:

A story captures the rendered state of a UI component. Developers write multiple stories per component that describe all the “interesting” states a component can support.

Das folgende Bild zeigt zum Beispiel die verschiedenen Geschichten, die für eine unserer Schaltflächen namensNbxButton.tsx. Wie man sieht, enthält jeder Beitrag auch den entsprechenden Codeschnipsel auf der rechten Seite.

Stroybook

Warum verwenden wir Storybook?

Bei Nitrobox dokumentieren wir unsere Komponenten aus mehreren Gründen mit Storybook. Der erste Grund ist die Verbesserung der Zusammenarbeit zwischen Beteiligten aus verschiedenen Teams in der Entwurfsphase. 

Der zweite Grund ist, die Sichtbarkeit der Komponenten, insbesondere der wiederverwendbaren, für Entwickler und andere Beteiligte zu verbessern. 

Der dritte Grund ist die Möglichkeit, die Komponenten isoliert zu testen, ohne die gesamte Anwendung starten zu müssen.

Wie verwenden wir Storybook?

Heutzutage nutzen viele moderne React-Anwendungen die Context-API, um einen Zustand bereitzustellen, der von jeder UI-Komponente innerhalb der Anwendung konsumiert werden kann. Dieser Zustand wird intern von der Komponente verwendet, um den Stil und/oder die Funktionalität der Komponente zu ändern, was bedeutet, dass die Komponente ohne einen bestimmten Zustand von einem Kontextanbieter nicht gerendert werden kann.

Einige unserer Komponenten sind auf Werte angewiesen, die von Kontextanbietern bereitgestellt werden. Der Versuch, diese Komponenten isoliert in Storybook zu rendern, führt zu einem Fehler. Um dieses Problem zu lösen, werden wir Storybook so konfigurieren, dass es die notwendigen Kontextanbieter für diese Komponenten enthält.

Storybook Konfiguration

Heutzutage nutzen viele moderne React-Anwendungen die Context-API, um einen Zustand bereitzustellen, der von jeder UI-Komponente innerhalb der Anwendung konsumiert werden kann. Dieser Zustand wird intern von der Komponente verwendet, um den Stil und/oder die Funktionalität der Komponente zu ändern, was bedeutet, dass die Komponente ohne einen bestimmten Zustand von einem Kontextanbieter nicht gerendert werden kann.

Einige unserer Komponenten sind auf Werte angewiesen, die von Kontextanbietern bereitgestellt werden. Der Versuch, diese Komponenten isoliert in Storybook zu rendern, führt zu einem Fehler. Um dieses Problem zu lösen, werden wir Storybook so konfigurieren, dass es die notwendigen Kontextanbieter für diese Komponenten enthält.

Konfigurieren des Storybook Prjoekts

er erste Schritt in der Konfiguration von Storybook ist das Hinzufügen der Hauptkonfigurationsdatei namens.storybook/main.ts. Die Datei main.ts definiert das Verhalten des Storybook-Projekts, wie z.B. den Speicherort der Stories, welche Addons das Projekt verwenden soll und so weiter. Ein Beispiel für eine solche Konfiguration für eine React-Anwendung, die das Vite-Build-Tool verwendet, könnte wie folgt aussehen:

				
					import type { StorybookConfig } from '@storybook/react-vite';

const config: StorybookConfig = {
  stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
  addons: [
    '@storybook/addon-links',
    '@storybook/addon-essentials',
    '@storybook/addon-docs',
    'storybook-addon-remix-react-router',
  ],
  framework: {
    name: '@storybook/react-vite',
    options: {},
  },
  docs: {
    autodocs: 'tag',
  },
};

export default config;
				
			

Konfigurieren der Wiedergabe von Stories

Der zweite Schritt im Konfigurationsprozess ist das Hinzufügen der Datei .storybook/preview.tsx. Die Datei preview.tsx ermöglicht es uns zu kontrollieren, wie Stories gerendert werden und globale decorators und Parameter hinzuzufügen. Storybook definiert decorators wie folgt:

Ein Dekorator ist ein Weg, eine Story in zusätzliche „Rendering“-Funktionalität zu verpacken… Beim Schreiben von Stories werden decorators typischerweise verwendet, um Stories mit zusätzlichem Markup oder Kontext-Mocking zu umhüllen.

Context Mocking ist genau das, was uns interessiert, um das Problem des Renderings von Komponenten zu lösen, die einen Status von Kontextanbietern benötigen. Wir führen diesen Schritt in unsererpreview.tsx Datei mit dem hook useContextProvidersaus, wo wir einige unserer Context-Provider nachbilden, die für das unabhängige Rendern der Komponenten in Storybook benötigt werden. Der Hook useContextProviders wird dann in die decorators Eigenschaft in der preview  am Ende des folgenden code snippet aus unserer  preview.tsxeingefügt:

				
					import type { Preview } from '@storybook/react';
import { CssBaseline, ThemeProvider } from '@mui/material';
import React, { Suspense } from 'react';
import { I18nextProvider } from 'react-i18next';
import { withRouter } from 'storybook-addon-remix-react-router';
import { LocalizationProvider } from '@mui/x-date-pickers';
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFnsV3';
import theme from '../src/Theme';
import i18n from '../src/i18n/i18n';
import UserProfileContext from '../src/sharedComponents/UserProfileContext';
import { mockedUserProfile } from '../src/vitest/mocks';

const useContextProviders = (Story, context) => {
  return (
    <UserProfileContext.Provider
      value={{
        userProfile: mockedUserProfile,
        setUserProfile: () => {},
      }}
    >
      <ThemeProvider theme={theme}>
        <CssBaseline />
        <LocalizationProvider dateAdapter={AdapterDateFns}>
          <Suspense fallback={<div>loading translations...</div>}>
            <I18nextProvider i18n={i18n}>
              <Story /> // any story can consume values from context providers above
            </I18nextProvider>
          </Suspense>
        </LocalizationProvider>
      </ThemeProvider>
    </UserProfileContext.Provider>
  );
};

const preview: Preview = {
  parameters: {
    actions: { argTypesRegex: '^on[A-Z].*' },
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/i,
      },
    },
  },
  decorators: [useContextProviders, withRouter], // global decorators
};

export default preview;
				
			

Auf diese Weise stellen wir sicher, dass die Komponenten isoliert gerendert werden können, ohne sich um die Kontextanbieter zu kümmern.

Komponenten Stories hinzufügen

Im Webportal von Nitrobox wird eine Komponente namens  NbxAlert.tsx verwendet, um Informationen mit verschiedenen Stilen innerhalb eines Containers anzuzeigen. Gehen wir nun den Prozess des Hinzufügens der Stories zu Storybook durch.

Wir fügen die Komponenten mit Stories in das Verzeichnis src/stories/ein. Dort erstellen wir die Datei NbxAlert.stories.tsx, in der wir das Meta-Objekt mit Informationen über die Komponente wie ihre Hierarchie (definiert in title, Zeile 5 unten), die zu rendernde Komponente (festgelegt in component, Zeile 6 unten) und andere Meta-Informationen definieren.

				
					import { Meta, StoryObj } from '@storybook/react';
import NbxAlert from 'components/base/NbxAlert';

const meta = {
  title: 'nbx components/Alert/NbxAlert',
  component: NbxAlert,
  parameters: {
    docs: {
      description: {
        component: `This component is a alert with various status displays. The severity of the condition is displayed.`,
      },
    },
  },
  tags: ['autodocs'],
  argTypes: {},
} satisfies Meta<typeof NbxAlert>;

export default meta;
				
			

Anschließend erstellen wir einen Typ Story der auf demmeta basiert (Zeile 1 unten). Jede Story vom Typ Story, repräsentiert eine Variante der Komponente NbxAlert.tsx,auf der Grundlage der im Objekt args übergebenen Werte (Zeile 11 unten). Im folgenden code snippet erstellen wir die Story für eine Variante namens InfoAlert:

				
					type Story = StoryObj<typeof meta>;

export const InfoAlert: Story = {
  parameters: {
    docs: {
      description: {
        story: 'A alert that shows information',
      },
    },
  },
  args: {
    children: <>Info</>,
    severity: 'info',
  },
};
				
			

Mit mehreren Stories, die in der Datei NbxAlert.stories.tsx,geschrieben sind, kann eine Seite in unserer internen Storybook-Komponenten-Webseite erstellt werden. Die Seite NbxAlert.tsx szeigt die folgenden Stories:

Storybook components webpage

Fazit

Bei Nitrobox verwenden wir Storybook, um wiederverwendbare Komponenten unabhängig voneinander anzuzeigen und zu testen, was eine effiziente Entwicklung und Demonstration dieser Komponenten außerhalb der Hauptanwendung ermöglicht. Die Isolierung verfügbarer Komponenten kann Diskussionen über die aktuellen Funktionalitäten und deren Erweiterung anstoßen. Es hilft auch bei der Reduzierung von Code-Duplizierung, da wiederverwendbare Komponenten mit Storybook Sichtbarkeit erlangen und die Entwicklung über verschiedene Teams hinweg leiten. Das sind unsere bisherigen Erfahrungen mit Storybook.

Über den Autor

David Albrecht ist Senior Software Engineer bei Nitrobox. Mehrt zu David auf GitHub und LinkedIn.