序章

Webサイトまたはアプリケーションを構築する場合、多くの場合、最も困難なタスクの1つは、複数のソースからデータを取得し、それを統一された出力にまとめることです。 これを解決する一般的な方法は、サイトのさまざまな部分にまったく異なるビルドシステムを使用することですが、これにより複雑さが増し、均一性の実現が困難になる場合があります。 ここで、データ駆動型の Static Site Generator (SSG)であるGatsbyがソリューションを提供できます。

Gatsbyの主要な目的の1つは、開発者にとってこの問題を解決することであり、ソースプラグインがその主な方法です。 ソースプラグインは、特定のソースからGatsbyエコシステムへのデータの取り込みを処理するコードのバンドルです。 ソースは、Markdownファイル、データベース、公開されたデータフィード、またはAPIなどの完全に動的なリモートデータソースの場合と同様に、ローカルファイルシステムから取得できます。

このチュートリアルでは、独自のカスタムソースプラグインを作成して、実際のAPIから新しいデータをGatsbyに取り込みます。 また、Gatsby全体でアクセスできるようにデータをフォーマットし、チュートリアルの終わりまでに、新しい動的データソースから静的HTMLを構築する作業プロジェクトを作成します。

前提条件

始める前に、ここにあなたが必要とするいくつかのものがあります:

  • Gatsbyを実行してサイトを構築するためのNode.jsのローカルインストール。 インストール手順はオペレーティングシステムによって異なりますが、DigitalOceanには Ubuntu20.04およびmacOSのガイドがあり、最新リリースは公式Node.jsダウンロードページ[ X213X]。
  • Gatsbyで作業するためのJavaScriptにある程度精通している。 JavaScript言語は広大なトピックですが、出発点としては、JavaScriptでコーディングする方法シリーズが適しています。
  • Web API Node.js 、およびJSONにある程度精通している。
  • から足場となった新しいギャツビープロジェクト gatsby-starter-default. この要件を満たし、新しいGatsbyプロジェクトを最初から構築するには、最初のGatsbyWebサイトのセットアップ方法チュートリアルのステップ1を参照してください。
  • このチュートリアルで説明されている以上に投稿のユーザーインターフェイス(UI)をカスタマイズする場合は、ReactとJSX、およびHTML要素にある程度精通している必要があります。

このチュートリアルは、Node.js v14.16.1、npm v6.14.12、Gatsby v3.13.0、および node-fetch v2.6.2。

ステップ1—ファイルのスキャフォールディングと依存関係のインストール

何かを構築するときの最初のステップは、常にツールとパーツを整頓することです。 このステップでは、必要なファイル構造を作成し、コードが依存する依存関係をインストールすることにより、ソースプラグインの初期ビルディングブロックを配置します。

これはローカルプラグインになるため、Gatsbyプロジェクト内にディレクトリを作成して、プラグインのソースコードをルートレベルで保持します。 plugins ディレクトリ。 これを行うには、ファイルブラウザで手動でフォルダを作成するか、プロジェクトのルートにあるコマンドラインから mkdir 指図:

  1. mkdir -p plugins/my-custom-source-plugin

注: Gatsbyプロジェクトディレクトリの外部でプラグインを開発する場合は、それを行うことができますが、Gatsbyにファイルをサイトにプルさせるにはいくつかの追加手順が必要です。 詳細については、公式のGatsbyドキュメントをご覧ください。

次に、を作成する必要があります package.json このディレクトリを独自の依存関係を持つNode.jsパッケージとしてマークするファイル。 このファイルを作成し、いくつかの必須フィールドに事前に入力するには、次のコマンドを使用します。

  1. cd plugins/my-custom-source-plugin
  2. npm init -y

このコマンドは、新しく作成したプラグインフォルダーに移動し、 npm init 新しいパッケージを初期化します。 The -y フラグは、このプロジェクトに関係のないいくつかの質問をスキップし、 package.json 必要最小限の値でファイルします。

package.json 存在する場合は、プラグインに依存関係を追加して、機能のコーディングを容易にすることができます。 次のコマンドを使用して、このチュートリアルで必要となる唯一の追加の依存関係node-fetchをインストールします。

  1. npm install node-fetch@^2

最後に、 gatsby-node.js ソースプラグインのメインコードを保持することになるファイル:

  1. touch gatsby-node.js

注: Gatsbyプラグインを頻繁に作成している場合は、プラグインテンプレートが役立つ場合があります。

プラグインをサポートするファイル構造を作成し、初期の依存関係をインストールしたので、プラグインを見つけてロードする方法についてGatsbyに指示を与えることに移ります。

ステップ2—プラグインのロードと構成

Gatsbyプラグインまたはテーマの場合と同様に、Gatsbyは、プラグインをどこからどのようにロードするかについて指示を受ける必要があります。 これを行うには、メインのGatsby構成ファイルを編集します gatsby-config.js 、Gatsbyプロジェクトのルートにあります。 選択したエディターでファイルを開き、次の強調表示された行を追加します。

gatsby-config.js
module.exports = {
...
  plugins: [
    `gatsby-plugin-react-helmet`,
    `gatsby-plugin-image`,
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `images`,
        path: `${__dirname}/src/images`,
      },
    },
    `my-custom-source-plugin`,
    `gatsby-transformer-sharp`,
...

プラグインのソースコードは plugins ディレクトリ、Gatsbyにロードさせるために必要なのは、そのフォルダ内にあるサブディレクトリの名前を渡すことだけです。 プラグインも現時点ではオプションを使用しないため、合格する必要はありません。 options Gatsby構成ブロックでそれに反対します。

保存 gatsby-config.js ファイルを終了します。

これで、カスタムソースプラグインをロードするようにGatsbyを構成し、実行するソースコードの場所を正確に指示しました。 次のステップでは、このソースコードを作成して、カスタムリモートソースからNode.jsランタイムにデータをプルします。

ステップ3—生データをNode.jsにプルする

前の手順では、カスタムソースプラグインのコードを読み込んで実行するようにGatsbyを構成しましたが、Gatsbyエコシステムに新しいデータを取り込むタスクを実行するには、このコードを構築する必要があります。 このステップでは、これを行うコードを記述し、を介してリモートデータをフェッチします node-fetch 将来のステップで使用するために準備します。

ソースプラグインは、ローカルまたはリモートのほぼどこからでもデータをプルできますが、このチュートリアルでは、ソースプラグインは、ウィキペディアコンピュータープログラミングブックカテゴリから、それらのパブリックAPIを介してタイトルと抜粋を具体的にプルします。 ]。

あなたの my-custom-source-plugin/gatsby-node.js あなたのファイル plugins ディレクトリを作成し、次のコードを追加します。

plugins / my-custom-source-plugin / gatsby-node.js
const fetch = require('node-fetch').default

/**
 * Fetch a list of computer books from Wikipedia, with excerpts
 */
async function getWikiProgrammingBooks() {
  const BASE_ENDPOINT = "https://en.wikipedia.org/w/api.php?action=query&format=json&utf8=1&redirects=1";

  // Get list of books
  const listEndpoint = new URL(BASE_ENDPOINT);
  listEndpoint.searchParams.append('list', 'categorymembers');
  listEndpoint.searchParams.append("cmtitle", "Category:Computer_programming_books");
  listEndpoint.searchParams.append("cmlimit", "10");
  const listResults = await (await fetch(listEndpoint.toString())).json();


  // Extract out the page IDs from the list
  const pageIds = listResults.query.categorymembers.map((listing) => listing.pageid);

  // Fetch details for page IDs
  const extractEndpoint = new URL(BASE_ENDPOINT);
  extractEndpoint.searchParams.append("pageids", pageIds.join("|"));
  extractEndpoint.searchParams.append("prop", "extracts|info");
  extractEndpoint.searchParams.append("exintro", "");
  extractEndpoint.searchParams.append("explaintext", "");
  extractEndpoint.searchParams.append("inprop", "url");

  const bookResult = await (await fetch(extractEndpoint.toString())).json();

  return Object.values(bookResult.query.pages);
}

このコードでは、コンピュータープログラミングブックのリストを、それらのページID(Wikipedia内の一意のID)および抜粋/抜粋とともに返すために呼び出すことができる再利用可能な関数を作成しました。 関数の最初の部分では、特定のカテゴリ Computer Programming Books )に属するタイトルとIDの初期リストをフェッチするために使用する適切なAPIURLを作成します。 URLコンストラクターとインターフェイスは、クエリ文字列の変更を読みやすく管理しやすくするために使用されます。

あなたは fetch node-fetchからメソッドを作成して GET 作成されたURLにリクエストします。これにより、本のタイトルとそのIDのリストが返されます。 その応答は、配列に変換されます。 pageid 後にウィキペディアAPIを再度クエリするために使用される値。今回は、指定されたページIDに対して生成されたextractおよびmetainfoを要求します。 ページIDはパイプ文字(|)、ウィキペディアAPIはこの形式を使用して、単一の文字列値を介して複数のIDを受け入れます。

最後に、ページの抜粋の結果はオブジェクトとして返され、各書籍のリストは独自のIDでキーとしてネストされているため、次のように使用します。 Object.values() ページIDキーを省略し、結果を配列に変換してから返します。

この関数の出力をログに記録すると、次のようになります。

[
  {
    "pageid": 379671,
    "ns": 0,
    "title": "The C Programming Language",
    "extract": "The C Programming Language (sometimes termed K&R, after its authors' initials) is a computer programming book written by Brian Kernighan and Dennis Ritchie...",
    "fullurl": "https://en.wikipedia.org/wiki/The_C_Programming_Language",
    ...
  },
  ...
]

必ず変更を保存してください。ただし、次の手順でコードを追加するため、このファイルは開いたままにしてください。

このステップでは、 node-fetch リモートソースコンテンツを取得し、 gatsby-node.js ファイル。 次のステップでは、コンテンツを正規化して、Gatsbyプロジェクト全体で使用する新しいGatsbyノードを作成します。

ステップ4—データの正規化とノードの作成

リモートコンテンツを取得してに取り込む gatsby-node.js 前のステップで、ギャツビー全体でアクセスできるようになったという意味ではありません。 Gatsbyは、データを普遍的な方法で共有するために、ノードの概念を使用します。ノードは、統合されたGraphQLデータレイヤー間で共有されます。 このステップでは、これらのノードを作成し、それに合わせて新しいコンテンツをフォーマットします。

ウィキペディアから結果を取得してアクセスできるようになりましたが、 getWikiProgrammingBooks()、これをGatsbyのノードシステムと統合するためのコードを追加する必要があります。 同じように gatsby-node.js 前のステップのファイルで、ノードの生成を処理するためにこの新しいコードブロックを追加します。

plugins / my-custom-source-plugin / gatsby-node.js
const fetch = require('node-fetch').default

...

exports.sourceNodes = async ({ actions, createContentDigest, createNodeId }) => {
  // Arbitrary node type constant
  const BOOK_TYPE = 'BookWikiPage';

  // Get books
  const bookResults = await getWikiProgrammingBooks();

  // Convert raw book results to nodes
  for (const book of bookResults) {
    actions.createNode({
      ...book,
      id: createNodeId(`${BOOK_TYPE}-${book.pageid}`),
      parent: null,
      children: [],
      internal: {
        type: BOOK_TYPE,
        contentDigest: createContentDigest(book)
      }
    })
  }
};

このコードブロックでは、によって返された各本を繰り返し処理しています getWikiProgrammingBooks createNodeメソッドを介してGatsbyノードを作成します。 に渡される各プロパティと値 createNode 重要性があり、検討する価値があります。

  • ...book は、ウィキペディアAPIオブジェクトから作成中のGatsbyノードにキーと値のペアを拡散するために使用されます。 これは、後でアクセスできることを意味します node.title、からコピーされるため book.title.
  • id ギャツビー内でグローバルにユニークな値です。 独自のプラグイン内で各書籍のIDを一意にするために、書籍の種類とWikipediaのページIDを組み合わせてID文字列を形成します。 ただし、他のプラグインが使用しているIDがわからないため、IDをに渡すベストプラクティスを使用しました。 createNodeId、これは、IDがグローバルに一意のものに変換されることを保証するギャツビーヘルパー関数です。
  • parent IDを介してノードを別のノードにリンクし、このノードを子としてマークするために使用できるフィールドです。 各本は独自のエンティティであり、他のノードに接続されていないため、これを次のように残しました null、親がないことを意味します。
  • children と類似しています parent ノードをリンクする方法として、ただしIDの配列を取ります。 各本には子がないため、配列は空のままにしておきます。
  • internal Gatsbyの内部ノード管理システムおよびその他のプラグインに非常に固有のフィールドをグループ化するオブジェクトです。 公式フィールドのみを含めることができるため、 book それにオブジェクト。
  • type 作成しているノードのタイプを説明するグローバルに一意の文字列であり、後でGraphQLを介してノードをクエリするときに使用されます。
  • contentDigestノードとギャツビーのコンテンツから構築されたハッシュ文字列です createContentDigest ヘルパーユーティリティ。 このフィールドは、ノードの変更があった場合にハッシュ文字列が変更されるため、Gatsbyがノードが変更されたことを検出するのに役立ちます。 book オブジェクトが変更されます。

ソースコンテンツを取得し、それを使用して新しいGatsbyノードを作成し、Gatsby環境全体で共有するコードを追加しました。 次のステップでは、これらのノードがGraphQLデータレイヤーに表示され、クエリできることを確認します。

ステップ5—(オプション)GraphQLAPIを使用したノード出力の検査

これで、ソースコンテンツをGatsbyにプルし、それを使用して新しいノードを作成しました。 ブレークポイントまたはログステートメントを使用して手動でデバッグする代わりに、このステップでは、インタラクティブなGraphQL IDEを使用して、これらの新しいノードが作成され、GraphQLAPIでクエリできることを確認します。

Gatsbyプロジェクトのルートから次のコマンドを実行して、ローカル開発サーバーを起動します。

  1. npm run develop

注:このチュートリアルの執筆時点で、Gatsbyの依存関係チェーンの問題により、メッセージを返す可能性のあるエラーが発生しました Error: Cannot find module 'gatsby-core-utils' 開発サーバーを起動しようとしたとき。 このエラーが発生した場合は、次を実行してください。

  1. npm install gatsby-core-utils

これにより、Gatsbyコアユーティリティが再インストールされ、依存関係の問題が解決されます。 詳細については、このギャツビーエラーGitHubの問題を確認してください。

Gatsbyサイトのライブバージョンを立ち上げることに加えて、 develop このコマンドは、ローカルのGraphQLサーバーとIDEも公開します。 コードを確認するには gatsby-node.js すべての本のノードを作成している場合、このGraphQLクエリを使用して、本のタイトル、ページID、およびGatsbyIDを取得します。

{
  allBookWikiPage {
    edges {
      node {
        title
        pageid
        id
      }
    }
  }
}

このクエリを実行するには、インタラクティブなGraphQLIDEを開きます。 localhost:8000/___graphql 実行する前にクエリを左側に貼り付けるか、cURLを介してクエリを実行します。

  1. curl --location --request POST 'http://localhost:8000/___graphql' \
  2. --header 'Content-Type: application/json' \
  3. --data-raw '{
  4. "query": "{ allBookWikiPage { edges { node { title pageid id } } } }"
  5. }'

応答JSONは次のようになります。

{
  "data": {
    "allBookWikiPage": {
      "edges": [
        {
          "node": {
            "title": "The C Programming Language",
            "pageid": 379671,
            "id": "818771ca-40aa-5cfd-b9e7-fddff093d5ec"
          }
        },
        ...
      ]
    }
  },
  "extensions": {}
}

新しいカスタムソースノードが作成され、GraphQLデータレイヤーでアクセス可能であることを確認したら、次のステップは、それらを使用して、サイトまたはアプリケーションの訪問者に表示されるコンテンツを作成することです。

ステップ6—(オプション)ノードに基づいてページを作成する

これまでのすべてのステップは、内部Gatsbyノードの作成に焦点を当てており、それらの作成と取得機能を検証する最後のステップも含まれています。 ただし、これらのノードは、Gatsbyプロジェクトで実行されているコードにのみ表示され、サイトやアプリケーションの訪問者には表示されません。 このステップでは、 React ページテンプレートファイルを追加してノードに接続し、ソースプラグインのコンテンツが実際の公開ウェブページに変わるようにします。

Gatsbyノードに基づいてページを作成する方法は複数ありますが、このチュートリアルでは、ファイルシステムルートAPI を使用します。これは、特別なファイル名構文に基づいてページを作成します。

まず、で空のファイルを作成します src/pages ファイル名は {BookWikiPage.title}.js. 中括弧は、ファイル名がファイルシステムルートAPIを使用していることをギャツビーに伝え、中括弧の内側には、 BookWikiPage.title Gatsbyに、固有の本のタイトルごとにページを作成するように指示します。 内のファイルで作業していないことに注意してください plugins ディレクトリですが、現在メインのGatsbyプロジェクト内で作業しています。

次に、ブックノードを取得してWebページとして表示するコードをそのファイルに追加します。

src / pages / {BookWikiPage.title} .js
import { graphql } from "gatsby";
import * as React from "react";
import Layout from "../components/layout";
import Seo from "../components/seo";

export default function BookPageTemplate({ data: { bookWikiPage } }) {
  const { title, extract, fullurl } = bookWikiPage;
  return (
    <Layout>
      <Seo title={title} />
      <h1>{title}</h1>
      <blockquote>{extract}</blockquote>

      <i>This article uses material from the Wikipedia article <a href={fullurl} target="_blank" rel="noreferrer">"{title}"</a>, which is released under the <a href="https://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-Share-Alike License 3.0</a>.</i>
    </Layout>
  );
}

export const pageQuery = graphql`
  query ($id: String!) {
    bookWikiPage(id: { eq: $id }) {
      title
      extract
      fullurl
    }
  }
`;

コードの最後には、と呼ばれるエクスポートされた変数があります pageQueryGatsbyGraphQLタグを使用します。 Gatsbyは、それに続く GraphQLクエリを評価し、結果を BookPageTemplate 関数。

The BookPageTemplate Reactコンポーネントである関数は、GraphQLクエリの結果を取得し、返される JSX に値を埋め込むことにより、それらをWebページの一部として表示します。 本のタイトルはページのメインの見出しとタイトルとして使用され、抜粋はブロック引用として表示され、完全なWikipediaエントリページへのリンクが下部に埋め込まれています。

また、マークを付けます BookPageTemplate を使用してデフォルトのエクスポートとして機能する export default Gatsbyは、各ページテンプレートファイルのデフォルトのエクスポートとして、最終的にレンダリングされたページの生成を担当するReactコンポーネントを見つけることを期待しているため、宣言の前に。

Reactテンプレートコードをファイルに追加したら、変更を保存して閉じます。 案内する http://localhost:8000/the-c-programming-language/ サンプルページをレンダリングするには:

注:ノードに基づいてページを作成するためのより手動のアプローチについては、内部で createPagesAPIを使用できます。 gatsby-node.js.

これらの新しいノードとそれに関連するページのリストを表示するには、専用のリストページも作成します。このページでは、すべての書籍が1か所に表示されます。 下 src/pages、ファイル名が books.js. 次に、次のコードを追加します。

src / pages / books.js
import { graphql, Link } from "gatsby";
import * as React from "react";
import Layout from "../components/layout";
import Seo from "../components/seo";

export default function BookListingsPageTemplate({ data: { allBookWikiPage } }) {
  return (
    <Layout>
      <Seo title="Programming Books Listing" />
      <p>Here are some computer programming books that have their own Wikipedia entries:</p>

      {allBookWikiPage.edges.map((edge) => {
        const node = edge.node;
        return (
          <details key={node.title}>
            <summary>{node.title}</summary>

            <div className="details-body">
              <p>{node.extract}</p>
              <div className="links">
                <Link href={node.gatsbyPath}>Internal Page</Link>
                <a rel="noreferrer" href={node.fullurl}>Wikipedia Page</a>
              </div>
            </div>
          </details>
        )
      })}
    </Layout>
  );
}

export const pageQuery = graphql`
  query {
    allBookWikiPage {
      edges {
        node {
          title
          extract
          gatsbyPath(filePath: "/{BookWikiPage.title}")
          fullurl
        }
      }
    }
  }
`;

に似ています {BookWikiPage.title}.js ページテンプレート、このファイルもGraphQLを使用します pageQuery タグを付けてGraphQLレイヤーからデータを取得し、それをReactコンポーネントに渡します。 ただし、以前のテンプレートはIDに基づいて単一の本をレンダリングしましたが、このテンプレートは、以前に作成された個々の本のページにリンクしながら、すべての本のリストをレンダリングします。

各本のリストは <details> 要素。リストを展開して本とリンクの完全な抜粋を表示したり、折りたたんでタイトルだけを表示したりできます。 ベストプラクティスに従って、独自の値をに渡します key アレイを反復処理している間、内部リンクにGatsbyLinkコンポーネントを使用します。 a 外部リンクのタグ。

The gatsbyPath(filePath: "/{BookWikiPage.title}") GraphQLクエリの文字列は特別なものを使用します gatsbyPath() 渡されたファイルシステムルートAPIファイル名に基づいて作成されるパブリックパスを取得する関数。

このファイルを保存して終了します。

注:コンポーネントのデータソースを変更すると、ホットリロード機能によって次のようなエラーが返されることがあります。 error Cannot query field "gatsbyPath" on type "BookWikiPage" graphql/template-strings. このエラーを修正するには、プロセスを終了して実行することにより、開発サーバーを手動で再起動します npm run develop また。

すべての本が1ページにあるため、折りたたみ可能なセクションでも少し混雑しているため、最後のステップは、訪問者がリストを読みやすくするためのスタイルを追加することです。 で新しいスタイルシートファイルを作成します src/styles/books.css. これは、ファイルブラウザで、またはGatsbyプロジェクトのルートからのコマンドラインを使用して実行できます。

  1. mkdir -p ./src/styles
  2. touch ./src/styles/books.css

次に、次のCSSをファイルに追加します。

src / styles / books.css
details {
  border: 1px dotted black;
  margin: 6px;
  padding: 6px;
}

.details-body {
  background-color: #eedeff;
  margin: 4px 0px 2px 12px;
  padding: 4px;
  border-radius: 4px;
}

.links {
  display: flex;
  justify-content: space-evenly;
}

このCSSは、各本のリストの周囲に境界線を追加し、リスト内の間隔と余白、および内部と外部の本のリンクの間に間隔を追加します。 CSSをファイルに追加したら、保存して閉じてから次に進みます。

最後に、書籍リストページテンプレートを更新して、このCSSファイルを次の場所にプルします。

src / pages / books.js
import { graphql, Link } from "gatsby";
import * as React from "react";
import Layout from "../components/layout";
import Seo from "../components/seo";
import "../styles/books.css";

新しく追加されたCSSインポート行を使用して、このファイルを保存して閉じます。

結果を確認するには、developコマンドを再度実行して開発サーバーを起動し、新しいページをプレビューします。

  1. npm run develop

これで、次の場所で書籍リストページにアクセスできます。 localhost:8000/books/.

これで、Gatsbyソースプラグインを最初から作成しただけでなく、Reactテンプレートに基づいてページを生成するためにも使用できました。

結論

このチュートリアルの手順に従うことで、外部コンテンツをGatsbyプロジェクトに取り込み、それを使用してサイト内の新しいページを強化するカスタムソースプラグインの構築が完了しました。

プラグインのソースには多くの深みがあります。 ベストプラクティスに従い、より高度なソースプラグインの概念を学ぶことに興味がある場合は、次の分野に興味があるかもしれません。

Gatsbyの詳細については、Gatsby.jsシリーズを使用して静的Webサイトを作成する方法の残りの部分を確認してください。