MDX
는 마크다운에서 컴포넌트(jsx
,tsx
등)를 허용하는 확장자다.
Gatsby
에서 mdx
파일을 쿼리로 사용하는데 필요한 플러그인을 설치한다.npm install gatsby-plugin-mdx gatsby-source-filesystem @mdx-js/react
config
파일에 gatsby-plugin-mdx
를 추가한다.import type { GatsbyConfig } from "gatsby";
const config: GatsbyConfig = {
// (...)
plugins: [
`gatsby-plugin-mdx`,
{
resolve: `gatsby-source-filesystem`,
options: {
path: `${__dirname}/blog-posts`,
},
},
],
};
export default config;
hello.mdx
파일을 생성 후 frontmatter
를 포함한 내용을 작성했다.
frontmatter
는 마크다운 파일의 메타데이터를 식별하는 방법으로, 3개짜리 하이픈(-
) 사이에 식별 내용을 적는다.
ex<!-- frontmatter --> --- title: Bla Bla ---
---
title: Hello everyone
category: personal
date: "2022-12-03"
author: JS
slug: hello-everyone
---
# Hello everyone!
Welcome to my blog post. I'm very happy to have you all here with me on this special occasion.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi consectetur magna vitae lorem posuere, ut bibendum metus condimentum. Nullam lacinia, sapien ac congue fermentum, metus dolor blandit sem, in volutpat turpis nisi ut enim. Suspendisse dignissim risus a faucibus commodo. Pellentesque pulvinar lobortis pretium. Nullam ut justo a nulla pellentesque lobortis a id quam. Vestibulum scelerisque molestie lectus, et tincidunt neque malesuada vel. Morbi turpis massa, dignissim sed libero eu, finibus laoreet eros. Aenean mi nisl, posuere ac magna quis, volutpat ultricies nisi. In id ligula vitae nibh scelerisque imperdiet. Nulla tempor eleifend elementum. Nunc at arcu at massa finibus viverra ac hendrerit quam.
Gatsby
가 제공하는 GraphQL Explorer
에 allMdx
가 생기고, 파일의 각종 정보를 찾을 수 있다.date
의 옵션 중 formatString
으로 포맷을 변경한다.# GrapQL
query MyQuery {
allMdx {
nodes {
frontmatter {
date(formatString: "MM.DD, YYYY")
}
}
}
}
# JSON
{
"data": {
"allMdx": {
"nodes": [
{
"frontmatter": {
"date": "12.03, 2022"
}
},
{
"frontmatter": {
"date": "12.03, 2022"
}
}
]
}
},
"extensions": {}
}
pruneLength
로 노출 길이를 조절할 수 있다.# GraphQL
query MyQuery {
allMdx {
nodes {
excerpt(pruneLength: 30)
}
}
}
#JSON
{
"data": {
"allMdx": {
"nodes": [
{
"excerpt": "Welcome to my blog post. I…"
},
{
"excerpt": "See you later! Lorem ipsum…"
}
]
}
},
"extensions": {}
}
export const query = graphql
로 해당 데이터를 받아온다.const Blog = ({ data }: PageProps<Queries.BlogPostsQuery>) => {
return (
<Layout title="Blog">
<section>
{data.allMdx.nodes.map((file, idx) => (
<article key={idx}>
<Link to={`/blog/${file.frontmatter?.slug}`}>
<h3>{file.frontmatter?.title}</h3>
<h5>
{file.frontmatter?.author} in: {file.frontmatter?.category}
</h5>
<h6>{file.frontmatter?.date}</h6>
<hr />
<p>{file.excerpt}</p>
</Link>
</article>
))}
</section>
</Layout>
);
};
export default Blog;
export const query = graphql`
query BlogPosts {
allMdx {
nodes {
frontmatter {
slug
title
date(formatString: "YYYY.MM.DD")
category
author
}
excerpt(pruneLength: 50)
body
}
}
}
`;
frontmatter
를 포함한 데이터를 받을 수 있다.Gatsby
가 제공하는 다이나믹 라우트로 하위 페이지 이동이 가능하다.index
로 하는 폴더를 생성하고, 중괄호({}
)로 감싼 이름을 가진 파일을 생성한다./blog
├─ index.tsx
└─ {mdx.frontmatter__slug}.tsx
frontmatter
에 담긴 slug
로 하위 경로를 설정했다.{mdx.frontmatter__slug}
는 mdx 파일의 frontmatter 중 slug를 파일명으로 삼아라를 의미한다.slug
를 통해 가져온 데이터는 다음과 같다.slug
로 검색하는 문법으로 작성한다.// blog/{mdx.frontmatter__slug}.tsx
export default function BlogPost({ data, children }: PageProps<Queries.PostDetailQuery>) {
return (
<Layout title={`${data.mdx?.frontmatter?.title}`}>
<div>{children}</div>
</Layout>
);
}
export const query = graphql`
query PostDetail($frontmatter__slug: String) {
mdx(frontmatter: { slug: { eq: $frontmatter__slug } }) {
frontmatter {
author
category
date
slug
title
}
}
}
`;
$
문자와 합쳐 쿼리에 전달한다.children
으로 mdx
의 body
를 적용할 수 있다.mdx
파일 내에 작성한 컴포넌트도 자동으로 파싱되어 출력된다.// temp.tsx
import React from "react";
export default function Temp() {
const [change, setChange] = React.useState(false);
const onChangeClick = () => setChange((prev) => !prev);
return (
<div>
<h3>{change ? "That" : "This"} Temp Page</h3>
<button onClick={onChangeClick}>
Change {change ? "That ➡ This" : "This ➡ That"}
</button>
</div>
);
}
<!-- hello.mdx -->
---
title: Hello everyone
category: personal
date: "2022-12-03"
author: JS
slug: hello-everyone
---
import Temp from "../src/components/temp";
# Hello everyone!
<Temp />
⏫컴포넌트를 렌더링한 모습⏫
결과
참고
노마드코더 - 리액트JS 마스터 클래스
gatsby-plugin-mdx
MDX docs
What is Frontmatter?