Aller au contenu principal
Version : 2.0.0-beta.17

Architecture client

Alias de thème

Un thème fonctionne en exportant un ensemble de composants, par exemple Navbar, Layout, Footer, pour rendre les données transmises à partir de plugins. Docusaurus et les utilisateurs utilisent ces composants en les important en utilisant l'alias de webpack @theme :

import Navbar from '@theme/Navbar';

L'alias @theme peut faire référence à quelques répertoires, selon la priorité suivante :

  1. Un répertoire website/src/theme d'un utilisateur, qui est un répertoire spécial qui a la priorité supérieure.
  2. Un répertoire theme des paquets du thème de Docusaurus.
  3. Des composants de secours fournis par le noyau de Docusaurus (généralement pas nécessaire).

C'est ce qu'on appelle une architecture en couches : une couche de priorité supérieure fournissant le composant ferait de l'ombre à une couche de priorité inférieure, rendant le swizzling possible. Considérons la structure suivante :

website
├── node_modules
│ └── @docusaurus/theme-classic
│ └── theme
│ └── Navbar.js
└── src
└── theme
└── Navbar.js

website/src/theme/Navbar.js est prioritaire lorsque @theme/Navbar est importé. Ce comportement est appelé « swizzling de composant ». Si vous êtes familier avec Objective C où l'implémentation d'une fonction peut être permutée pendant l'exécution, c'est exactement le même concept ici avec le changement de la cible vers laquelle @theme/Navbar pointe !

Nous avons déjà parlé de la façon dont le thème personnalisé dans src/theme peut réutiliser un composant de thème grâce à l'alias @theme-original. Un paquet de thème peut également envelopper un composant d'un autre thème, en important le composant du thème initial, à l'aide de l'import @theme-init.

Voici un exemple d'utilisation de cette fonctionnalité pour améliorer le composant CodeBlock du thème par défaut avec une fonctionnalité de terrain de jeu react-live.

import InitialCodeBlock from '@theme-init/CodeBlock';
import React from 'react';

export default function CodeBlock(props) {
return props.live ? (
<ReactLivePlayground {...props} />
) : (
<InitialCodeBlock {...props} />
);
}

Vérifiez le code de @docusaurus/theme-live-codeblock pour plus de détails.

attention

À moins que vous ne vouliez publier sur npm un « rehausseur de thème » (comme docusaurus-theme-live-codeblock), vous n'avez probablement pas besoin de @theme-init.

Il peut être assez difficile de se faire une idée de ces alias. Imaginons le cas suivant avec une configuration super alambiquée où trois thèmes/plugins et le site lui-même essaient tous de définir le même composant. En interne, Docusaurus charge ces thèmes comme une « pile ».

+-------------------------------------------------+
| `website/src/theme/CodeBlock.js` | <-- `@theme/CodeBlock` pointe toujours vers le haut
+-------------------------------------------------+
| `theme-live-codeblock/theme/CodeBlock/index.js` | <-- `@theme-original/CodeBlock` pointe vers le composant le plus haut qui n'a pas été swizzlé
+-------------------------------------------------+
| `plugin-awesome-codeblock/theme/CodeBlock.js` |
+-------------------------------------------------+
| `theme-classic/theme/CodeBlock/index.js` | <-- `@theme-init/CodeBlock` pointe toujours vers le bas
+-------------------------------------------------+

Les composants de cette « pile » sont poussés dans l'ordre de preset plugins > preset themes > plugins > themes > site, de sorte que le composant swizzled dans website/src/theme arrive toujours en haut car il est chargé en dernier.

@theme/* pointe toujours vers le composant le plus haut — lorsque CodeBlock est swizzlé, tous les autres composants demandant @theme/CodeBlock reçoivent la version swizzlée.

@theme-original/* pointe toujours vers le composant non swizzlé le plus haut. C'est la raison pour laquelle vous pouvez importer @theme-original/CodeBlock dans le composant swizzlé - il pointe vers le suivant dans la « pile de composants », un composant fourni par le thème. Les auteurs de plugins ne devraient pas essayer de l'utiliser car votre composant pourrait être le composant le plus haut et provoquer un auto-import.

@theme-init/* pointe toujours vers le composant le plus bas - généralement, il provient du thème ou du plugin qui fournit ce composant en premier. Les plugins / thèmes individuels qui tentent d'améliorer le bloc de code peuvent utiliser en toute sécurité @theme-init/CodeBlock pour obtenir sa version de base. Les créateurs de sites ne devraient généralement pas l'utiliser car vous souhaitez probablement améliorer le composant le plus haut au lieu du plus bas. Il est également possible que l'alias @theme-init/CodeBlock n'existe pas du tout — Docusaurus ne le crée que lorsqu'il pointe vers un alias différent de @theme-original/CodeBlock, c'est-à-dire lorsqu'il est fourni par plus d'un thème. Nous ne gaspillons pas les alias !

Modules client

Les modules clients font partie de l'offre groupée de votre site, tout comme les composants du thème. Cependant, ils sont généralement accompagnés d'effets secondaires. Les modules clients peuvent être importés par Webpack — CSS, JS, etc. Les scripts JS travaillent généralement sur le contexte global, comme l'enregistrement d'écouteurs d'événements, la création de variables globales...

Ces modules sont importés globalement avant même que React ne rende l'interface utilisateur initiale.

App.tsx
// Comment ça marche sous le capot
import '@generated/client-modules';

Les plugins et les sites peuvent déclarer les modules clients respectivement via getClientModules et siteConfig.clientModules.

Les modules clients sont également appelés pendant le rendu côté serveur, alors n'oubliez pas de vérifier l'environnement d'exécution avant d'accéder aux globales côté client.

mySiteGlobalJs.js
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';

if (ExecutionEnvironment.canUseDOM) {
// Dès que le site se charge dans le navigateur, enregistrez une écoute d'événements globale
window.addEventListener('keydown', (e) => {
if (e.code === 'Period') {
location.assign(location.href.replace('.com', '.dev'));
}
});
}

Les feuilles de style CSS importées en tant que modules clients sont globales.

mySiteGlobalCss.css
/* Cette feuille de style est globale. */
.globalSelector {
color: red;
}