EY-Office ブログ

いつの間にか停止していたEY-OfficeブログのRSSフィードを再開しました!

EY-OfficeRSSでブログの更新情報を配信しています。 ・・・はずだったのですが、ある時点(2023年末?)からRSSフィードrss.xmlが作成されていませんでした。😓

今回のブログは、「RSSフィードの再開」と「サイト https://www.ey-office.com/ のページがインデックスに登録されない新しい要因」というGoogleからの警告への対応に付いて書きます。

RSS_feed

RSS知ってますか?

皆さまはRSS知ってますか?

若い人は知らないかも知れませんが、昔は多くのブログやホームページが更新情報をRSSで配信していました。しかし、X(Twitter)やFacebook等のSNSの普及により人々の情報収集・情報発信がSNSに移りRSSはあまり使われなくなりました、さらに利用者の多かったGoogle Readerのサービスも止まりRSSは廃れて行きました。
しかし私は今でもFeedly + iOSのReeder Classicアプリを使いRSSを配信してくれるブログ等を読んでいます。

EY-OfficeでもRSSがあまり使われていない事に気が付き、ある時点からブログ更新をX(Twitter)とFacebookで告知するようにしました。そのためEY-OfficeブログのRSSフィードが止まっていることに1年以上も気が付きませんでした。

なぜEY-OfficeブログのRSSフィードが止まったか

このブログやホームページの作成にはAstroを使っています、AstroにはRSS作成機能が内蔵されているので、それを使いRSSフィードが作成しています。
Astroで最終的なサイト(HTML, CSS…)をnpm run buildで構築すると大量のログが表示されます、そして最終行には Complete! と表示されていました。
しかしログをよく見ると/rss.xml作成部分でWARN(ワーニング)が出ていましたが見落としていました。 😅

原因は、この警告にあるようにGET関数がないからでした。Astroではプログラムでコンテンツを生成するにはエンドポイントのGET関数を定義する必要がありますが、Astro V2.0までは関数名は小文字のgetでもOKでしたが、V3.0からは大文字GETのみとなりました。

  • V2.0までのRSS作成コード
import rss from '@astrojs/rss';
import { recentBlogs, getPosts } from '@utils/BlogPost';

const FeedSize = 3;

const blogs = recentBlogs(FeedSize);
const posts = getPosts();
const htmls = blogs.map((_, ix) => posts[ix].compiledContent());

export const get = () => rss({
  title: 'EY-Office Blog',
  description: 'EY-Offce Yuumi Yoshida talks about technology',
   site: import.meta.env.SITE,
   items: blogs.map((blog, ix):any=> ({
    link: blog.path,
    title: blog.title,
    pubDate: blog.date,
    description: blog.summary(200),
    content: htmls[ix]
   }))
});
  • 今回修正したRSS作成コード
import rss from '@astrojs/rss';
import { recentBlogsAndContents } from '@utils/BlogPost';

const FeedSize = 3;

export const GET = async (context: any) => {
  const blogs = await recentBlogsAndContents(FeedSize);

  return rss({
    title: 'EY-Office Blog',
    description: 'EY-Offce Yuumi Yoshida talks about technology',
    site: context.site,
    items: blogs.map((blog) => ({
      link: blog.path,
      title: blog.title,
      pubDate: new Date(blog.date),
      description: blog.summary(200),
      content: blog.content
    })
  )});
}

さらに、RSSフィードにコンテンツのHTMLを含める場合は、コンテンツ作成関数compiledContent()が非同期関数に変更されたので、この対応を含めコンテンツ作成コードはユーティリティーモジュルに移動しました。

export const recentBlogsAndContents = async (limit:number) => {
  const blogs = recentBlogs(limit);

  const contents = await Promise.all(blogs.map((_, ix) =>
    posts[ix].compiledContent()));
  return blogs.map((blog, ix) => ({...blog, content: contents[ix]}));
}

これで、RSSフィードの/rss.xmlファイルが作成されるようになりました。😄

「サイトhttps://www.ey-office.com/のページがインデックスに登録されない新しい要因」というGoogleからの警告

最近、Googleから「サイトhttps://www.ey-office.com/のページがインデックスに登録されない新しい要因」というメールが届きました。これはSEO的には重要な案件ですね。

この中で、「ページはインデックスに登録されていません: ページにリダイレクトがあります」というエラーが多数ありました。
例えば、先週のブログのURLは https://www.ey-office.com/blog_archive/2025/09/30/caludecode-can-create-draw-io-data-from-pdf/ になっています。
これは厳密には https://www.ey-office.com/blog_archive/2025/09/30/caludecode-can-create-draw-io-data-from-pdf/index.html ですがWebサーバーの仕様で最初のURLで正しくアクセスできます。

しかし、URLの最後/が無い https://www.ey-office.com/blog_archive/2025/09/30/caludecode-can-create-draw-io-data-from-pdf でアクセスするとWebサーバーはステータス301(リダイレクト)と正しいURLを戻すので、ブラウザーは正しいURLで再度アクセスしブログ記事を表示してくれます。

ページにリダイレクトがありますという警告はこの事を指摘しています。URLの最後に/が無いことがエラーの原因でした。このブログ記事はMarkdownで書いていますがブログURLの最後に/が無くてもワーニング等はなくコンテンツが出来てします。

今回はブログURLのチェックと修正(最後に/を追加)する独立ツールを作りました(このチェックはAstroインテグレーションを使えばAstroに組み込めそうですが、今回は独立ツールで止めました)。
コードは、大枠をClaudeCodeに作ってもらい、言葉で伝えにくい正規表現の部分は自分で実験しながら書きました。

#!/usr/bin/env node

import fs from 'node:fs/promises';
import path from 'node:path';

const findMdFiles = async (dir) => {
  const results = [];

  try {
    const entries = await fs.readdir(dir, { withFileTypes: true });

    for (const entry of entries) {
      const fullPath = path.join(dir, entry.name);

      if (entry.isDirectory()) {
        const subResults = await findMdFiles(fullPath);
        results.push(...subResults);
      } else if (entry.isFile() && entry.name.endsWith('.md')) {
        results.push(fullPath);
      }
    }
  } catch (error) {
    console.error(`Error reading directory ${dir}:`, error.message);
  }

  return results;
}

const fixMdLinks = async (file) => {
  let replacedCount = 0;

  try {
    let content = await fs.readFile(file, 'utf-8');
    const matchees = content.matchAll(/\(\/blog_archive\/[\w/-]+[^\/]\)/g);

    for (const matchee of matchees) {
      const replacement = matchee[0].slice(0, -1) + "/)";
      content = content.replace(matchee[0], replacement);
      console.log(`File: ${file}: ${matchee[0]} => ${replacement}`);
      replacedCount++;
    }
    await fs.writeFile(file, content, 'utf-8');
    return replacedCount;
  } catch (error) {
    console.error(`Error reading file ${file}:`, error.message);
    return 0;
  }
}

const fixMdFiles = async (targetDir) => {
  const mdFiles = await findMdFiles(targetDir);
  let totalReplacedCount = 0;

  for (const file of mdFiles) {
    totalReplacedCount += await fixMdLinks(file);
  }

  console.log(`\nTotal replacements made: ${totalReplacedCount} ` + 
    `in ${mdFiles.length} file(s).`);
}

const targetDirectory = process.argv[2] || '.';
fixMdFiles(targetDirectory);

まとめ

毎週ブログを書いデプロイ(ビルド)していましたが、長い間ワーニングを見落としていました。
私は注意深くない人間なので、このようなワーニングの見落としはまた起きる可能性があるのでソフトウェアで対応したいです。 後半の件もブログURLの最後に/が抜けているのが原因で、注意力の低さを補えるような仕掛けが必要ですね。

今後も長くブログを書くと思うので、何らかの対処コードを書いて行きたいと思います。つづく・・・

- about -

EY-Office代表取締役
・プログラマー
吉田裕美の
開発者向けブログ