金曜日, 5月 16, 2025
ホームWordPresswordpress + astro.jsのヘッドレスCMS構築の道のり #3 デバッグについてroyaltrux

wordpress + astro.jsのヘッドレスCMS構築の道のり #3 デバッグについてroyaltrux

🧠 概要:

概要

この記事は、WordPressとAstro.jsを使用してヘッドレスCMSを構築する過程の第3回目で、デバッグの方法について詳しく説明しています。JavaScriptに慣れた著者が、特にAstro.jsにおけるconsole.log()の使い方や、クライアントサイドでデータをどのように取り扱うかに焦点を当てています。

要約

  • デバッグの重要性

    • JavaScriptを使ってデバッグを行いたいが、Astro.js内でのconsole.log()の使い方が難しいと感じている。
  • Node.jsとブラウザの違い

    • Node.jsサーバー側でのconsole.log()は、ブラウザのDevToolsには表示されない。
  • HTML内のJavaScript

    • HTML内に直接JavaScriptを埋め込む方法を説明。
  • Reactコンポーネントの使用

    • Reactを使用してデータをブラウザに渡す仕組みを考察。Reactを使うにはあらかじめReactをインストールしておく必要がある。
  • クライアントサイドReactの仕組み

    • Astroがビルド時にWordPress APIからpostsを取得し、Reactコンポーネントに渡す流れを説明。
  • デバッグ用コンポーネント PostLogger

    • PostLogger.jsxの作成方法と、ReactのuseEffect()を使用してコンソールにデータを出力する方法を確認。
  • Vue.jsでの実装

    • Vue.jsでも同様の手順でデバッグを行う方法を説明し、propsの受取についての注意点を指摘。
  • 他の手法

    • set:htmlを用いてJavaScriptコードをHTML内に埋め込む方法や、JSONデータの扱いについても解説。
  • 各手法の選択

    • どの手法を使うかは個人の好みによるが、ReactやVueを使ったコンポーネントを作る方法が推奨される。
  • 次回予告
    • 次回は各ページを作成することについて話す予定がある。

wordpress + astro.jsのヘッドレスCMS構築の道のり #3 デバッグについてroyaltrux

ってな訳で、javaScriptに慣れ親しんだ者としては、cosole.log() をバシバシに使いたいところ…。
astro ではデバッグはどうすればいいんじゃ…🫠

デバッグについて

ひとまずは前回使用した、下記のコードで変数 res の中身を確認したい場合はどうすりゃいいんじゃ?ってことで

const res = await fetch('http:

たとえば

---
const res = await fetch('http://headless.local/wp-json/wp/v2/posts');
console.log(res);
---

としてみても、— ブロック内に記述された console.log() はNode.js のサーバー側(ターミナル)に出力されるので、ブラウザのDevToolsでは見えないのです😅

1.

html内の <![CDATA[ でクライアントのjavaScript側に渡すやり方がありますが、猛烈にダルいです。
— の中はサーバー上で実行され、ブラウザでは利用できないのが基本です。
じゃあどうするかという、htmlのタグの属性に値をセットして、それを読み込むという感じらしい(正気か…💀)。]]>

---
const x = 12;
---

"aaa">{x}

<![CDATA[ const dataVal = document.getElementById("aaa").getAttribute("data-val"); console.log(dataVal); ]]>

狂ってますな…🤡

✨✨✨
色々とやっていたら、普通にjavaScriptだけで簡単に出力出来ました!
詳しくはこのページの下の方の、「他のフレームワークでもやってみよう!」の「あれ?ちょっと待て!」で書いてあります
✨✨✨

2.デバッグ用にクライアントJSに渡してログを出す(Reactを使用)

次は取得したデータを、Reactのコンポーネント経由でブラウザに渡してみます!
ただ、みなさんもお気づきのように今回のプロジェクトにはreactがインストールされていません!
AstroでReactコンポーネント(.jsx や .tsx)を使う場合は、当然ながらReactが必要です。
Reactをインストールしておきましょう~😁

npm install react react-dom @astrojs/react

そして、astro.config.mjs に下記を追加しておきます!

import { defineConfig } from 'astro/config';
import react from '@astrojs/react'; 


export default defineConfig({
  integrations: [react()], 
});

これで準備はばっちりなので、/src/components/ の中に、PostLogger.jsx というjsxファイルを作り、下記の内容を記述しておきます。

import { useEffect } from 'react';

export default function PostLogger({ posts }) {
  useEffect(() => {
    console.log("クライアント側の posts:", posts);
  }, []);

  return null;
}

そして astro側で PostLogger を import して、htmlに PostLogger コンポーネントを記述して読み込みます。
PostLogger コンポーネントは、client:load を付けて必ずブラウザ上で動作するようにします!

---
import PostLogger from '../../components/PostLogger.jsx';

let posts = [];
let error = false;


try {
  const res = await fetch('http://headless.local/wp-json/wp/v2/posts');
  if (!res.ok) throw new Error("HTTPエラー");
  posts = await res.json();
} catch (err) {
  console.error("記事の取得に失敗しました:", err);
  error = true;
}
---


  
    
    ブログ一覧
  
  
    

    {error ? (
      

記事の取得に失敗しました。

) : ( )}

すると…

出たー😁!!

全体の流れの解説

クライアントサイド React コンポーネントの仕組み

今回のコードがどういう流れで動いているかと言いますと…。

  1. Astro がビルド時に WordPress API を叩いて posts を取得

  2. posts を props として React コンポーネント PostLogger に渡す

  3. PostLogger は client:load により「クライアント側で動的にロードされるJSとして埋め込まれる

  4. React の useEffect() により「クライアントのブラウザで console.log(posts)」が実行される

と、こんな感じになっています。

各要素の詳しい説明

◆client:load

  • この記述により、Astroはビルド時に その場では HTML を出力しない

  • クライアント用の JavaScript バンドルを作る

  • ページ読み込み後に ブラウザ上で React を実行します

ちなみに他にも、client:visible(ビューポート内で読み込む)、client:only(完全にクライアント専用)などがあります。

◆PostLogger コンポーネント

import { useEffect } from 'react';

export default function PostLogger({ posts }) {
  useEffect(() => {
    console.log("クライアント側の posts:", posts);
  }, []);

  return null;
}
  • useEffect() は React のフックで、「コンポーネントがマウントされた直後に実行」されます

  • posts は Astro から props 経由で受け取ったデータ

  • Astro が posts を JSON にして script に埋め込む → React のコンポーネントで受け取って使う、という流れになります😊

なぜこれでクライアント側で console.log() が出るのか?

Astroは

  1. Astroの .astro ファイルの中で posts を取得して、

  2. Reactコンポーネントにその値を埋め込む形でHTML + JSを生成、

  3. そして client:load 指定により、Reactがブラウザ上で初めて実行されるからです

結果的に、console.log() はブラウザ(ChromeのDevTools)に出力されることになります!
イメージとしては下記のような感じですな🐭

[ Astro (.astro) ]
   |
   |--- SSGで WordPress から JSON 取得
   |
   |--- React の PostLogger に props として渡す
   |
   |--- client:load によって JS バンドルとして出力
   |
[ ブラウザ ]
   |
   |--- JS が読み込まれ、PostLogger 実行
   |
   |--- useEffect によって console.log(posts)

この仕組みを使えば、Astroで取得したデータを、クライアントJSで処理することが出来るので便利そうです!
例えば、検索フィルターとかはこの仕組みを使うと良さげ…。

他のフレームワークでもやってみよう!

多分これ、Reactじゃなくても出来ますよね…
という訳で!

Vue.jsでやってみた

まずはVueをインストールです!

npm install vue @astrojs/vue

続いては astro.config.mjs にVue統合を追加します!

import { defineConfig } from 'astro/config';
import vue from '@astrojs/vue';

export default defineConfig({
  integrations: [vue()],
});

そして React に代わって、Vueコンポーネントを作成します!
場所は同じで /src/components/PostLogger.vue となります


  
  


<![CDATA[
import { onMounted } from 'vue';

// Astroから props を明示的に変数として受け取る
const props = defineProps({
  posts: Array
});

onMounted(() => {
  console.log("クライアント側(Vue)で受け取った posts:", props.posts);
});
]]>

Reactに比べると、少し記述することが多いですな。
props のオブジェクトは自分で名前を付けて受け取る必要があるので、変数に入れておきましょー

次は astro側で

// import PostLogger from '../../components/PostLogger.jsx';
import PostLogger from '../../components/PostLogger.vue';

ファイルを React の jsx から vue に変更します!
そしてhtmlの方も

<!-- <PostLogger client:load posts={posts} /> -->
client:load :posts={posts} />

と Vue の記述したものにしておきます!
これでばっちり!と思ったら、

クライアント側(Vue)で受け取った posts: undefined

と undefined になりました…😥
どういうこったい…。

こうなったら教えて!chatGPT先生!
と先生に聞いてみると…


client:load :posts={posts} />

という指摘!なんだって~!
「:posts は Vue SFC 内のテンプレートでのみ有効なシンタックスなので、Astro 側では props が渡らず undefined になります。」
とのこと。
ぬぬぬ!変に Vue に慣れ親しんでいたために…💀
なので、ここを修正して

に変更したところ

やった~!!

javaScriptのみ

javaScriptだけでやるには、html内に script タグで記述していくことになります。

<!-- 🔽 1. JSONとしてクライアントに渡す -->
<![CDATA["application/json" id="posts-json">
  {JSON.stringify(posts).replace(/, '\u003c')}
]]>

<!-- 🔽 2. プレーンJSで読み取ってログ出力 -->
<![CDATA[
  const jsonText = document.getElementById("posts-json").textContent;
  try {
    const posts = JSON.parse(jsonText);
    console.log("クライアント側(プレーンJS)の posts:", posts);
  } catch (e) {
    console.error("JSON parse error:", e);
  }
]]>

これでサクッと終了!と思ったら、JSON parse error が…。
これはjson受けとれてないみたいですね。
console.log(jsonText);
してみると

{JSON.stringify(posts).replace(/, '\u003c')}

あれ?そのまま文字列として出てきちゃってますな。
javaScriptとして認識されてないようです。
Astro では<![CDATA[ タグ内に書いた {…} は テンプレート構文ではなく、文字列リテラルとしてそのまま出力されてしまうとのことです😓
んじゃどうしようかとなった時に、set:html というのを使用すると、展開した結果を「生のHTMLとして挿入する」ことが出来る模様。
なので]]>

<![CDATA["application/json" id="posts-json" set:html={JSON.stringify(posts).replace(/, '\u003c')}>]]>

と、JSONとしてクライアントに渡す javaScript の箇所をまるっと set:html で挿入させます。

ばっちり!!

あれ?ちょっと待て!

ってことは、このページの上の方で書いた

---
const x = 12;
---

"aaa">{x}

<![CDATA[ const dataVal = document.getElementById("aaa").getAttribute("data-val"); console.log(dataVal); ]]>

この狂ったやり方ですが、set:html 使えばいいんじゃね?って思って

<![CDATA[set:html={`console.log("クライアント側のx:", ${x});`}>]]>

と書いてみたら

普通に出ましたな😓

ちなみにですが、set:html でコンソールに出力する場合、上の様に値が数字とかならいいんですが、文字列の場合は console.log 内でもクォートで囲む必要があります。

const x = 12;
const y = 'Astro';

こんな場合は

<![CDATA[set:html={`console.log("x =", ${x}); console.log("y =", "${y}");`}>]]>

と、”${y}” とクォートで囲まないとエラーとなりますので、要注意です!

どれを使えばいいのか?

3種類ともに、DevToolのコンソールに出力することが出来ました。
これのどれを使うのがいいのか…という感じですが、そこは個人の好みですかねぇ🤔

ひとまずは React でも Vue でもどちらでもいいので、PostLogger を作っておいて、それを使いつつ、ちょろっとしたものは set:html を使うとかですかね。
みんなはどうやってるんだろ…。

次回はblogの各ページを作っていきます!😀



続きをみる


Views: 0

RELATED ARTICLES

返事を書く

あなたのコメントを入力してください。
ここにあなたの名前を入力してください

- Advertisment -

インモビ転職