Gridsome으로 매달 아카이브 기능을 제작합니다.

26093 단어 JamstackGridsometech
원래내 블로그까지 투고하려 했으나 젠은Gridsome 투고가 하나도 없어 절망해 젠에 쓰기로 했다.
(Gridsome에 대한 무한 대략적인 설명은 정적 사이트인 Generater Gatsby의 Vue 버전이다. 자신의 블로그도 Gridsome이 제작했다.)
그나저나 저는 Vue와 React를 거의 접해 본 적이 없는 전단 초보자입니다.

이루고 싶은 일.


Gridsome에서 매달 아카이브 기능을 만듭니다.
이것은 블로그에 자주 있는 물건이다.

파일의 URL은
https://retrorocket.biz/archives/date/2020/10
이렇게 하면 /archives/date/{Year}/{Month} 열람할 수 있다.

작업 확인 환경


$ gridsome info
  System:
    OS: Linux 4.19 Ubuntu 20.04.1 LTS (Focal Fossa)
  Binaries:
    Node: 12.18.3 - /usr/local/bin/node
    Yarn: 1.22.5 - /usr/local/bin/yarn
    npm: 6.14.8 - /usr/local/bin/npm
  npmPackages:
    gridsome: ^0.7.21 => 0.7.21 
  npmGlobalPackages:
    @gridsome/cli: 0.3.4
GraphiQL의 조회에서 사용allBlogPost을 전제로 대화를 진행하고, 사용allWordpressPost 등이 있으면 적당히 다시 읽어주세요.

할 일

  • 월별 아카이브를 /archives/date/{Year}/{Month} 열람하기 위해 Pages API를 사용하여 독립 페이지
  • 만들기
  • 사이드바에서component를 만들어서 매달 압축 파일 목록을 표시합니다
  • 월별 아카이브 개별 페이지 만들기


    Pages APIcreatePages를 사용하여 특정 경로에서 사용되는 데이터와 템플릿을 직접 편집할 수 있습니다.
    이번에는 아래의 절차에 따라 개별 페이지를 만들었다.
  • GraphiQL의allBlogPost에서 전체 투고에서 투고년과 투고월만 취득하고 createPages연월에 맞는 페이지를 제작
  • template에서GraphiQL의filter를 사용하여 이전 프로젝트에서 얻은 연과 월에 해당하는 투고를 일람합니다
    실장할 때 아주 참고했어Gatsby.js에 연간 글 목록 표시하기 - Qita.감사합니다.
  • gridsome.server.js


    // gridsome.server.js
    module.exports = api => {
      api.createPages(async ({ graphql, createPage }) => {
        // GraphQLで全投稿を検索
        // 投稿年と投稿月だけ取得する
        const { data } = await graphql(`{
          allBlogPost {
            edges {
              node {
                year: date(format: "YYYY")
                month: date(format: "YYYY,MM")
              }
            }
          }
        }`)
    
        const years = new Set();
        const yearMonths = new Set();
    
        // 全投稿から取得した投稿年と投稿月の重複を削除
        data.allBlogPost.edges.forEach(({ node }) => {
          years.add(node.year);
          yearMonths.add(node.month);
        });
    
        // 年ページの作成
        years.forEach(year => {
          createPage({
            path: `/archives/date/${year}`,
            component: "./src/templates/Years.vue",
            context: {
              displayYear: year,
    	  // template内で投稿年の1/1から12/31までの記事一覧を取得するために、年末の日時を呼び出せるようにする
              periodStartDate: `${year}-01-01T00:00:00.000Z`,
              periodEndDate: `${year}-12-31T23:59:59.999Z`
            }
          });
        });
    
        // 月ページの作成
        yearMonths.forEach(yearMonthStr => {
          const yearMonth = yearMonthStr.split(",");
          // 指定した月の末日を取得
          const date = new Date(yearMonth[0], yearMonth[1], 0);
          const year = date.getFullYear();
          const month = ("00" + (date.getMonth() + 1)).slice(-2);
          const day = ("00" + date.getDate()).slice(-2);
          createPage({
            path: `/archives/date/${yearMonth[0]}/${yearMonth[1]}`,
            component: "./src/templates/Years.vue",
            context: {
              displayYear: `${yearMonth[0]}/${yearMonth[1]}`,
    	  // template内で投稿月の1日から月末までの記事一覧を取得するために、月末の日時を呼び出せるようにする
              periodStartDate: `${year}-${month}-01T00:00:00.000Z`,
              periodEndDate: `${year}-${month}-${day}T23:59:59.999Z`
            }
          });
        });
    
      })
    }
    

    template

    api.createPages에 설정된)periodStartDateperiodEndDate 범위 내의 글 목록에서 출력합니다.
    <!-- ./src/templates/Years.vue -->
    <template>
      <Layout>
        <div>
          <h1 class="entry-title" itemprop="headline">
            {{ $context.displayYear }}
          </h1>
    
          <ul>
            <li v-for="{ node } in $page.years.edges" :key="node.id">
              <g-link :to="node.path">
                <span v-html="node.title" />
              </g-link>
              {{ node.date }}
            </li>
          </ul>
        </div>
      </Layout>
    </template>
    
    <!-- periodStartDateとperiodEndDateの範囲内にある記事を検索する -->
    <page-query>
    query PostsByDate($periodStartDate: Date, $periodEndDate: Date) {
      years: allBlogPost(filter: {date: {between: [$periodStartDate, $periodEndDate]} }) {
        edges {
          node {
            id
            title
            path
            date(format: "YYYY/MM/DD")
          }
        }
      }
    }
    </page-query>
    
    그러면 방문/archives/date/{Year}/{Month}하면 해당 글의 일람표를 표시할 수 있습니다.

    매달 파일 일람용component 만들기


    상당히 풍자적인 실상이지만 아래 절차에 따라 조립품을 제작했다.
  • allBlogPost 전체 투고에서 투고년과 투고월만 취득
  • 기고년을 표시하기 위해 v-for 내에 Set을 사용하여 중복된 기고년을 삭제하고 순환
  • 투고월을 표시하기 위해 filter(GraphiQL의 Filter가 아닌 Array.prototype.filter()의 방법으로 투고년과 대응하는 달을 축소
  • <template>
      <div>
        <div
          v-for="(year, yindex) in new Set(
            $static.years.edges.map((e) => e.node.year)
          )"
          :key="`y-${yindex}`"
        >
          <h6>
            » {{ year }}
          </h6>
          <div>
            <g-link
              v-for="(month, mindex) in new Set(
                $static.years.edges
                  .map((e) => e.node.month)
                  .filter((e) => e.indexOf(year) === 0)
                  .reverse()
              )"
              :key="`m-${mindex}`"
              :to="`/archives/date/${month}`"
              >{{ month.slice(-2) }}</g-link
            >
            <g-link
              :to="`/archives/date/${year}`"
              >all</g-link
            >
          </div>
        </div>
      </div>
    </template>
    
    <static-query>
    query {
      years: allBlogPost(sortBy: "published_at", order: ASC) {
        edges { 
          node { 
            year: date(format: "YYYY")
            month: date(format: "YYYY/MM")
          }
        }
      }
    }
    </static-query>
    
    이렇게 하면 사이드바에 매달 압축 파일 일람표를 표시할 수 있다.
    원래는 자신의 블로그에서 받은 질문에 대한 답변으로 쓴 기사인데 잘못되면 지적해주세요.

    좋은 웹페이지 즐겨찾기