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.
export default 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
:
import React from 'react';
export default function FriendsComponent({friends}) {
return <div>Vos amis sont {friends.join(',')}</div>;
}
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
.
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
:
import React from 'react';
import {usePluginData} from '@docusaurus/useGlobalData';
export default function FriendsComponent() {
const {friends} = usePluginData('docusaurus-friends-plugin');
return <div>Vos amis sont {friends.join(',')}</div>;
}
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.
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
.
export default 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 :
export default 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
.
export default function (context, options) {
return {
name: 'custom-docusaurus-plugin',
configureWebpack(config, isServer, utils) {
return {
devServer: {
open: '/docs', // Ouvre localhost:3000/docs au lieu de 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 :
export default 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 :
export default 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 :
export default 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> This is post body </div>`],
};
},
};
}
Les balises seront ajoutés comme ceci:
headTags
sera inséré avant la balise de fermeture</head>
après les scripts ajoutés par config.preBodyTags
sera inséré après la balise ouvrante<body>
avant tout élément enfant.postBodyTags
sera inséré avant la balise fermante</body>
après tout élément enfant.
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 :
export default function (context, options) {
const {customCss, customJs} = options || {};
return {
name: 'name-of-my-theme',
getClientModules() {
return [customCss, customJs];
},
};
}