Gridsome Strapi Blogのsource pluginをsource-strapiに変えてみる

7 min read読了の目安(約6800字

Strapi Starter Gridsome Blogはsource pluginに@gridsome/source-graphqlが使用されているのですが、このままだとページング(@paginate)やqueryでの日付フォーマットの変更等が使用できなかったりするので、@gridsome/source-strapiに変えてみます。

@gridsome/source-strapiのインストール

下記コマンドで@gridsome/source-strapiをインストールします。

$ yarn add @gridsome/source-strapi

gridsome.config.jsの変更

下記のようにpluginsから@gridsome/source-graphqlを削除し、@gridsome/source-strapiを追加します。

gridsome.config.js
-    {
-      use: "@gridsome/source-graphql",
-      options: {
-        url:
-          (process.env.GRIDSOME_STRAPI_URL || "http://localhost:1337") +
-          "/graphql",
-        fieldName: "strapi",
-        typeName: "strapiTypes",
-      },
-    },
+    {
+      use: '@gridsome/source-strapi',
+      options: {
+        apiURL: (process.env.GRIDSOME_STRAPI_URL || "http://localhost:1337"),
+        queryLimit: 1000,
+        contentTypes: ['article', 'category'],
+        singleTypes: ['global', 'homepage'],
+      }
+    },

strapiでCollection TypeのものはcontentTypes、Single TypeのものはsingleTypesに設定します。

gridsome.server.jsの変更

下記のようにgridsome.server.jsを変更します。

gridsome.server.js
module.exports = function (api) {
  api.createPages(async ({ graphql, createPage }) => {

    const { data } = await graphql(`{
      allStrapiArticle(filter: { status: {eq: "published"} }) {
        edges {
          node {
            id
            slug
          }
        }
      }
      allStrapiCategory {
        edges {
          node {
            id
            slug
          }
        }
      }
    }`)

    const articles = data.allStrapiArticle.edges;
    const categories = data.allStrapiCategory.edges;

    articles.forEach((article) => {
      createPage({
        path: `/article/${article.node.slug}`,
        component: "./src/templates/Article.vue",
        context: {
          id: article.node.id,
        },
      });
    });

    categories.forEach((category) => {
      createPage({
        path: `/category/${category.node.slug}`,
        component: "./src/templates/Category.vue",
        context: {
          id: category.node.id,
          slug: category.node.slug,
        },
      });
    });
  });
};

src/pages/Index.vueの変更

src/pages/Index.vueを下記のように変更します。

frontend/src/pages/Index.vue
<template>
  <Layout>
      <Articles :articles="$page.allStrapiArticle.edges" />
  </Layout>
</template>

<page-query>
query ($page: Int) {
  strapiGlobal(id:1) {
    siteName
    favicon {
      url
    }
    defaultSeo {
      metaTitle
      metaDescription
      shareImage {
        url
      }
    }
  }
  strapiHomepage(id:1) {
    hero {
      title
    }
    seo {
      metaTitle
      metaDescription
      shareImage {
        url
      }
    }
  }
  allStrapiArticle(filter: { status: {eq: "published"} } sortBy: "publishedAt", order: DESC) {
    edges {
      node {
        slug
        title
        description
        category {
          name
        }
        image {
          url
        }
        author {
          name
          picture {
            url
          }
        }
      }
    }
  }
}
</page-query>

<script>
import Articles from "~/components/Articles";
import { getMetaTags } from "~/utils/seo";
import { getStrapiMedia } from "~/utils/medias";

export default {
  components: {
    Articles,
  },
  metaInfo() {
    const { seo } = this.$page.strapiHomepage;
    const { defaultSeo, favicon } = this.$page.strapiGlobal;

    // Merge default and article-specific SEO data
    const fullSeo = {
      ...defaultSeo,
      ...seo,
    };

    return {
      title: fullSeo.metaTitle,
      meta: getMetaTags(fullSeo),
      link: [
        {
          rel: "favicon",
          href: getStrapiMedia(favicon.url),
        },
      ],
    };
  },
};
</script>

@gridsome/source-strapiはデフォルトでtypeNameのプレフィックスにStrapiがつきます。
たとえばstrapiのCollection Typeがarticleの場合、GridsomeのtypeNameはstrapiArticle、allStrapiArticleになります。
typeNameのプレフィックスはプラグインのオプションでtypeNameを定義することで変更ができます。

queryの定義を変更したことでpage.strapi.articlesがpage.allStrapiArticle.edges、this.page.strapi.homepageがthis.page.strapiHomepage等に変更しています。

src/templates/Article.vueの変更

src/templates/Article.vueのpage-queryを下記のように変更します。

src/templates/Article.vue
<page-query>
query ($id: ID!) {
  article: strapiArticle(id: $id) {
    title
    description
    content
    publishedAt
    image {
      url
    }
    author {
      name
      picture {
        url
      }
    }
  }
  global: strapiGlobal(id: 1) {
    siteName
    favicon {
      url
    }
    defaultSeo {
      metaTitle
      metaDescription
      shareImage {
        url
      }
    }
  }
}
</page-query>

またtemplateとscriptで下記を変更します。

変更前 変更後
$page.strapi.articles[0] $page.article
$page.strapi.global $page.global

src/templates/Category.vueの変更

src/templates/Category.vueのpage-queryを下記のように変更します。

src/templates/Article.vue
<page-query>
query ($id: ID!, $slug: String!) {
  category: strapiCategory(id: $id) {
    name
  }
  articles: allStrapiArticle(filter: { category: { slug: { eq: $slug }}, status: { eq : "published" }}) {
    edges {
      node {
        id
        title
        content
        slug
        image {
          url
        }
        category {
          name
        }
        author {
          name
          picture {
            url
          }
        }
      }
    }
  }
}
</page-query>

templateとscriptで下記を変更します。

変更前 変更後
$page.strapi.categories[0].article $page.articles.edges
$page.strapi.categories[0] $page.category

queryのcategory: strapiCategory(id: $id)内で、belongsToを使ってarticlesを持ってきたかったのですがうまく取得できませんでした。
また、articles: allStrapiArticleのfilterでcategory: { id: { eq: $id }}としたかったのですが、下記エラーになったため、slugを使用しています。

Error: Variable "$id" of type "ID!" used in position expecting type "Int".

src/components/Navbar.vueの変更

src/components/Navbar.vueのstatic-queryを下記のように変更します。

src/components/Navbar.vue
<static-query>
query {
  strapiGlobal(id:1) {
    siteName
  }
  allStrapiCategory {
    edges {
      node {
        id
        name
        slug
      }
    }
  }
}
</static-query>

templateで下記を変更します。

変更前 変更後
$static.strapi.global $static.strapiGlobal
$static.strapi.categories $static.allStrapiCategory.edges
category category.node

src/components/Articles.vueの変更

src/components/Articles.vueのtemplateで下記を変更します。

変更前 変更後
article article.node

src/components/Card.vueの変更

src/components/Card.vueのtemplateで下記を変更します。

変更前 変更後
article article.node