チーム個々人のテックブログをRSSで集約するサイトを作った(Next.js)
先日、こんな記事を見かけました。
採用目的でテックブログを始めたものの、時間の経過とともに古い記事ばかりになる or すでに退職している社員の記事ばかりになる…というのはよく見かける光景です。
目の前のタスクが積み上がっている状況で、業務時間内にブログを書く時間を取るのはなかなか難しいと思います。
そうは言っても業務時間外に無償で会社のブログに書くのもなかなか気乗りしません。「数年以内に転職するかもしれない」という気持ちがあればなおさらです。記事が転職しても自分のものとして残るのであれば、書くモチベーションは上がるのかもしれません。
その後、こんなツイートを見かけました。
企業のテックブログと言えば「会社がひとつブログを作って、みんなでそこに投稿する」という形が当たり前になっていますが、たしかに個々人の投稿を集約する場所を用意するだけでも良いのかもしれません。
もう少し調べてみるとHERP社のテックブログはまさにそのような形になっています。メンバーは個人ブログなど自分の好きな場所に記事を投稿し、会社のテックブログはその記事へのリンクを集約して表示するハブの役割をすると。とても良いですね。
チームメンバーのテックブログをRSSで集約するサイトを作った
RSSを辿って社内メンバーの個人ブログを集約するというのは、技術的にそこまで難しくありません。最近Zennの開発ばかりやっているので、息抜きがてらスターター的なものを作ってみました。
デモサイトはこんな感じ
デモサイトを見ていただければ分かると思いますが、個々人が投稿した記事へのリンクを集めた入り口のような場所になっています。
各メンバーは、Zenn、Qiita、Medium、note、はてなブログなど、自分の好きな場所に、自分の記事として投稿できます。RSSを取得できさえすれば、どこに投稿してもOKというわけです。
技術的な構成
サイトの構築にはNext.js(TypeScript)を使いました。以下のような流れで静的なサイトがビルドされるようになっています。
- 各メンバーのRSSのURLから投稿データのフェッチする
- 1をまとめて投稿データ一覧のjsonファイルを作成する
- Next.jsで静的サイトとしてビルドする
メンバーのRSSの登録
ソースコードを見ていただくと早いと思いますが、members.ts
というファイルの中で各メンバーのプロフィールとRSSのURL一覧を登録する形になっています。
[{
name: "メンバーの名前",
role: "役職名",
sources: [
"https://zenn.dev/catnose99/feed",
"https://medium.com/feed/@catnose99",
]
}]
👆sources
の部分にRSSのURLを指定します。複数のURLを指定することもできます。
正規表現で一部の記事を除外できるように
一部の記事は会社のテックブログから除きたい(or含めたい)こともあると思うので、下記のように正規表現を指定することでフィルターをかけられるようにしました。
[{
...
sources: [
"https://zenn.dev/catnose99/feed",
"https://medium.com/feed/@catnose99",
],
includeUrlRegex: "含めたい記事のURLにマッチする正規表現",
excludeUrlRegex: "除きたい記事のURLにマッチする正規表現"
}]
yarn build:posts
が実行されたときに、指定内容をもとにRSSから投稿のメタデータ一覧をフェッチしてposts.json
という記事の情報をまとめたファイルが生成されます。RSSのパースはrss-parserというパッケージを使うと簡単です。
Next.jsで静的サイトをビルドする
Next.jsを使えば、静的なサイトも簡単に作れます。今回は上述の通りposts.json
という投稿データ一覧がディレクトリ内に存在するため、ここから必要なデータをimport
して表示するだけです。
Next.jsでアプリを作るときに頻繁に使いがちなgetInitialProps
やgetStaticProps
などもほとんど必要ありません。
デプロイ
デモサイトはVercelにデプロイしました。npm run build
(yarn build
)さえホスティング前に実行できれば、デプロイ先はどこでもOKです。
チームで運営する場合には、CI/CD環境を整えると管理しやすそうです。新しく社員が入ってきたときに「個人ブログのRSSのURLを追加してプルリク投げておいて」とお願いできるとお互い楽ですね。
そういう意味でリポジトリとの連携がしやすいVercelやNetlifyなどがおすすめです。
定期的に自動ビルドする
実際の運用では、投稿一覧を更新するために、定期的に(1日に1回など)自動でビルドを行う必要があります。
-
Vercelの場合、GitHub Actionsの「cron」を使えば、定期的な自動デプロイを楽に設定できます。詳しくはGitHubのDiscussionが参考になると思います。
-
Netlifyの場合はAuto trigger deploys on Netlifyのような方法で自動デプロイできます。
ライセンス
今回作ったものはオープンソースです。Forkしてご自由にお使いください。
チームでなくとも個人で使っていただくのも良いかもしれません。たとえば、noteとMediumとZennに投稿している方は、同じ仕組みを使って一箇所に投稿一覧をまとめることができます。
※ 真っ先に変えたいのは配色だと思います。使用する色の数を抑えつつ、カラーコードはCSS変数で管理しているため、比較的変更しやすいと思います。
Discussion
🙏
質問ってここで良いのでしょうか?
私もこれを使って自分のブログを1箇所で見れるようにしてみました。
ありがとうございます。
質問というのは最初の頃はうまく動いてるように見えたんですが最近zennへの投稿数と取得されてる記事の数が合わない事に気づいたのです
自分でも調べてみたのですがJS系の開発経験もなく原因がよくわかりませんでした。
私がやったのはposts.tsのfetchFeedItems関数に
を追加してビルド時に取得できた記事の数を表示させてzennの自分の記事数と比較したり
として他の人のRSSではどうかと確認したりしたんですがどちらも記事数が合わなくなってしまいました。
またrss-parserという外部モジュールが記事を認識できていないのが原因かと思い
package.jsonのバージョン指定の部分を
に書き換えて最新のものを取得し直してみたりしましたが結果が変わりませんでした。
この段階で手詰まり状態に陥ってしまったのですが
なにか他に試せるようなことがあればご教授願えないでしょうか?
すいません自己解決しました
zennのRSSは最新15件だけ返却されるんですね😓
自分のTOPページに出てるArticlesの数と比較してたので気づきませんでした
ふと実際のRSSのitemフィード数えたら15件だったので表示出来てました
お騒がせしました😖
ありがとうございます。
もしかするとなのですが、RSSの最大表示件数によるものかもしれません。Zennに関わらずほとんどの投稿サービスではRSSの最大表示件数が10〜20程度に制限されています。RSSリーダーが最大10程度までしかフェッチを行わないため、パフォーマンスのために制限を設ける形になっています。
ZennでもRSSに載るアイテム数は最大15となっています。noteだと25みたいですね。Zennの方でURLに
?limit
をつけることで最大アイテム数を変えられるようにできないか検討してみますね。noteの方はどうにもできませんが…
あ、コメントを見逃していました!ちなみに、以下のURLを叩くと
tantan_tanuki
さんの全ての記事一覧が取得できます。jsonをいじる必要は出てきますが、それでもよければご活用ください🙏ただの勘違いだったのに丁寧な返信ありがとうございます!
全記事取得するAPIがあるんですか
フロントエンド周りはかなりスキル低いので頑張ってみます😆
遅くなってしまいましたが、フィードページにおいて
https://zenn.dev/ユーザー名/feed?all=1
のようにall=1
というクエリ文字列を指定することで全ての投稿アイテムを出力できるようになりました。おぉ!ありがとうございます
こういう隠しコマンドみたいなの面白いですw
早速取り込みました
記事数が多くなるとLOAD MOREボタンで記事追加読み込み出来るの初めて知りましたw
何度もすいません。
記事内容と違う内容の相談になってきてしまうのですが
私の感じてた違和感がなんとなく掴めてきたのでご相談させて下さい。
この記事の内容なのですが
継続して確認していた所たまに過去のRSSが取得される事象が起きて
それが反映されているのではないかという気がします。
以下を見ていただきたいのですが
こんな感じでcurlとwgetで同じRSSにアクセスするとかなり前のフィードが取得される事があります
curlとwgetの違いを確認した所リクエストヘッダに
Accept-Encoding:identity
が付くようでcurlにこのヘッダを付けてリクエストするとwgetと同じ記事が取れるようになったりもします。
そこで昨日一日なにも更新せずに以下のような手法で確認していたのですが
午前中は日付を跨いだ瞬間に1件だけ違うパターンが紛れ込みましたが大体1時間位ずれた2パターンのfeedがランダムに取得されるという挙動になりました。
また私ではないのですが他の人のRSSでこの揺れの間に記事を更新されている方の記事が巻き戻っている事も確認できました。(ログが残ってないので申し訳ない)
そこで更に確認のため以下のように確認してみました
ここでcurlとwgetで取れる記事が違いさらにそれぞれで2パターンの記事が取得されるようですので
少なくとも4パターンのRSSが取得される可能性がありそうです。
Wed, 07 Apr 2021 14:18:55 GMT
Wed, 07 Apr 2021 21:15:41 GMT
Thu, 08 Apr 2021 00:49:54 GMT
Thu, 08 Apr 2021 00:50:21 GMT
内部の構造がわからないので憶測になりますが
この返却のパターンから考えてLBの裏に2台RSSを配信しているサーバがいて
そのサーバ毎にキャッシュされているRSSが違うのではないか?
そしてそのキャッシュはリクエストヘッダによって変わるレスポンス内容毎に別々にキャッシュを保存しているのではないか?
というのが私の見解なのですがこれ以上ちょっと調べるのが難しいのと
そもそも全然見当違いの推測をしているかもしれないので
申し訳ありませんが何かわかることがあればご教授願えないでしょうか?
すみません、見落としてました。
こちらのキャッシュの問題についても解消済みです。
お忙しい中対応いただいてありがとうございました🙇
こちらのteam-blog-hubを使いたいと思い。試してみたのですが、以下のようなエラーが出てしまいました。
私の力では解決できなかったので、お力添えいただけますでしょうか。
npx browserslist@latest --update-db
のコマンドで解消されるか試しましたが、解消されませんでした。yarn dev
を実行する前に一度yarn build
の実行が必要です(yarn build
を実行するとposts.json
が生成されます)。ありがとうございます。
yarn build
を実行後にエラーが出てしまいました。説明が不足していました。エラーの内容のすべてです。
./src/builder/posts.ts
でエラーが生じており、posts.json
を生成することができませんでした。何度も申し訳ありません。
あ、今確認したところエラーが再現できました。
一部のRSSのURLが404になっており、そのせいでビルドに失敗してしまっていたようです。
この部分を修正すると動くようになると思います!
ありがとうございます。動作しました。対応していただきありがとうございました。