메인 컨텐츠로 이동
Version: 2.0.0-beta.10 🚧

Lifecycle API

caution

Lifecycle API는 아직 개발 진행중입니다.

Lifecycle API는 테마와 플러그인에서 사용됩니다.

validateOptions({options, validate})

플러그인에서 사용할 수 있도록 유효성을 검사하고 정규화된 옵션값을 반환합니다. 플러그인이 초기화되기 전에 메소드가 호출됩니다. 반환된 옵션값은 플러그인 초기화를 위해 전달되므로 반드시 옵션값을 반환해주어야 합니다.

options

validateOptions은 플러그인에 전달할 options 항목의 유효성을 검사하고 정규화합니다.

validate

validateOptionsvalidate 함수에 Joi 스키마와 options 항목을 인자로 전달해서 유효성을 검사하고 정규화된 옵션값을 반환받습니다. validate 함수에서는 자동으로 에러와 유효성 검사에 필요한 설정을 처리합니다.

tip

Joi는 옵션값에 대한 유효성 검사와 정규화 처리에 적절한 기능을 지원합니다.

적절한 Joi 버전을 사용하기 위해 const {Joi} = require("@docusaurus/utils-validation")를 적용하세요.

유효성 검사에 Joi를 사용하지 않는다면 코드 내에서 잘못된 옵션의 경우 에러를 던지고 성공한 경우 옵션값을 반환해야 합니다.

my-plugin/src/index.js
module.exports = function (context, options) {
return {
name: 'docusaurus-plugin',
// rest of methods
};
};

module.exports.validateOptions = ({options, validate}) => {
const validatedOptions = validate(myValidationSchema, options);
return validationOptions;
};

ES 모듈을 사용해 export 구문을 사용할 수도 있습니다.

my-plugin/src/index.ts
export default function (context, options) {
return {
name: 'docusaurus-plugin',
// rest of methods
};
}

export function validateOptions({options, validate}) {
const validatedOptions = validate(myValidationSchema, options);
return validationOptions;
}

validateThemeConfig({themeConfig, validate})

테마에서 사용할 수 있도록 유효성을 검사하고 정규화된 설정값을 반환합니다.

themeConfig

validateThemeConfigdocusaurus.config.js에서 사용할 themeConfig 항목의 유효성을 검사하고 정규화합니다.

validate

validateThemeConfigvalidate 함수에 Joi 스키마와 themeConfig 항목을 인자로 전달해서 유효성을 검사하고 정규화된 옵션값을 반환받습니다. validate 함수에서는 자동으로 에러와 유효성 검사에 필요한 설정을 처리합니다.

tip

Joi는 테마 설정값에 대한 유효성 검사와 정규화 처리에 적절한 기능을 지원합니다.

적절한 Joi 버전을 사용하기 위해 const {Joi} = require("@docusaurus/utils-validation")를 적용하세요.

유효성 검사에 Joi를 사용하지 않는다면 코드 내에서 잘못된 옵션의 경우 에러를 던져야 합니다.

my-theme/src/index.js
module.exports = function (context, options) {
return {
name: 'docusaurus-plugin',
// rest of methods
};
};

module.exports.validateThemeConfig = ({themeConfig, validate}) => {
const validatedThemeConfig = validate(myValidationSchema, options);
return validatedThemeConfig;
};

ES 모듈을 사용해 export 구문을 사용할 수도 있습니다.

my-theme/src/index.ts
export default function (context, options) {
return {
name: 'docusaurus-plugin',
// rest of methods
};
}

export function validateThemeConfig({themeConfig, validate}) {
const validatedThemeConfig = validate(myValidationSchema, options);
return validatedThemeConfig;
}

getPathsToWatch()

플러그인과 테마 변경을 체크하기 위한 경로를 설정합니다. 설정된 경로는 개발 서버에서 지켜보고 있다가 내용 변경이 생기면 플러그인 수명주기가 다시 로드됩니다. 초기 설정된 플러그인과 테마 모듈은 노드 상에서 contextoptions를 사용해 접근할 수 있습니다. 이를 통해 필요한 디렉터리 정보를 얻을 수 있습니다.

예를 들면 아래와 같이 설정합니다.

docusaurus-plugin/src/index.js
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()

플러그인이 데이터 소스(파일, 원격 API, 헤드리스 CMS 등) 또는 서버 측 프로세스에서 무언가를 가져올 때 사용합니다.

예를 들어 아래 코드에서는 1부터 10 사이의 무작위 숫자를 콘텐츠로 가져옵니다.

docusaurus-plugin/src/index.js
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})

플러그인은 loadContent에서 가져온 데이터를 사용할 수 있습니다. 필요에 따라 데이터를 사용해 페이지나 경로를 구성할 수 있습니다.

content

loadContent이 처리된 후에 contentLoaded을 호출합니다. loadContent() 실행 후 반환된 값은 contentLoaded 실행 시 content 인자로 전달됩니다.

actions

actions은 세 가지 함수를 포함하고 있습니다.

addRoute(config: RouteConfig): void

웹 사이트에 추가할 경로를 만듭니다.

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>

경로에 속성으로 제공할 수 있는 정적인 데이터(보통 JSON 또는 문자열) 만들기를 지원하는 함수입니다.

예를 들어 아래 코드에서 플러그인은 Your friends are: Yangshun, Sebastien라는 문자열을 보여주는 /friends 페이지를 만듭니다.

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

export default function FriendsComponent({friends}) {
return <div>Your friends are {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;
// friends.json 파일을 만듭니다.
const friends = ['Yangshun', 'Sebastien'];
const friendsJsonPath = await createData(
'friends.json',
JSON.stringify(friends),
);

// '/friends' 경로를 추가하고 friends 속성을 받을 수 있게 합니다.
addRoute({
path: '/friends',
component: '@site/src/components/Friends.js',
modules: {
// propName -> JSON 파일 경로
friends: friendsJsonPath,
},
exact: true,
});
},
};
}

setGlobalData(data: any): void

다른 플러그인에서 만든 페이지를 포함한 다른 페이지나 테마 레이아웃에서 읽을 수 있는 전역 플러그인 데이터 만들기를 지원합니다.

만들어진 데이터는 클라이언트/테마 코드에서 useGlobalDatausePluginData을 통해 접근할 수 있습니다.

또한 전역 데이터 hooks API를 통해 접근할 수도 있습니다.

caution

전역 데이터는 말 그대로 전역적인 특성을 가집니다. 여러분의 사이트 모든 페이지 로딩 시간에 영향을 미칠 수 있으므로 작은 크기로 유지하기를 권장합니다.

가능하면 createData를 활용하거나 각 페이지 데이터를 사용하세요.

예를 들어 아래 코드에서 플러그인은 Your friends are: Yangshun, Sebastien라는 문자열을 보여주는 /friends 페이지를 만듭니다.

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>Your friends are {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;
// friends 전역 데이터를 만듭니다.
setGlobalData({friends: ['Yangshun', 'Sebastien']});

// '/friends' 경로를 추가합니다.
addRoute({
path: '/friends',
component: '@site/src/components/Friends.js',
exact: true,
});
},
};
}

configureWebpack(config, isServer, utils, content)

내부 웹팩 설정을 수정합니다. 반환되는 값이 자바스크립트 오브젝트라면 webpack-merge를 사용해 마지막 설정과 합쳐집니다. 반환되는 값이 함수인 경우에는 config를 첫 번째 인자, isServer를 다른 인자로 함수를 호출합니다.

caution

configureWebpack API는 조만간 (configureWebpack({config, isServer, utils, content})) 오브젝트 형태로 수정될 겁니다.

config

configureWebpack은 클라이언트/서버 빌드 시 만들어지는 config를 사용합니다. 전달된 config를 기본으로 적절하게 다른 설정과 합치는 작업을 진행할 수 있습니다.

isServer

configureWebpack은 서버와 클라이언트 빌드 시 호출됩니다. 서버 빌드 시에는 true값을 받고 클라이언트 빌드 시에는 false 값을 받아 isServer 인자값으로 사용합니다.

utils

configureWebpack은 util 오브젝트를 인자로 받을 수 있습니다.

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

조건에 따라 웹팩 설정을 받기 위해 사용할 수 있습니다.

예를 들어 아래 코드에서는 웹팩 설정 파일을 .foo 파일로 변환하도록 설정을 수정했습니다.

docusaurus-plugin/src/index.js
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'],
},
],
},
};
},
};
};

content

configureWebpack은 플러그인에 의해 로딩된 콘텐츠를 모두 호출할 수 있습니다.

합치기 전략

webpack-merge를 사용해 플러그인의 웹팩 설정을 전역 웹팩 설정과 합칠 수 있습니다.

이때 합치기 전략을 설정할 수 있습니다. 예를 들어 웹팩에 적용할 규칙을 뒤에 추가하는 대신 앞에 삽입할 수 있습니다.

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]},
};
},
};
};

좀 더 자세한 내용은 웹팩 합치기 전략 가이드 문서를 참고하세요.

configurePostCss(options)

클라이언트 번들 생성 시 postcss-loaderpostcssOptions을 수정합니다.

변경된 postcssOptions 값을 반환해야 합니다.

기본적으로 postcssOptions는 아래와 같은 형식입니다.

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

예를 들면 아래와 같이 설정합니다.

docusaurus-plugin/src/index.js
module.exports = function (context, options) {
return {
name: 'docusaurus-plugin',
configurePostCss(postcssOptions) {
// 새로운 PostCSS 플러그인을 추가합니다.
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>[];
}

예를 들면 아래와 같이 설정합니다.

docusaurus-plugin/src/index.js
module.exports = function (context, options) {
return {
name: 'docusaurus-plugin',
async postBuild({siteConfig = {}, routesPaths = [], outDir}) {
// 모든 처리 경로를 콘솔에 출력합니다.
routesPaths.map((route) => {
console.log(route);
});
},
};
};

extendCli(cli)

도큐사우루스의 명령행 인터페이스를 확장하기 위한 추가 명령어를 등록합니다. clicommander 오브젝트입니다.

예를 들면 아래와 같이 설정합니다.

docusaurus-plugin/src/index.js
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({content})

도큐사우루스에서 생성한 HTML에 head, body HTML 태그를 추가합니다.

injectHtmlTags는 플러그인에 의해 로딩된 콘텐츠를 모두 호출할 수 있습니다.

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

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

interface HtmlTagObject {
/**
* HTML 태그 속성
* 예 `{'disabled': true, 'value': 'demo', 'rel': 'preconnect'}`
*/
attributes?: {
[attributeName: string]: string | boolean;
};
/**
* 태그 이름. `div`, `script`, `link`, `meta`
*/
tagName: string;
/**
* The inner HTML
*/
innerHTML?: string;
}

예를 들면 아래와 같이 설정합니다.

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> This is post body </div>`],
};
},
};
};

getThemePath()

테마 컴포넌트를 찾을 수 있는 디렉터리 경로를 반환합니다. 사용자가 swizzle을 호출하면 getThemePath가 호출되면서 테마 컴포넌트를 찾을 수 있는 경로를 반환합니다.

getThemePath 코드는 아래와 같이 설정할 수 있습니다.

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

module.exports = function (context, options) {
return {
name: 'name-of-my-theme',
getThemePath() {
return path.resolve(__dirname, './theme');
},
};
};

getTypeScriptThemePath()

getThemePath()와 비슷하게 타입스크립트 테마 컴포넌트 소스 코드를 찾을 수 있는 디렉터리 경로를 반환합니다. 해당 경로에 있는 테마 컴포넌트는 웹팩에서는 확인할 수 없습니다. 그래서 getThemePath() 기능을 대체하는 것은 아닙니다. 반환되는 경로는 타입스크립트 테마 컴포넌트를 바꾸기 위한 용도로 사용합니다.

타입스크립트 컴포넌트를 여러분의 테마로 바꾸려면 getTypeScriptThemePath()에서 반환된 경로를 소스 디렉터리로 설정하고 getThemePath()에서 반환된 경로를 컴파일된 자바스크립트 출력 경로로 설정합니다.

예를 들면 아래와 같이 설정합니다.

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

module.exports = function (context, options) {
return {
name: 'name-of-my-theme',
getThemePath() {
// 컴파일된 자바스크립트 출력 경로
return path.join(__dirname, '..', 'lib', 'theme');
},
getTypeScriptThemePath() {
// 타입스크립트 소스 코드 경로
return path.resolve(__dirname, './theme');
},
};
};

getSwizzleComponentList()

안전하게 바꾸기를 처리할 수 있는 안정적인 컴포넌트 목록을 반환합니다. 해당 컴포넌트는 --danger 옵션을 사용하지 않고 컴포넌트 swizzle을 처리할 수 있습니다. 기본적으로 모든 컴포넌트는 안정적이지 않는 것으로 여깁니다. 빈 배열값을 반환하는 경우에는 모든 컴포넌트가 안정적이지 않은 상태입니다. undefined를 반환하는 경우에는 모든 컴포넌트가 안정적인 상태로 간주합니다.

my-theme/src/index.js
const swizzleAllowedComponents = [
'CodeBlock',
'DocSidebar',
'Footer',
'NotFound',
'SearchBar',
'hooks/useTheme',
'prism-include-languages',
];

module.exports.getSwizzleComponentList = () => swizzleAllowedComponents;

getClientModules()

클라이언트 번들에서 가져올 모듈들의 경로 배열값을 반환합니다. 리액트에서 초기 UI를 렌더링 처리하기 전에 전역으로 모듈을 가져옵니다.

예를 들어 인자로 전달받은 options에서 customCss 또는 customJs 파일 경로를 반환받아 테마에서 로드하게 하려면 아래와 같이 작성할 수 있습니다.

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];
},
};
};

i18n 수명 주기

getTranslationFiles({content})

플러그인에서 사용할 JSON 번역 파일을 설정합니다.

{path: string, content: ChromeI18nJSON}: 형태로 번역 파일을 반환합니다.

  • Path: i18n/<locale>/pluginName 형식으로 로케일 디렉터리의 상대 경로를 설정합니다. .json 확장자는 필요하지 않습니다.
  • Content: 크롬 i18n JSON 형식을 사용합니다.

파일은 write-translations 명령행 인터페이스에 의해 플러그인 i18n 하위 디렉터리에 작성되며 translateContent()translateThemeConfig()를 호출하기 전에 적절한 로케일에서 읽습니다.

예를 들면 아래와 같이 설정합니다.

module.exports = function (context, options) {
return {
name: 'my-plugin',
async getTranslationFiles({content}) {
return [
{
path: 'sidebar-labels',
content: {
someSidebarLabel: {
message: 'Some Sidebar Label',
description: 'A label used in my plugin in the sidebar',
},
someLabelFromContent: content.myLabel,
},
},
];
},
};
};

translateContent({content,translationFiles})

번역 파일을 사용해 플러그인 콘텐츠를 번역합니다.

로케일에 해당하는 플러그인 콘텐츠를 반환합니다.

contentLoaded()translateContent()에서 반환하는 로케일에 해당하는 플러그인 콘텐츠를 인자로 호출됩니다.

예를 들면 아래와 같이 설정합니다.

module.exports = function (context, options) {
return {
name: 'my-plugin',
translateContent({content, translationFiles}) {
const myTranslationFile = translationFiles.find(
(f) => f.path === 'myTranslationFile',
);
return {
...content,
someContentLabel: myTranslationFile.someContentLabel.message,
};
},
};
};

translateThemeConfig({themeConfig,translationFiles})

로케일에 해당하는 번역 파일을 사용해 사이트의 themeConfig 문자열을 번역합니다.

로케일에 해당하는 themeConfig을 반환합니다.

예를 들면 아래와 같이 설정합니다.

module.exports = function (context, options) {
return {
name: 'my-theme',
translateThemeConfig({themeConfig, translationFiles}) {
const myTranslationFile = translationFiles.find(
(f) => f.path === 'myTranslationFile',
);
return {
...themeConfig,
someThemeConfigLabel: myTranslationFile.someThemeConfigLabel.message,
};
},
};
};

async getDefaultCodeTranslationMessages()

<Translate> API를 사용하는 테마는 기본 코드 번역 메시지를 제공할 수 있습니다.

Record<string,string>에 메시지를 반환해주어야 합니다. key는 번역 id값이고 values는 현재 로케일에 해당하는 메시지(설명은 없는)입니다.

예를 들면 아래와 같이 설정합니다.

module.exports = function (context, options) {
return {
name: 'my-theme',
async getDefaultCodeTranslationMessages() {
return readJsonFile(`${context.i18n.currentLocale}.json`);
},
};
};

아래 코드는 모든 기능을 사용한 플러그인 구현을 위한 컨셉 예제입니다.

const DEFAULT_OPTIONS = {
// 기본값을 정의합니다.
};

// 오브젝트를 반환하는 자바스크립트 함수입니다.
// `context`는 도큐사우루스에서 제공합니다. 예: siteConfig는 context에서 접근할 수 있습니다.
// `opts`는 사용자 지정 옵션입니다.
module.exports = function (context, opts) {
// 사용자 지정 옵션과 기본 옵션을 합칩니다.
const options = {...DEFAULT_OPTIONS, ...options};

return {
// 각 플러그인의 중간 캐시 데이터를 처리하기 위한
// 디렉터리의 네임스페이스로 사용하는 필수 항목입니다.
// 여러분이 사용하는 로컬 플러그인이 다른 플러그인과 충돌하지 않도록
// 유일한 값이 필요할 때 사용합니다.
// 가장 좋은 방법은 프로젝트 이름을 앞에 붙이는 것입니다.
name: 'docusaurus-my-project-cool-plugin',

async loadContent() {
// loadContent Hook는 siteConfig와 env가 로드된 이후에 처리됩니다.
// contentLoaded Hook의 인자로 사용할 자바스크립트 오브젝트를 반환할 수 있습니다.
},

async contentLoaded({content, actions}) {
// contentLoaded Hook는 loadContent Hook가 처리된 이후에 동작합니다.
// `actions`은 도큐사우루스에서 제공하는 API입니다(예. addRoute)
},

async postBuild(props) {
// 도큐사우루스 <build> 다음 동작을 설정합니다.
},

// TODO
async postStart(props) {
// docusaurus <start> finish
},

// TODO
afterDevServer(app, server) {
// https://webpack.js.org/configuration/dev-server/#devserverbefore
},

// TODO
beforeDevServer(app, server) {
// https://webpack.js.org/configuration/dev-server/#devserverafter
},

configureWebpack(config, isServer, utils, content) {
// 내부 웹팩 설정을 수정합니다. 반환되는 값이 오브젝트라면
// webpack-merge를 사용해 마지막 설정과 합쳐집니다.
// 반환되는 값이 함수라면 config를 첫 번째 인자로 isServer 항목을 두 번째 인자로 전달합니다.
},

getPathsToWatch() {
// 변경을 체크할 경로를 설정합니다.
},

getThemePath() {
// 테마 컴포넌트를 찾을 수 있는 디렉터리 경로를
// 반환합니다.
},

getClientModules() {
// 클라이언트 번들로 가져올 모듈 배열을
// 반환합니다. 리액트에서 초기 UI를 렌저링 처리하기 전에
// 전역으로 모듈을 가져옵니다.
},

extendCli(cli) {
// 도큐사우루스 명령행 인터페이스를 확장할 수 있는 추가 명령을 등록합니다.
},

injectHtmlTags({content}) {
// HTML 태그에 head, body 태그를 삽입합니다.
},

async getTranslationFiles({content}) {
// 번역 파일을 반환합니다.
},

translateContent({content, translationFiles}) {
// 플러그인 콘텐츠를 번역합니다.
},

translateThemeConfig({themeConfig, translationFiles}) {
// 사이트 themeConfig를 번역합니다.
},

async getDefaultCodeTranslationMessages() {
// 기본 테마 번역을 반환합니다.
},
};
};