| @ブログ

iPad を持っていないので確認していなかったのだけど、タブレットなど狭めの横幅のブラウザーでこのサイトのインデックスページを見ると残念な感じになっていたのでいい感じに調整した。横幅 1113px 以上だと past-entries セクションが 3 カラム表示になり、 1112px 以下だと 2 カラム表示に、 640px 以下だと 1 カラム表示になるようにした。これまでは 640px 以下のときの 1 カラム表示対応しかなくて、横幅が狭いブラウザーで見たときに悲惨なことになっていた。

デスクトップ表示
デスクトップ表示

タブレット表示
タブレット表示

スマートフォン表示
スマートフォン表示

その他、フッターの人気記事表示を変更した。インデックスページに最近の人気記事とはてブでホッテントリ入りした記事を表示するようにしたので、同じコンテンツがフッターにあるのは無駄だと感じた。かわりにフッターには今日と昨日の人気記事を表示するようにした。

今日の人気記事と昨日の人気記事
今日の人気記事と昨日の人気記事

よく読まれる記事の傾向はその日その日で結構違う。新しい記事を書くと当然その記事にアクセスが集まるのだけど、しばらく何も書いていないと意外な記事がアクセスを集めてたりして発見がある。例えば最近では Flickr の有料化についての記事がアクセスを集めていたが、 Google Photos の有料化が発表されたからだった。いっぱい記事を書いておくと、自分のブログへのアクセス傾向から世の中の動きが確認できて便利だ。

| @ブログ

インデックスページにカテゴリーへの導線を作るべきということを書いたがさすがにラディカル過ぎた。

インデックスページのコンテンツ数が増え、ページの応答速度が 800ms ほどになっていた。 DOM サイズも大きくなり、転送量が増えてユーザーフレンドリーではないなと思った。確かにユーザーの回遊性は高まるかもしれないが、ページがごちゃごちゃしていて快適ではない。これではブログサービスでブログをやっているのと大差ないと思い直し、インデックスページの記事数を最小限に絞った。

少しシンプルになったインデックスページ
少しシンプルになったインデックスページ

全カテゴリーの最新記事の表示はやめ、最新の 7 記事だけ表示するようにした(最新の記事だけ大きく表示するというスタイルは残している)。カテゴリー一覧ごとの最新記事は別途 カテゴリー一覧ページ を用意してそちらに移した。

またページ下部に最近閲覧数が多い記事とはてブでホッテントリ入りした記事へのリンク1を付けた。これまではフッターに表示していたが、フッターのリンクはあまりクリックされていない疑惑があるし、結構面白コンテンツだと思うのでインデックスページのメインコンテンツとしてしつらえることにした。そもそも 21 世紀のブログでフッターなんてものはいらないのかもしれない。

人気記事一覧
人気記事一覧

シンプルにしたインデックスページは応答速度が 200ms を切っていてまぁまぁ高速で Google PageSpeed Insights でも 90 点くらいを取れる。個人ブログなのでシンプリシティは大切にしたい。

| @ブログ

インデックスページをいじって各カテゴリーの最新記事 4 件を配置するようにしてみた。最近の個人サイト復興ブームでみなさんインデックスページを工夫されているのを見ていて真似したくなってやった。

カテゴリーごとに最新記事 4 件を表示
カテゴリーごとに最新記事 4 件を表示

昔ながらのブログだとインデックスページというのは最新の記事 10 件くらいが表示されていて、「次へ」を押すと古い記事が出てくるという構成になっている。以前のこのブログもそうだった。

しかし自分自身が他人のブログで「次へ」を押して次々に記事を読んでいくということをやった記憶がほとんどない。自分のブログでだって何か目的があって特定のキーワードで検索したあとに引っかかった記事を読むという感じなので、時系列に本文とセットで記事が 10 件ずつ表示される UI というのは意味をなしていないと思った。そもそもインデックスという名称なのに最近の記事数件しか表示していないのはおかしい。インデックスというからにはすべての記事の目次になるべきだ。

このブログはカテゴリーがあるので、サイトマップを作るとするとこんな感じになると思う。

+----------+        +------------+        +-----------+
|          |        |            |        |           |
|   Blog   +---+--->+  Category  +------->+   Entry   |
|          |   |    |            |        |           |
+----------+   |    +------------+        +-----------+
               |
               |
               |    +------------+        +-----------+
               |    |            |        |           |
               +--->+  Category  +---+--->+   Entry   |
                    |            |   |    |           |
                    +------------+   |    +-----------+
                                     |
                                     |
                                     |    +-----------+
                                     |    |           |
                                     +--->+   Entry   |
                                     |    |           |
                                     |    +-----------+
                                     |
                                     |
                                     |    +-----------+
                                     |    |           |
                                     +--->+   Entry   |
                                          |           |
                                          +-----------+

第一階層がインデックスページで、第二階層がカテゴリートップ、そして各記事がある。なのでインデックスページは二階層目の一覧ページになっているのが望ましいはずだ。しかし伝統的なブログはカテゴリーという記事をまとめる概念がありつつも、インデックスページから各記事ページへ直接遷移するのが主な導線だった。常に最新の記事が時系列順に並んでいるだけでは味気ないし、常連の読者ではないコンテキストを知らない訪問者には不親切だろう。

しかも SNS の隆盛で個人のブログのインデックスページが参照される機会というのはとんとなくなってしまった。個人が書いたブログ記事は SNS 経由で読まれ、個別記事だけが読まれる。インデックスページやトップページが読まれることはほとんどない。 SNS でシェアされている URL をクリックして個別記事を読んで、それ以上そのブログのほかの記事を読むことなく離脱してしまう。前後のコンテキストは無視して、一つのコンテンツだけがつまみ食いされてしまう。そんな流れにあらがいたいと思った。

これまで関連記事を記事下に表示するなどやってきたが、気に入っていくつか記事を読んで「ホーム」( = インデックスページ)を訪れたユーザーがもう少しブログを深掘りしてみたくなるようにインデックスページを各カテゴリーの最新記事一覧とするようにしてみた。このブログは現在カテゴリーが 13 個あるので、それぞれから 4 件ずつ記事を取得すると 52 記事になる。全カテゴリーからまんべんなく 4 記事ずつ取得して表示するのは簡単なようで結構難しい。普通の SQL ではできない。 OR マッパーではまず無理だろう。

いろいろ調べてみた結果、 MySQL では GROUP_CONCAT というのが使えそうだった。以下のような SQL を書いた。

select entries.id
from entries
inner join (
  select
    category_id,
    GROUP_CONCAT(id order by created_at desc) as entry_ids,
    max(created_at) as last_created_at
  from entries
  where entries.draft = false
  group by category_id
) as grouped_entries
on grouped_entries.category_id = entries.category_id
and FIND_IN_SET(id, entry_ids) between 1 and 4
order by last_created_at desc, entries.id desc;

GROUP_CONCATFIND_IN_SET という関数を組み合わせることで、各カテゴリーから作成日の降順に記事を 4 件ずつ取得できた。このクエリでは記事 id のみ取得して、もう一回 DB に記事を取得するクエリを ActiveRecord で投げる。 ActiveRecord でクエリを組み立てるときは N+1 が起こらないように関連テーブルを JOIN する。

query = <<~SQL
  select entries.id
  from entries
  inner join (
    select
      category_id,
      group_concat(id order by created_at desc) as entry_ids,
      max(created_at) as last_created_at
    from entries
    where entries.draft = false
    group by category_id
  ) as grouped_entries
    on grouped_entries.category_id = entries.category_id
    and find_in_set(id, entry_ids) between 1 and 4
  inner join categories on categories.id = entries.category_id
  order by last_created_at desc, entries.id desc;
SQL
entry_ids = ActiveRecord::Base.connection.select_all(query).rows.flatten
entries = Entry.includes(:category, :user, :tags, :comments).where(id: entry_ids)

PostgreSQL のときに最初に取得した entry_ids の並び順通りに結果が受け取れるかは怪しいが、 MySQL の場合は一回目のクエリで取得した id 順に各レコードが ActiveRecord のクエリ結果として取得できた。あとはこれをカテゴリーごとにグルーピングして View でよろしくやれば良い。

なお各カテゴリーはカテゴリー内の最新の記事の作成日で降順ソートするようにしている。例えば現在のインデックスページの最下部には音楽カテゴリーがあるが、これは音楽についての記事を最後に書いたのが一年以上前だからだ。もしいま音楽の記事を書けば音楽カテゴリーがトップに浮上するようになっている。

見た目に関しては各カテゴリーの記事最新一件は大きなサイズで表示している。最も最近書かれた記事なのでより多く人の目に付いた方がよいだろうという考えだ。またすべての記事にサムネイルというか、アイキャッチ画像を表示するようにした。画像がない記事に関してはデフォルトのサイトアイコン画像を表示するようにしている。やっぱり視覚的に情報を捉えられるのは重要だ。画像がごちゃごちゃ表示されるのを嫌う人もいるかもしれないが、テキストだけでは人間の認知というのはどうしても追いつかない。

あわせて今回、インデックスページの冒頭部にこのサイトについての説明文を載せることにした。ながしまきょうさんr7kamura さんがやっているののパクりだ。伝統的なブログのインデックスページは初めて訪れた人のことを無視しすぎていたと思う。そのブログ自体について説明するページがあるブログは少ない。最初の記事でブログを始めた経緯みたいなことが書かれたきり、そのブログは何なのか、誰が書いているのかが書かれることは希だ。きちんとブログについての説明ページと著者についての説明ページがあっても、左右のサイドバーやトップのナビゲーションの端っこに押し込まれて見られることはない。これではいけないだろう。というわけでインデックスページの一番目立つ位置にブログと自分自身の簡単な紹介を入れた。

インデックスページトップに紹介文を表示
インデックスページトップに紹介文を表示

ブログはなぜ衰退したかを考えてみると、 Facebook や Twitter の隆盛はあるにせよ、ブログ自体に初めて訪れた人に読まれるための工夫が欠けていたのだと思う。誰も自分のブログの継続率を計測したりコホート分析したりはしない。読者が前後の記事を読んでいることを前提に書かれた記事やサイト構成では初めて訪れた人はどうやっても離脱してしまう。特に書き手が芸能人でもない一般人の場合はなおさらだ。誰も RSS フィードを購読していないし、ほとんどの読者は初めて訪れる人なのだから、そういう人たちが読んでブログのテーマや著者の人となりが分かる構成にしていかなければならないのだと思う。でないと SNS でたまにバズったときだけ読んでもらえる、ソーシャルメディアの肥やしにしかならない。

この新しいインデックスページが正解なのかどうかは分からないが、ブログ衰退の流れにあらがっていきたい。

| @ブログ

画像を拡大できるようにしたいという欲求は前々からあった。この手のものでは Lightbox が有名だが、 jQuery べったりなのでいまさら使いたくない。 P_BLOG の頃は FacyZoom というやつを使っていて好きだったが、 2008 年から更新されていない。何かいいのがないかなと探していて Medium Zoom というのを見つけた。

ブログサービスの Medium の画像拡大機能のコピープラグインだ。 npm パッケージになっているので導入も楽だった。

実際のこんな感じ。

Medium Zoom 利用風景
Medium Zoom 利用風景

| @ブログ

blog.8-p.info の過去記事ページの真似をして、 Archive ページにタグを表示するようにしてみた。

Archive ページにタグを表示
Archive ページにタグを表示

タグはあまり使っていなかったのだけど、一覧で記事タイトルだけ並んだときその記事にどんな内容が書いてあるのかを把握するためにはタグが便利だなと思い直し、タグを表示させてみることにした。いくつか過去のタグが付いていない記事にタグを振ってもみた。

このブログは技術情報からポエム、日々の日記まで何でもありのごった煮ブログなので、カテゴリーによる情報分類には限界がある。現在 13 個のカテゴリーがあるが、記事数にバラツキがあり、情報分類としてあまり機能していない。カテゴリーの粒度をもっと荒くして緩い分類に変更し、そこから先はタグによって超細かくラベリングすると情報の分類としてはまともになるのではないかと思った。

いま、カテゴリーの内訳がこんな感じ。

- "雑談":303
- "技術/プログラミング":272
- "映画/ドラマ/テレビ":150
- "Mac/iPhone":134
- "WWW":113
- "散財":95
- "旅行/ハイキング":70
- "ブログ":69
- "音楽":63
- "読書":34
- "写真":32
- "料理/食事":31
- "労働":27

もっと緩い分類にして以下みたいな感じにするとよさそう。

- 雑記
- パソコン・インターネット
- 見た・読んだ・聞いた
- 出かけた・撮った・食べた

カテゴリーとタグの使い分けは 10 年以上前から悩んでいる気がする。

情報分類の手法でありつつコンテンツの内容そのものを指し示すものでもあるからだろう。インスタグラムで #ラーメン #からの #うどん とかやってる投稿を見るととても嫌な気持ちになるのだけど、そういうことがされるくらいにタグというものは不安定なもので、正しく使おうとか気負わず、もっと緩く使えばいいのかもしれない。

もう廃れてしまったが、フォークソノミーが勢いを取り戻して、情報の発信者ではなく受け取り側がコンテンツにタグ付けできるような世の中になるとおもしろいのかもしれない。

| @ブログ

Archive ページにその月の記事数を表示
Archive ページにその月の記事数を表示

Archive ページの月コンポーネント右肩にその月の記事数を表示するようにしてみた。その月の自分の頑張り具合が一目で確認できて便利。 Kazuyoshi Kato さんの blog.8-p.info の真似。

ただ、いま見てたら blog.8-p.info では記事の文字数も表示されるようになっていた。 blog.8-p.info の過去記事ページは非常に参考になる。

blog.8-p.info の過去記事ページ
blog.8-p.info の過去記事ページ

| @ブログ

tech.portalshit.net の記事を取り込んだとき、記事ファイルの作成日を記事作成日として取り込んでいた。

Jekyll 移行後の記事の場合はそれで良いのだが、 Mephisto 時代の記事はデータベースから一度 Jekyll に移行した都合上、ファイルの作成日が Mephisto から Jekyll への移行作業を行った日になっており、 2011 年の 3 月 8 日に大量に記事を書いたことになっていた。作成日が 2011 年 3 月 8 日になってる全ての記事を見てまわって日付を元の記事作成日に変更する作業をやった。 Jekyll はファイルパスに日付が残る仕組みなのでその日付を使った。残念ながら作成時刻は調べようがないので諦めた。静的サイトジェネレーターを好きになれない理由の一つに記事の作成日時や更新日時がメタデータとして残らないことがあったのを思い出した。

今回の修正により 2010 年の記事数が増えて 2011 年の記事数が減った。 2011 年はブラック企業に転職するために福岡に引っ越してきたのでろくに記事が書けてなかったはずだが、それでも 57 記事書いていた。一つ前の記事が 2020 年の記事としては 57 個目だったので今年は 9 年ぶりに記録を更新した。 #100DaysToOffload に挑戦中なので 10 年ぶりの年間 100 記事達成目指して頑張りたい。