Lifecycle API
빌드 시 자체 콘텐츠를 가져와 경로에 렌더링하기 위해 플러그인은 병렬로 로드됩니다. 플러그인은 웹팩에서 구성하거나 생성된 파일을 나중에 처리할 수도 있습니다.
async loadContent()
Plugins should use this lifecycle to fetch from data sources (filesystem, remote API, headless CMS, etc.) or do some server processing. 반환값은 필요한 콘텐츠입니다.
예를 들어 아래 코드에서는 1부터 10 사이의 무작위 숫자를 콘텐츠로 가져옵니다.
export default function (context, options) {
return {
name: 'docusaurus-plugin',
async loadContent() {
return 1 + Math.floor(Math.random() * 10);
},
};
}
async contentLoaded({content, actions})
The data that was loaded in loadContent
will be consumed in contentLoaded
. 경로에 렌더링하거나 글로벌 데이터로 등록하는 등의 작업을 할 수 있습니다.
content
contentLoaded
will be called after loadContent
is done. The return value of loadContent()
will be passed to contentLoaded
as content
.
actions
actions
contain three functions:
addRoute(config: RouteConfig): void
웹 사이트에 추가할 경로를 만듭니다.
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 또는 문자열)를 생성하기 위한 선언적 콜백입니다. 파일 이름과 저장할 데이터를 가져와서 실제 데이터 파일 경로를 반환합니다.
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 data becomes accessible to your client-side/theme code through the useGlobalData
and usePluginData
hooks.
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.
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;
// friends 전역 데이터 생성
setGlobalData({friends: ['Yangshun', 'Sebastien']});
// '/friends' 경로 추가
addRoute({
path: '/friends',
component: '@site/src/components/Friends.js',
exact: true,
});
},
};
}
configureWebpack(config, isServer, utils, content)
내부 웹팩 설정을 수정합니다. 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.
The API of configureWebpack
will be modified in the future to accept an object (configureWebpack({config, isServer, utils, content})
)
config
configureWebpack
is called with config
generated according to client/server build. 전달된 config를 기본으로 적절하게 다른 설정과 합치는 작업을 진행할 수 있습니다.
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
also receives an util object:
getStyleLoaders(isServer: boolean, cssOptions: {[key: string]: any}): Loader[]
getJSLoader(isServer: boolean, cacheOptions?: {}): Loader | null
조건에 따라 웹팩 설정을 받기 위해 사용할 수 있습니다.
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
will be called both with the content loaded by the plugin.
Merge strategy
We merge the Webpack configuration parts of plugins into the global Webpack config using webpack-merge.
이때 합치기 전략을 설정할 수 있습니다. 예를 들어 웹팩에 적용할 규칙을 뒤에 추가하는 대신 앞에 삽입할 수 있습니다.
export default function (context, options) {
return {
name: 'custom-docusaurus-plugin',
configureWebpack(config, isServer, utils) {
return {
mergeStrategy: {'module.rules': 'prepend'},
module: {rules: [myRuleToPrepend]},
};
},
};
}
Read the webpack-merge strategy doc for more details.
Configuring dev server
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)
Modifies postcssOptions
of postcss-loader
during the generation of the client bundle.
Should return the mutated postcssOptions
.
By default, postcssOptions
looks like this:
const postcssOptions = {
ident: 'postcss',
plugins: [require('autoprefixer')],
};
예:
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)
(제품) 빌드가 완료되면 호출됩니다.
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;
}
예:
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})
도큐사우루스에서 생성한 HTML에 head, body HTML 태그를 추가합니다.
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;
};
예:
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>`],
};
},
};
}
아래 위치에 태그가 삽입됩니다.
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()
Returns an array of paths to the client modules that are to be imported into the client bundle.
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];
},
};
}