點燈坊

失くすものさえない今が強くなるチャンスよ

使用 Page 列出所有 Markdown

Sam Xiao's Avatar 2021-03-28

傳統資料都會放在 SQL 或 NoSQL,但 Blog 卻更適合使用 Markdown 以檔案形式儲存,Gridsome 提供了 Plugin 讓我們以 GraphQL 讀取 Markdown 並顯示 HTML。

Version

Gridsome 0.7.23

Markdown

markdown000

Blog 首頁列出了所有 markdown 的 titledatetag

Add Plugin

$ yarn add @gridsome/source-filesystem @gridsome/transformer-remark

使用 Yarn 安裝以上兩個 plugin,這些都是 Gridsome 官方維護的:

  • @gridsome/source-filesystem:讓 GraphQL 可以讀取本機 markdown
  • @gridsome/transformer-remark:將 markdown 轉成 HTML

由於 Gridsome 既能讀取 markdown 也能讀取 API,為了讓核心較小,因此將這些功能以 plugin 呈現, user 可依使用需求自行安裝 plugin

Gridsome Config

gridsome.config.js

module.exports = {
  siteName: 'Gridsome',
  plugins: [
    {
      use: '@gridsome/source-filesystem',
      options: {
        typeName: 'Blog',
        baseDir: './content/blog',
        path: '**/*.md',
      }
    }
  ]
}

第 3 行

plugins: [
  {
    use: '@gridsome/source-filesystem',
    options: {
      typeName: 'Blog',
      baseDir: './content/blog',
      path: '**/*.md',
    }
  }
]

設定 @gridsome/source-filesystem plugin:

  • typeName:設定 typeNameBlog
  • baseDir:設定從此目錄下開始定義
  • path: **/*.md:從 baseDir 目錄下所有 *.md 都屬於此 type

Blog 的 property 雖然稱為 typeName,但在 Gridsome 正式名稱為 Collection,GraphQL 將以 Collection 名稱定義 Type,在 templates folder 下以會以 Collection 名稱定義 component

Frontmatter

content/blog/ramda/first-post.md

---
title: First Post
date: 2020-01-08 04:04:04
tags: ['JavaScript', 'Ramda']
---
# First Post

This is `first post` content

在 Markdown 最上方以 --- 所框住的部分為 frontmatter,為 markdown 自帶的資料,可自行新增 property。

  • title:blog 的標題
  • date:blog 的日期
  • tags:blog 的 tag,可多個 tag 故為 Array

content/blog/tailwind/second-post.md

---
title: Second Post
date: 2020-02-08 04:04:04
tags: ['CSS', 'Tailwind']
---
# Second Post

This is `second post` content

content/blog 目錄下建立兩個 markdown 檔案。

重新 yarn serv 執行 dev server。

Gridsome 習慣將 markdown 放在 content 目錄下,將來將以其下目錄與檔案名稱為 route

allBlog Query

markdown001

Gridsome 根據 gridsome.config.js 所設定的 Blog type 新增了兩個 GraphQL query:

  • blog:回傳單一 blog
  • allBlog :回傳所有 blog
query {
  allBlog {
    edges {
      node {
        title
        date (format: "MMM.DD, YYYY")
        tags
        path
      }
    }
  }
}

透過 allBlog query 可取得所有 markdown 內 frontmatter 所有資料。

markdown002

Gridsome Page

pages/Blogs.vue

<template lang='pug'>
Layout
  h1 Blog List
  Article(v-for='({ node: x}, i) in $static.allBlog.edges', :key='i')
    h2 {{ x.title }}
    p Posted: {{ x.date }} 
    span(v-for='tag in x.tags', :key='tag') {{ tag }} 
    div
      g-link(:to='path') More
</template>

<static-query>
query {
  allBlog {
    edges {
      node {
        title
        date (format: "MMM.DD, YYYY")
        tags
        path
      }
    }
  }
}
</static-query>

12 行

<static-query>
query {
  allBlog {
    edges {
      node {
        title
        date (format: "MMM.DD, YYYY")
        tags
        path
      }
    }
  }
}
</static-query>

因為在 page 中,故使用 <static-query>

將 GraphQL Playground 的 allBlog query 貼過來。

第 4 行

Article(v-for='({ node: x}, i) in $static.allBlog.edges', :key='i')
  h2 {{ x.title }}
  p Posted: {{ x.date }} 
  span(v-for='tag in x.tags', :key='tag') {{ tag }} 
  div
    g-link(:to='path') More

由於 edges 為 Array,因此使用 Article 配合 v-for 將其展開,直接在 v-for 直接 destructure 出 titledatetags

由於 tags 是 Array,可再使用 v-for 展開。

Conclusion

  • 藉由 Gridsome 官方提供的 @gridsome/source-filesystem@gridsome/transformer-remark,使我們能透過 GraphQL 讀取 markdown
  • Frotmatter 亦為各 JAMStack 必備格式,Gridsome 可透過 GraphQL 加以讀取,非常方便

Reference

Reed Barger, Intro to Plugins, Source and Transformer Plugins
Reed Barger, Add Blog Page, Render Posts with Static Query
Reed Barger, Frontmatter for Blog Posts
Gridsome, @gridsome/source-filesystem
Gridsome, @gridsome/transformer-remark