This section is a work in progress.
Lifecycle APIs are shared by Themes and Plugins.
getPathsToWatch()
# Specifies the paths to watch for plugins and themes. The paths are watched by the dev server so that the plugin lifecycles are reloaded when contents in the watched paths change. Note that the plugins and themes modules are initially called with context
and options
from Node, which you may use to find the necessary directory information about the site.
Example:
docusaurus-plugin/src/index.js
Copy const path = require ( 'path' ) ;
module . exports = function ( context , options ) {
return {
name : 'docusaurus-plugin' ,
getPathsToWatch ( ) {
const contentPath = path . resolve ( context . siteDir , options . path ) ;
return [ ` ${ contentPath } /**/*.{ts,tsx} ` ] ;
} ,
} ;
} ;
async loadContent()
# Plugins should use this lifecycle to fetch from data sources (filesystem, remote API, headless CMS, etc) or doing some server processing.
For example, this plugin below return a random integer between 1 to 10 as content;
docusaurus-plugin/src/index.js
Copy const path = require ( 'path' ) ;
module . exports = function ( context , options ) {
return {
name : 'docusaurus-plugin' ,
async loadContent ( ) {
return 1 + Math . floor ( Math . random ( ) * 10 ) ;
} ,
} ;
} ;
async contentLoaded({content, actions})
# Plugins should use the data loaded in loadContent
and construct the pages/routes that consume the loaded data (optional).
content
# contentLoaded
will be called after loadContent
is done, the return value of loadContent()
will be passed to contentLoaded
as content
.
actions
# actions
contain two functions:
addRoute(config: RouteConfig): void
Create a route to add to the website.
Copy interface RouteConfig {
path : string ;
component : string ;
modules ? : RouteModule ;
routes ? : RouteConfig [ ] ;
exact ? : boolean ;
priority ? : number ;
}
interface RouteModule {
[ module : string ] : Module | RouteModule | RouteModule [ ] ;
}
type Module =
| {
path : string ;
__import ? : boolean ;
query ? : ParsedUrlQueryInput ;
}
| string ;
createData(name: string, data: any): Promise<string>
A helper function to help you write some data (usually a string or JSON) to disk with in-built caching. It takes a file name relative to to your plugin's directory (name) , your data (data) , and will return a path to where the data is created.
For example, this plugin below create a /roll
page which display "You won xxxx" to user.
website/src/components/roll.js
Copy import React from 'react' ;
export default function ( props ) {
const { prizes } = props ;
const index = Math . floor ( Math . random ( ) * 3 ) ;
return < div > You won $ { prizes [ index ] } </ div > ;
}
docusaurus-plugin/src/index.js
Copy module . exports = function ( context , options ) {
return {
name : 'docusaurus-plugin' ,
async contentLoaded ( { content , actions } ) {
const { createData , addRoute } = actions ;
const prizes = JSON . stringify ( [ '$1' , 'a cybertruck' , 'nothing' ] ) ;
const prizesDataPath = await createData ( 'prizes.json' , prizes ) ;
addRoute ( {
path : '/roll' ,
component : '@site/src/components/roll.js' ,
modules : {
prizes : prizesDataPath
}
exact : true ,
} ) ;
} ,
} ;
} ;
configureWebpack(config, isServer, utils)
# Modifies the internal webpack config. If the return value is a JavaScript object, it will be merged into the final config using webpack-merge
. If it is a function, it will be called and receive config
as the first argument and an isServer
flag as the argument argument.
config
# configureWebpack
is called with config
generated according to client/server build. You may treat this as the base config to be merged with.
isServer
# configureWebpack
will be called both in server build and in client build. The server build receives true
and the client build receives false
as isServer
.
utils
# The initial call to configureWebpack
also receives a util object consists of three functions:
getStyleLoaders(isServer: boolean, cssOptions: {[key: string]: any}): Loader[]
getCacheLoader(isServer: boolean, cacheOptions?: {}): Loader | null
getBabelLoader(isServer: boolean, babelOptions?: {}): Loader
You may use them to return your webpack configures conditionally.
For example, this plugin below modify the webpack config to transpile .foo
file.
docusaurus-plugin/src/index.js
Copy module . exports = function ( context , options ) {
return {
name : 'custom-docusaurus-plugin' ,
configureWebpack ( config , isServer , utils ) {
const { getCacheLoader } = utils ;
return {
module : {
rules : [
{
test : /\.foo$/ ,
use : [ getCacheLoader ( isServer ) , 'my-custom-webpack-loader' ] ,
} ,
] ,
} ,
} ;
} ,
} ;
} ;
postBuild(props)
# Called when a (production) build finishes.
Copy type Props = {
siteDir : string ;
generatedFilesDir : string ;
siteConfig : DocusaurusConfig ;
outDir : string ;
baseUrl : string ;
headTags : string ;
preBodyTags : string ;
postBodyTags : string ;
routesPaths : string [ ] ;
plugins : Plugin < any > [ ] ;
} ;
Example:
docusaurus-plugin/src/index.js
Copy module . exports = function ( context , options ) {
return {
name : 'docusaurus-plugin' ,
async postBuild ( { siteConfig = { } , routesPaths = [ ] , outDir } ) {
routesPaths . map ( ( route ) => {
console . log ( route ) ;
} ) ;
} ,
} ;
} ;
extendCli(cli)
# Register an extra command to enhance the CLI of docusaurus. cli
is commander object.
Example:
docusaurus-plugin/src/index.js
Copy module . exports = function ( context , options ) {
return {
name : 'docusaurus-plugin' ,
extendCli ( cli ) {
cli
. command ( 'roll' )
. description ( 'Roll a random number between 1 and 1000' )
. action ( ( ) => {
console . log ( Math . floor ( Math . random ( ) * 1000 + 1 ) ) ;
} ) ;
} ,
} ;
} ;
injectHtmlTags()
# Inject head and/or body html tags to Docusaurus generated html.
Copy function injectHtmlTags ( ) : {
headTags ? : HtmlTags ;
preBodyTags ? : HtmlTags ;
postBodyTags ? : HtmlTags ;
} ;
type HtmlTags = string | HtmlTagObject | ( string | HtmlTagObject ) [ ] ;
interface HtmlTagObject {
attributes ? : {
[ attributeName : string ] : string | boolean ;
} ;
tagName : string ;
innerHTML ? : string ;
}
Example:
docusaurus-plugin/src/index.js
Copy module . exports = function ( context , options ) {
return {
name : 'docusaurus-plugin' ,
injectHtmlTags ( ) {
return {
headTags : [
{
tagName : 'link' ,
attributes : {
rel : 'preconnect' ,
href : 'https://www.github.com' ,
} ,
} ,
] ,
preBodyTags : [
{
tagName : 'script' ,
attributes : {
charset : 'utf-8' ,
src : '/noflash.js' ,
} ,
} ,
] ,
postBodyTags : [ ` <div> This is post body </div> ` ] ,
} ;
} ,
} ;
} ;
getThemePath()
# Returns the path to the directory where the theme components can be found. When your users calls swizzle
, getThemePath
is called and its returned path is used to find your theme components.
If you use the folder directory above, your getThemePath
can be:
my-theme/src/index.js
Copy const path = require ( 'path' ) ;
module . exports = function ( context , options ) {
return {
name : 'name-of-my-theme' ,
getThemePath ( ) {
return path . resolve ( __dirname , './theme' ) ;
} ,
} ;
} ;
getClientModules()
# Returns an array of paths to the modules that are to be imported in the client bundle. These modules are imported globally before React even renders the initial UI.
As an example, to make your theme load a customCss
object from options
passed in by the user:
my-theme/src/index.js
Copy const path = require ( 'path' ) ;
module . exports = function ( context , options ) {
const { customCss } = options || { } ;
return {
name : 'name-of-my-theme' ,
getClientModules ( ) {
return [ customCss ] ;
} ,
} ;
} ;
Example# Here's a mind model for a presumptuous plugin implementation.
Copy const DEFAULT_OPTIONS = {
} ;
module . exports = function ( context , opts ) {
const options = { ... DEFAULT_OPTIONS , ... options } ;
return {
name : 'docusaurus-my-project-cool-plugin' ,
async loadContent ( ) {
} ,
async contentLoaded ( { content , actions } ) {
} ,
async postBuild ( props ) {
} ,
async postStart ( props ) {
} ,
afterDevServer ( app , server ) {
} ,
beforeDevServer ( app , server ) {
} ,
configureWebpack ( config , isServer ) {
} ,
getPathsToWatch ( ) {
} ,
getThemePath ( ) {
} ,
getClientModules ( ) {
} ,
extendCli ( cli ) {
} ,
injectHtmlTags ( ) {
} ,
} ;
} ;