Astro にコンテンツをロードする別の方法


Astro には fetchContent という超クールな関数があり、ページからコンテンツを取得するために使用できます.

ちょっとした例として、Astro のすべての投稿を取得したい場合は、単に次のコマンドを使用します.

const allPosts = Astro.fetchContent('../pages/posts/*.md');


次のようなオブジェクトを返します.

[
  {
    // Fronmatter parts for example:
    "title": "The title",
    "date": "2022-02-22",
    "astro": {
      "headers": [],
      "source": "",
      "html": ""
    },
    "url": ""
  }
]


ご覧のとおり、すべてのデータを含むすべてのコンテンツをすばやく取得する非常に巧妙な方法です.

そして、このメソッドは必要なものをすべて返すので完璧です.

デメリットと解決策



各記事に関連する投稿を表示したかったのですが、これは素晴らしいアイデアのように思えました.
私は fetchContent を使用することから始めましたが、すぐにこの関数を使用することのマイナス面に出くわしました.

無限ループを引き起こす可能性があります.これは、HTML を技術的にレンダリングするためです.そのため、他の投稿 (推奨投稿など) を参照すると、スクリプトで無限ループが発生します.

解決策は、Astro の基本的な方法を使用して、応答を制限することです.

正式には globEager を使用していましたが、最初から glob を使用しました.執筆時点では、2つの違いが何であるかはわかりません.

以前のようにすべての投稿をロードするには、次のコードを使用できます.

const allPosts = await import.meta.glob('../pages/posts/*.md');


ただし、優れた形式の配列ではなく、次のような promise ベースの配列が返されます.

[
      '../pages/posts/are-you-participating-in-the-reply-code-challenge.md': [Function: ../pages/posts/are-you-participating-in-the-reply-code-challenge.md],
      '../pages/posts/asking-questions.md': [Function: ../pages/posts/asking-questions.md],
];


最初の部分 (キー) はファイル名で、値は遅延読み込みインポート (Vite を使用) です.

投稿の前付部分にアクセスする必要がある場合は、ループする必要があります.これまでは、ファイル名しかありませんでした.
mappedPosts という別の配列を作成し、すべてのキーをループします.これは次のようになります.

const mappedPosts = await Promise.all(
  Object.keys(allPosts).map((key) => {
    // Todo
  })
);


これは怠惰な promise であるため、関数を取得して戻りを待つ必要があります.

ただし、まず、現在の投稿を保存し、ファイル名をスラッグに変換します.

const mappedPosts = await Promise.all(
  Object.keys(allPosts).map((key) => {
    const post = allPosts[key];
    const url = key.replace('../pages/', '/').replace('.md', '/');
  })
);


接頭辞と拡張子を置き換えるだけで、次の例のようになります.

// ../pages/posts/why-tailwind-jit-compiler-is-amazing.md
// /posts/why-tailwind-jit-compiler-is-amazing


最後に、約束された結果を返し、必要な要素をフォーマットします.

イントロから、どの要素が利用可能か覚えていますか?それらのどれでも使用できます.前付部分と URL のみを返すことにしました.

const mappedPosts = await Promise.all(
  Object.keys(allPosts).map((key) => {
    const post = allPosts[key];
    const url = key.replace('../pages/', '/').replace('.md', '/');
    return post().then((p) => {
      return { ...p.frontmatter, url };
    });
  })
);


これで、無限ループを引き起こさないフロントマター部分を備えたきちんとした一連の投稿ができました.

これで、このアレイで必要なすべてのフィルタリングを実行できます.

この方法は少し手間がかかりますが、物事をより動的にします.

読んでくれてありがとう、接続しましょう!



私のブログを読んでいただきありがとうございます.メール ニュースレターを購読して、Facebook に接続してください.