Aller au contenu principal
Version : Canary 🚧

Cycle de vie des API

Pendant la construction, les plugins sont chargés en parallèle pour récupérer leur propre contenu et les rendre aux routes. Les plugins peuvent également configurer webpack ou post-traiter les fichiers générés.

async loadContent()

Les plugins doivent utiliser ce cycle de vie pour récupérer des sources de données (système de fichiers, API distante, CMS sans entête, etc) ou pour effectuer un traitement du serveur. La valeur retournée est le contenu dont il a besoin.

Par exemple, ce plugin ci-dessous renvoie un entier aléatoire compris entre 1 et 10 comme contenu.

docusaurus-plugin/src/index.js
module.exports = function (context, options) {
return {
name: 'docusaurus-plugin',
async loadContent() {
return 1 + Math.floor(Math.random() * 10);
},
};
};

async contentLoaded({content, actions})

Les données qui ont été chargées dans loadContent seront consommées dans contentLoaded. Il peut être rendu sur des routes, enregistrés en tant que données globales, etc.

content

contentLoaded sera appelé après que loadContent soit fait. La valeur retournée de loadContent() sera passée à contentLoaded comme content (contenu).

actions

actions contient trois fonctions :

addRoute(config: RouteConfig): void

Créez une route pour l'ajouter au site web.

type RouteConfig = {
path: string;
component: string;
modules?: RouteModules;
routes?: RouteConfig[];
exact?: boolean;
priority?: number;
};
type RouteModules = {
[module: string]: Module | RouteModules | RouteModules[];
};
type Module =
| {
path: string;
__import?: boolean;
query?: ParsedUrlQueryInput;
}
| string;

createData(name: string, data: any): Promise<string>

Une callback déclarative pour créer des données statiques (généralement JSON ou string) qui peuvent être fournies ultérieurement à vos routes comme props. Prend le nom du fichier et les données à stocker, et renvoie le chemin du fichier de données actuel.

Par exemple, ce plugin ci-dessous crée une page /friends qui affiche Vos amis sont : Yangshun, Sébastien :

website/src/components/Friends.js
import React from 'react';

export default function FriendsComponent({friends}) {
return <div>Vos amis sont {friends.join(',')}</div>;
}
docusaurus-friends-plugin/src/index.js
export default function friendsPlugin(context, options) {
return {
name: 'docusaurus-friends-plugin',
async contentLoaded({content, actions}) {
const {createData, addRoute} = actions;
// Crée friends.json
const friends = ['Yangshun', 'Sebastien'];
const friendsJsonPath = await createData(
'friends.json',
JSON.stringify(friends),
);

// Ajoute la route '/friends' et assure-vous qu'il reçoit la props friends
addRoute({
path: '/friends',
component: '@site/src/components/Friends.js',
modules: {
// propName -> chemin fichier JSON
friends: friendsJsonPath,
},
exact: true,
});
},
};
}

setGlobalData(data: any): void

Cette fonction permet de créer des données globales de plugin, qui peuvent être lues depuis n'importe quelle page, y compris les pages créées par d'autres plugins et la mise en page de votre thème.

Ces données deviennent accessibles pour votre code client/thème, via les useGlobalData et usePluginData.

attention

Les données globales sont... globales : leurs tailles affectent le temps de chargement de toutes les pages de votre site, alors essayez de les garder petites. Préférez createData et des données spécifiques à la page dans la mesure du possible.

Par exemple, ce plugin ci-dessous crée une page /friends qui affiche Vos amis sont : Yangshun, Sébastien :

website/src/components/Friends.js
import React from 'react';
import {usePluginData} from '@docusaurus/useGlobalData';

export default function FriendsComponent() {
const {friends} = usePluginData('my-friends-plugin');
return <div>Vos amis sont {friends.join(',')}</div>;
}
docusaurus-friends-plugin/src/index.js
export default function friendsPlugin(context, options) {
return {
name: 'docusaurus-friends-plugin',
async contentLoaded({content, actions}) {
const {setGlobalData, addRoute} = actions;
// Crée des données globales friends
setGlobalData({friends: ['Yangshun', 'Sebastien']});

// Ajoute la route '/friends'
addRoute({
path: '/friends',
component: '@site/src/components/Friends.js',
exact: true,
});
},
};
}

configureWebpack(config, isServer, utils, content)

Modifie la configuration interne de webpack. Si la valeur retournée est un objet JavaScript, elle sera fusionnée dans la configuration finale en utilisant webpack-merge. Si c'est une fonction, elle sera appelée et recevra config comme premier argument et un drapeau isServer comme second argument.

attention

L'API de configureWebpack sera modifiée dans le futur pour accepter un objet (configureWebpack({config, isServer, utils, content}))

config

configureWebpack est appelée avec config générée selon la construction du client/serveur. Vous pouvez le considérer comme la configuration de base avec laquelle il faut fusionner.

isServer

configureWebpack sera appelée à la fois dans la construction du serveur et dans la construction du client. La construction du serveur reçoit true et la construction du client reçoit false pour isServer.

utils

configureWebpack reçoit également un objet utilitaire :

  • getStyleLoaders(isServer: boolean, cssOptions: {[key: string]: any}): Loader[]
  • getJSLoader(isServer: boolean, cacheOptions?: {}): Loader | null

Vous pouvez les utiliser pour retourner votre configuration webpack sous certaines conditions.

Par exemple, ce plugin ci-dessous modifie la configuration de webpack pour transpiler les fichiers .foo.

docusaurus-plugin/src/index.js
module.exports = function (context, options) {
return {
name: 'custom-docusaurus-plugin',
configureWebpack(config, isServer, utils) {
const {getJSLoader} = utils;
return {
module: {
rules: [
{
test: /\.foo$/,
use: [getJSLoader(isServer), 'my-custom-webpack-loader'],
},
],
},
};
},
};
};

content

configureWebpack sera appelé aussi avec le contenu chargé par le plugin.

Fusionnez la stratégie

Nous fusionnons les parties de configuration Webpack des plugins dans la configuration globale de Webpack en utilisant webpack-merge.

Il est possible de spécifier la stratégie de fusion. Par exemple, si vous voulez qu'une règle de webpack soit placée au début au lieu d'être ajoutée à la fin :

docusaurus-plugin/src/index.js
module.exports = function (context, options) {
return {
name: 'custom-docusaurus-plugin',
configureWebpack(config, isServer, utils) {
return {
mergeStrategy: {'module.rules': 'prepend'},
module: {rules: [myRuleToPrepend]},
};
},
};
};

Lisez la documentation de la stratégie de fusion de webpack-merge pour plus de détails.

Configuration du serveur de développement

Le serveur de développement peut être configuré en renvoyant un champ devServer.

docusaurus-plugin/src/index.js
module.exports = function (context, options) {
return {
name: 'custom-docusaurus-plugin',
configureWebpack(config, isServer, utils) {
return {
devServer: {
open: '/docs', // Opens localhost:3000/docs instead of localhost:3000/
},
};
},
};
};

configurePostCss(options)

Modifie postcssOptions de postcss-loader pendant la génération du bundle client.

Devrait retourner le postcssOptions muté.

Par défaut, postcssOptions ressemble à ceci :

const postcssOptions = {
ident: 'postcss',
plugins: [require('autoprefixer')],
};

Exemple :

docusaurus-plugin/src/index.js
module.exports = function (context, options) {
return {
name: 'docusaurus-plugin',
configurePostCss(postcssOptions) {
// Ajoute un nouveau plugin PostCSS.
postcssOptions.plugins.push(require('postcss-import'));
return postcssOptions;
},
};
};

postBuild(props)

Appelée quand une version (production) se termine.

interface Props {
siteDir: string;
generatedFilesDir: string;
siteConfig: DocusaurusConfig;
outDir: string;
baseUrl: string;
headTags: string;
preBodyTags: string;
postBodyTags: string;
routesPaths: string[];
plugins: Plugin<any>[];
content: Content;
}

Exemple :

docusaurus-plugin/src/index.js
module.exports = function (context, options) {
return {
name: 'docusaurus-plugin',
async postBuild({siteConfig = {}, routesPaths = [], outDir}) {
// Affiche dans la console toutes les routes rendues.
routesPaths.map((route) => {
console.log(route);
});
},
};
};

injectHtmlTags({content})

Injecte les balises HTML head et/ou body vers le HTML générées de Docusaurus.

injectHtmlTags sera appelé aussi avec le contenu chargé par le plugin.

function injectHtmlTags(): {
headTags?: HtmlTags;
preBodyTags?: HtmlTags;
postBodyTags?: HtmlTags;
};

type HtmlTags = string | HtmlTagObject | (string | HtmlTagObject)[];

type HtmlTagObject = {
/**
* Attributs de la balise HTML
* Par exemple. `{'disabled': true, 'value': 'demo', 'rel': 'preconnect'}`
*/
attributes?: {
[attributeName: string]: string | boolean;
};
/**
* Le nom de la balise, par exemple. `div`, `script`, `link`, `meta`
*/
tagName: string;
/**
* The inner HTML
*/
innerHTML?: string;
};

Exemple :

docusaurus-plugin/src/index.js
module.exports = function (context, options) {
return {
name: 'docusaurus-plugin',
loadContent: async () => {
return {remoteHeadTags: await fetchHeadTagsFromAPI()};
},
injectHtmlTags({content}) {
return {
headTags: [
{
tagName: 'link',
attributes: {
rel: 'preconnect',
href: 'https://www.github.com',
},
},
...content.remoteHeadTags,
],
preBodyTags: [
{
tagName: 'script',
attributes: {
charset: 'utf-8',
src: '/noflash.js',
},
},
],
postBodyTags: [`<div> Ceci est le corps de l'article </div>`],
};
},
};
};

Les balises seront ajoutés comme ceci:

  • headTags will be inserted before the closing </head> tag after scripts added by config.
  • preBodyTags will be inserted after the opening <body> tag before any child elements.
  • postBodyTags will be inserted before the closing </body> tag after all child elements.

getClientModules()

Retourne un tableau de chemins vers les modules client qui doivent être importés dans le paquet client.

À titre d'exemple, pour que votre thème puisse charger un fichier customCss ou customJs à partir des options passées par l'utilisateur :

my-theme/src/index.js
const path = require('path');

module.exports = function (context, options) {
const {customCss, customJs} = options || {};
return {
name: 'name-of-my-theme',
getClientModules() {
return [customCss, customJs];
},
};
};