作成日:2022-08-10 ・更新日:2023-02-01
gatsby-starter-blogをいじってみてmarkdownの理解を深める。ために頑張ってみた奮闘記です。参考になるものはあまりないと思う。
markdownを理解する。
gatsby-starter-blogをいじってgatsbyのmarkdownとは何だ?
markdownを実装するにはどうすれば良いのか?
を理解するために戦った傷跡です。参考にはならないと思いますが...
markdown解説はこちらを確認ください。
markdown実装と言いたいがとりあえず理解していないと実装できないので、サンプルソース今回確認することにした。
このテンプレを使って始めてみました。
公式ページからダウンロード してみる
npx gatsby new gatsby-starter-blog https://github.com/gatsbyjs/gatsby-starter-blog
githubソースコードを見てみました。 ソースで必要な部分を一部抜粋しました。
const path = require(`path`)
const { createFilePath } = require(`gatsby-source-filesystem`)
exports.createPages = async ({ graphql, actions, reporter }) => {
const { createPage } = actions
const result = await graphql(
`
{
allMarkdownRemark(
sort: { fields: [frontmatter___date], order: ASC }
limit: 1000
) {
nodes {
id
fields {
slug
}
}
}
}
`
)
const posts = result.data.allMarkdownRemark.edges
if (posts.length > 0) {
posts.forEach((post, index) => {
const previousPostId = index === 0 ? null : posts[index - 1].id
const nextPostId = index === posts.length - 1 ? null : posts[index + 1].id
createPage({
path: post.fields.slug,
component: blogPost,
context: {
id: post.id,
previousPostId,
nextPostId,
},
})
})
}
}
分かったことは、 graphqlとはいうものを使っているらしい。 graphqlの登録、参照については ここの解説がとても参考になりました。ありがとうございます。
重要なのはgatsby-source-filesystemのプラグインであることが判明 http://localhost:8000/___graphql で確認するといいらしい。
まずはgatsby-config.jsを確認してみる。
{
resolve: `gatsby-source-filesystem`,
options: {
path: `${__dirname}/content/blog`,
name: `blog`,
},
},
よくわからないがこれでcontent/blogの中を登録しているようだ。
確認をするにはdevelopで起動させてhttp://localhost:8000/___graphqlにアクセスしたら確認ができる。
gatsby develop
試しにcomponentsを追加してテストする
plugins: [
`gatsby-plugin-image`,
{
resolve: `gatsby-source-filesystem`,
options: {
path: `${__dirname}/content/blog`,
name: `blog`,
},
},
/**これを追加した**/
{
resolve: `gatsby-source-filesystem`,
options: {
path: `${__dirname}/src/components`,
name: `components`,
},
},
/**ここまで追加した**/
そして同様にabsolutePathを確認するとcomponetsの中身も追加あれていることが分かった。 graphqlで値を取得できるところまで確認ができた。
gatsby-transformer-remarkのプラグインを使うとできるみたいだが、mdはgraphqlを使用している。そのためgraphqlで取得できていないファイルはmarkdownで記事を作成できない。
とりあえずプラグインを追加する。
resolve: "gatsby-transformer-remark",
このプラグインはgatsby-source-filesystemdで登録した、フォルダー内のmdファイルを自動で検知して、読み込んでくれる。そのためgraphqlで取得できている。尚且つmdファイルである場合mdを実装できる。
テストをしてみる。先ほどcomponentsを追加したのでその中にtest.mdを追加してみた。内容は適当に記入する。
またgatsby developを実行して確認してみる
query MyQuery {
allMarkdownRemark {
nodes {
fileAbsolutePath
}
}
}
正常にtext.mdが追加されたことが確認できた。
ページが追加されていることも確認ができる
mdファイルが読み込まれることが分かったので当ページにも追加してみたがページが増えなかった。 ここでページを作成しているのは実はgatsby-node.jsであることがここで判明する。 createPage({})があって、これがページが作成している。
if (posts.length > 0) {
posts.forEach((post, index) => {
const previousPostId = index === 0 ? null : posts[index - 1].id
const nextPostId = index === posts.length - 1 ? null : posts[index + 1].id
createPage({
path: post.fields.slug,
component: blogPost,
context: {
id: post.id,
previousPostId,
nextPostId,
},
})
})
}
それではこのposts.forEachとは何かとさかのぼると、最終的にこれの事でした。
console.logを入れてgatsby developを実行してみる
const result = await graphql(
`
{
allMarkdownRemark(
sort: { fields: [frontmatter___date], order: ASC }
limit: 1000
) {
nodes {
id
fields {
slug
}
}
}
}
`
)
//省略
const posts = result.data.allMarkdownRemark.nodes;
gatsby developを実行してみると以下のようなログが表示される。
いやいや「data.allMarkdownRemark.nodes」ってどこからきた?
じつはこれはhttp://localhost:8000/___graphqlと同様な事を行っている。
graphqlで同じコードを実行してみると
query MyQuery {
allMarkdownRemark(
sort: { fields: [frontmatter___date], order: ASC }
limit: 1000
) {
nodes {
id
fields {
slug
}
}
}
}
以下の結果が返って来る
{
"data": {
"allMarkdownRemark": {
"nodes": [
{
"id": "7cdce3cf-71fc-573b-bb84-03526189160f",
"fields": {
"slug": "/hello-world/"
}
},
{
"id": "f5858bf6-a8f4-5d7e-9bf6-78faa3b44d1d",
"fields": {
"slug": "/my-second-post/"
}
},
{
"id": "eac236df-9f92-5e44-ad6e-0240b0f2e9ff",
"fields": {
"slug": "/new-beginnings/"
}
},
{
"id": "0ac780b5-e106-53fb-b828-41553a44205b",
"fields": {
"slug": "/test/"
}
}
]
}
},
"extensions": {}
}
つまりposts.forEachのpostsはnodes:[{ "id": "7..."}...省略]であることが分かった。
ここまでを整理すると
createPageの公式ページを確認してみる。 簡潔に
createPageまでは理解できた、あとはblog-post.jsだけだ。 一部抜粋
const BlogPostTemplate = ({
data: { previous, next, site, markdownRemark: post },
location,
}) => {
//省略
//26行目
<section
dangerouslySetInnerHTML={{ __html: post.html }}
itemProp="articleBody"
/>
//省略
}
//75行目
export const pageQuery = graphql`
query BlogPostBySlug(
$id: String!
$previousPostId: String
$nextPostId: String
) {
markdownRemark(id: { eq: $id }) {
id
excerpt(pruneLength: 160)
html
}
}
`
コードを確認するとmdからhtmlのパースはされている用で、dangerouslySetInnerHTML={{ __html: post.html }}
でページに反映できるよう。
export const pageQuery = graphql
を使用してる
正直このpageQueryでかなり躓いてgatsbyを投げ出したくなった。
pageQueryで理解できなかったこと。
必要だった。これを記述しないとmdで記入したものをページに反映できない。 ただの空のページが作成されてしまう。
gatsbyを使用する上でgraphqlを理解しないとやっていけない登録は置いといてせめて、読み込みを理解しないといけない。http://localhost:8000/___graphql で値は確認できるので使いこなさないと今後厳しい
export const pageQuery = graphql
をすることでmdの値、その他の必要な情報を全て渡すことができる。逆に言うとここで指定しないと、何も値を読み込みできない。
const BlogPostTemplate = ({
data: { previous, next, site, markdownRemark: post },
location,
})
サンプルソースでは値を細かく決めているのでとりあえず全てを取得できるようにコードを変えて、分解すると理解できるかもしれない。
const BlogPostTemplate = (props) => {
const data = props.data;
const previous = props.data.previous;
const next = props.data.next;
const site = props.data.site;
const post = props.data.markdownRemark.post;
const location = props.location;
}
idってなんで必要?
idが無いと全てのmarkdownの記事を取得するため(厳密には多少異なる)特定のmarkdownファイルをidでフィルタ―を行いmarkdown内の値を取得している。そのためidでなくても特定のmarkdownファイルを指定できるのであれば問題ない。「fileAbsolutePath」絶対パスとかを使うこともできる。
idはgatsby-node.jsで指定してblog-post.jsに渡している。
createPage({
path: post.fields.slug,
component: blogPost,
context: {
id: post.id,
previousPostId,
nextPostId,
},
})
もしくはgatsby-node.jsで渡すblog-post.jsに渡す情報を全て追加すればidは不要となる。 まぁ、結局記述内容が増えて全て渡すと管理しづらい。build時間は短縮されるのかな?id無しの方が良かったりして?
createPage({
path: post.fields.slug,
component: blogPost,
context: {
id: post.id,
previousPostId,
nextPostId,
body: html,
title: title,
date: post.frontmatter.date
},
})
markdownを実装するのに物凄く苦労しました。最終的にmarkdownでページが作成される流れは
質問や、間違いがありましたら、お気軽にどうぞ
※お名前とコメントの内容を入力してください。
※全てこのブログ上に公表されます。
※許可なく管理者によって修正・削除する場合がございます。 詳しくはプライバシーポリシーを参照ください