生命周期 API
¥Lifecycle APIs
在构建过程中,插件会并行加载以获取自己的内容并将其渲染给路由。插件还可以配置 webpack 或对生成的文件进行后处理。
¥During the build, plugins are loaded in parallel to fetch their own contents and render them to routes. Plugins may also configure webpack or post-process the generated files.
async loadContent()
插件应该使用此生命周期从数据源(文件系统、远程 API、无头 CMS 等)获取数据或进行一些服务器处理。返回值就是它需要的内容。
¥Plugins should use this lifecycle to fetch from data sources (filesystem, remote API, headless CMS, etc.) or do some server processing. The return value is the content it needs.
例如,下面的这个插件返回 1 到 10 之间的随机整数作为内容。
¥For example, this plugin below returns a random integer between 1 and 10 as content.
export default function (context, options) {
return {
name: 'docusaurus-plugin',
async loadContent() {
return 1 + Math.floor(Math.random() * 10);
},
};
}
async contentLoaded({content, actions})
loadContent
中加载的数据将在 contentLoaded
中消耗。它可以渲染到路由、注册为全局数据等。
¥The data that was loaded in loadContent
will be consumed in contentLoaded
. It can be rendered to routes, registered as global data, etc.
content
contentLoaded
将在 loadContent
完成后被调用。loadContent()
的返回值将作为 content
传递给 contentLoaded
。
¥contentLoaded
will be called after loadContent
is done. The return value of loadContent()
will be passed to contentLoaded
as content
.
actions
actions
包含三个功能:
¥actions
contain three functions:
addRoute(config: RouteConfig): void
创建要添加到网站的路由。
¥Create a route to add to the website.
export type RouteConfig = {
/**
* With leading slash. Trailing slash will be normalized by config.
*/
path: string;
/**
* Component used to render this route, a path that the bundler can `require`.
*/
component: string;
/**
* Props. Each entry should be `[propName]: pathToPropModule` (created with
* `createData`)
*/
modules?: RouteModules;
/**
* The route context will wrap the `component`. Use `useRouteContext` to
* retrieve what's declared here. Note that all custom route context declared
* here will be namespaced under {@link RouteContext.data}.
*/
context?: RouteModules;
/**
* Nested routes config, useful for "layout routes" having subroutes.
*/
routes?: RouteConfig[];
/**
* React router config option: `exact` routes would not match subroutes.
*/
exact?: boolean;
/**
* React router config option: `strict` routes are sensitive to the presence
* of a trailing slash.
*/
strict?: boolean;
/**
* Used to sort routes.
* Higher-priority routes will be matched first.
*/
priority?: number;
/**
* Optional route metadata
*/
metadata?: RouteMetadata;
/**
* Extra props; will be available on the client side.
*/
[propName: string]: unknown;
};
/**
* Plugin authors can assign extra metadata to the created routes
* It is only available on the Node.js side, and not sent to the browser
* Optional: plugin authors are encouraged but not required to provide it
* * Some plugins might use this data to provide additional features.
* This is the case of the sitemap plugin to provide support for "lastmod".
* See also: https://github.com/facebook/docusaurus/pull/9954
*/
export type RouteMetadata = {
/**
* The source code file path that led to the creation of the current route
* In official content plugins, this is usually a Markdown or React file
* This path is expected to be relative to the site directory
*/
sourceFilePath?: string;
/**
* The last updated date of this route
* This is generally read from the Git history of the sourceFilePath
* but can also be provided through other means (usually front matter)
* * This has notably been introduced for adding "lastmod" support to the
* sitemap plugin, see https://github.com/facebook/docusaurus/pull/9954
*/
lastUpdatedAt?: number;
};
type RouteModules = {
[module: string]: Module | RouteModules | RouteModules[];
};
type Module =
| {
path: string;
__import?: boolean;
query?: ParsedUrlQueryInput;
}
| string;
createData(name: string, data: any): Promise<string>
用于创建静态数据(通常是 JSON 或字符串)的声明性回调,稍后可以将其作为 props 提供给你的路由。获取要存储的文件名和数据,并返回实际数据文件的路径。
¥A declarative callback to create static data (generally JSON or string) which can later be provided to your routes as props. Takes the file name and data to be stored, and returns the actual data file's path.
例如,下面的这个插件创建了一个显示 Your friends are: Yangshun, Sebastien
的 /friends
页面:
¥For example, this plugin below creates a /friends
page which displays Your friends are: Yangshun, Sebastien
:
import React from 'react';
export default function FriendsComponent({friends}) {
return <div>Your friends are {friends.join(',')}</div>;
}
export default function friendsPlugin(context, options) {
return {
name: 'docusaurus-friends-plugin',
async contentLoaded({content, actions}) {
const {createData, addRoute} = actions;
// Create friends.json
const friends = ['Yangshun', 'Sebastien'];
const friendsJsonPath = await createData(
'friends.json',
JSON.stringify(friends),
);
// Add the '/friends' routes, and ensure it receives the friends props
addRoute({
path: '/friends',
component: '@site/src/components/Friends.js',
modules: {
// propName -> JSON file path
friends: friendsJsonPath,
},
exact: true,
});
},
};
}
setGlobalData(data: any): void
此功能允许创建一些可以从任何页面读取的全局插件数据,包括其他插件创建的页面以及你的主题布局。
¥This function permits one to create some global plugin data that can be read from any page, including the pages created by other plugins, and your theme layout.
你的客户端/主题代码可以通过 useGlobalData
和 usePluginData
钩子访问此数据。
¥This data becomes accessible to your client-side/theme code through the useGlobalData
and usePluginData
hooks.
全局数据是...全球的:它的大小会影响网站所有页面的加载时间,因此请尽量使其较小。尽可能首选 createData
和特定于页面的数据。
¥Global data is... global: its size affects the loading time of all pages of your site, so try to keep it small. Prefer createData
and page-specific data whenever possible.
例如,下面的这个插件创建了一个显示 Your friends are: Yangshun, Sebastien
的 /friends
页面:
¥For example, this plugin below creates a /friends
page which displays Your friends are: Yangshun, Sebastien
:
import React from 'react';
import {usePluginData} from '@docusaurus/useGlobalData';
export default function FriendsComponent() {
const {friends} = usePluginData('docusaurus-friends-plugin');
return <div>Your friends are {friends.join(',')}</div>;
}
export default function friendsPlugin(context, options) {
return {
name: 'docusaurus-friends-plugin',
async contentLoaded({content, actions}) {
const {setGlobalData, addRoute} = actions;
// Create friends global data
setGlobalData({friends: ['Yangshun', 'Sebastien']});
// Add the '/friends' routes
addRoute({
path: '/friends',
component: '@site/src/components/Friends.js',
exact: true,
});
},
};
}
configureWebpack(config, isServer, utils, content)
修改内部 webpack 配置。如果返回值是 JavaScript 对象,它将使用 webpack-merge
合并到最终配置中。如果它是一个函数,它将被调用并接收 config
作为第一个参数和 isServer
标志作为第二个参数。
¥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 second argument.
configureWebpack
的 API 将来会修改为接受对象(configureWebpack({config, isServer, utils, content})
)
¥The API of configureWebpack
will be modified in the future to accept an object (configureWebpack({config, isServer, utils, content})
)
config
configureWebpack
被调用,并根据客户端/服务器构建生成 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
将在服务器构建和客户端构建中被调用。服务器版本接收 true
,客户端版本接收 false
作为 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
configureWebpack
还接收一个 util 对象:
¥configureWebpack
also receives an util object:
-
getStyleLoaders(isServer: boolean, cssOptions: {[key: string]: any}): Loader[]
-
getJSLoader(isServer: boolean, cacheOptions?: {}): Loader | null
你可以使用它们有条件地返回你的 webpack 配置。
¥You may use them to return your webpack configuration conditionally.
例如,下面的这个插件修改 webpack 配置以转译 .foo
文件。
¥For example, this plugin below modify the webpack config to transpile .foo
files.
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
将与插件加载的内容一起调用。
¥configureWebpack
will be called both with the content loaded by the plugin.
合并策略
¥Merge strategy
我们使用 webpack-merge 将插件的 Webpack 配置部分合并到全局 Webpack 配置中。
¥We merge the Webpack configuration parts of plugins into the global Webpack config using webpack-merge.
可以指定合并策略。例如,如果你希望将 webpack 规则添加到前面而不是附加到后面:
¥It is possible to specify the merge strategy. For example, if you want a webpack rule to be prepended instead of appended:
export default function (context, options) {
return {
name: 'custom-docusaurus-plugin',
configureWebpack(config, isServer, utils) {
return {
mergeStrategy: {'module.rules': 'prepend'},
module: {rules: [myRuleToPrepend]},
};
},
};
}
阅读 webpack-合并策略文档 了解更多详细信息。
¥Read the webpack-merge strategy doc for more details.
配置开发服务器
¥Configuring dev server
可以通过返回 devServer
字段来配置开发服务器。
¥The dev server can be configured through returning a devServer
field.
export default 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)
在生成客户端打包包期间修改 postcssOptions
共 postcss-loader
。
¥Modifies postcssOptions
of postcss-loader
during the generation of the client bundle.
应该返回突变的 postcssOptions
。
¥Should return the mutated postcssOptions
.
默认情况下,postcssOptions
看起来像这样:
¥By default, postcssOptions
looks like this:
const postcssOptions = {
ident: 'postcss',
plugins: [require('autoprefixer')],
};
示例:
¥Example:
export default function (context, options) {
return {
name: 'docusaurus-plugin',
configurePostCss(postcssOptions) {
// Appends new PostCSS plugin.
postcssOptions.plugins.push(require('postcss-import'));
return postcssOptions;
},
};
}
postBuild(props)
当(生产)构建完成时调用。
¥Called when a (production) build finishes.
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;
}
示例:
¥Example:
export default function (context, options) {
return {
name: 'docusaurus-plugin',
async postBuild({siteConfig = {}, routesPaths = [], outDir}) {
// Print out to console all the rendered routes.
routesPaths.map((route) => {
console.log(route);
});
},
};
}
injectHtmlTags({content})
将 head 和/或 body HTML 标签注入 Docusaurus 生成的 HTML。
¥Inject head and/or body HTML tags to Docusaurus generated HTML.
injectHtmlTags
将与插件加载的内容一起调用。
¥injectHtmlTags
will be called both with the content loaded by the plugin.
function injectHtmlTags(): {
headTags?: HtmlTags;
preBodyTags?: HtmlTags;
postBodyTags?: HtmlTags;
};
type HtmlTags = string | HtmlTagObject | (string | HtmlTagObject)[];
type HtmlTagObject = {
/**
* Attributes of the HTML tag
* E.g. `{'disabled': true, 'value': 'demo', 'rel': 'preconnect'}`
*/
attributes?: {
[attributeName: string]: string | boolean;
};
/**
* The tag name e.g. `div`, `script`, `link`, `meta`
*/
tagName: string;
/**
* The inner HTML
*/
innerHTML?: string;
};
示例:
¥Example:
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>`],
};
},
};
}
将添加标签如下:
¥Tags will be added as follows:
-
headTags
将被插入到 config 添加的脚本之后的结束</head>
标记之前。¥
headTags
will be inserted before the closing</head>
tag after scripts added by config. -
preBodyTags
将插入到任何子元素之前的<body>
起始标记之后。¥
preBodyTags
will be inserted after the opening<body>
tag before any child elements. -
postBodyTags
将插入到所有子元素之后的</body>
结束标记之前。¥
postBodyTags
will be inserted before the closing</body>
tag after all child elements.
getClientModules()
返回要导入到客户端包中的 客户端模块 的路径数组。
¥Returns an array of paths to the client modules that are to be imported into the client bundle.
例如,要使你的主题从用户传入的 options
加载 customCss
或 customJs
文件路径:
¥As an example, to make your theme load a customCss
or customJs
file path from options
passed in by the user:
export default function (context, options) {
const {customCss, customJs} = options || {};
return {
name: 'name-of-my-theme',
getClientModules() {
return [customCss, customJs];
},
};
}