Astro3.4

作成:
heroimage

もう3.4なの!?

この前3.3になったと思ったら

Astro 3.3: Picture component | Astro
Astro 3.3 is out with a brand new, experimental Picture component, improved compatibility for syntax highlighting, and package provenance.
Astro 3.3: Picture component | Astro favicon https://astro.build/blog/astro-330/
Astro 3.3: Picture component | Astro

二週間で3.4になったAstro。

Astro 3.4: Page Partials | Astro
Astro 3.4 is now released with support for page partials, improved image optimization performance, and an early preview of a new dev overlay.
Astro 3.4: Page Partials | Astro favicon https://astro.build/blog/astro-340/
Astro 3.4: Page Partials | Astro

Page Partialsが新たな機能だが、特に自分にはこの機能は関係なさそうではある。

画像コンポーネントのパフォーマンス改善は良いアップデート。

そんなわけで最大の問題だったMarkdown内の画像が最適化できない問題をプラグインを導入して解決し、カテゴリー部分の修正をした。

/src/assets/に画像を入れてMarkdownファイルから画像を参照すれば画像最適化はAstroが行うがMarkdownファイルがAstroに依存した相対ファイルパスを含んだものになるので将来の互換性を考えて避けたい。将来的にファイルの場所や機能の融通が効くようになれば公式のものを利用することにする。

Markdownファイルの画像最適化

Gatsbyにあったような画像最適化プラグインを作成している方がおられたのでこのプラグインを導入する。

GitHub - seesjays/astro-remark-eleventy-image: Astro Integraton that automatically optimizes images referenced in markdown files.
Astro Integraton that automatically optimizes images referenced in markdown files. - seesjays/astro-remark-eleventy-image
GitHub - seesjays/astro-remark-eleventy-image: Astro Integraton that automatically optimizes images referenced in markdown files. favicon https://github.com/ChrisOh431/astro-remark-eleventy-image
GitHub - seesjays/astro-remark-eleventy-image: Astro Integraton that automatically optimizes images referenced in markdown files.

Astro Remark Eleventy Imageの導入

Githubに書かれているようにインストールする。

npx astro add astro-remark-eleventy-image

非公式プラグインである旨などが表示され許可を求めてくるのでYを押していく。

インストール後に/astro.config.mjsに追記する。

//省略
  integrations: [
    sitemap(),
    astroImageTools,
    mdx(),
    remarkEleventyImage({
      sizes: "(max-width: 700px) 100vw, 700px",
      remoteImages: false,
      altRequired: true,
      customMarkup: customMarkup,
      eleventyImageConfig: {
        formats: ['webp'],
        widths: ['auto', 600, 1000, 1400],
        sharpOptions: {
          animated: true
        }
      },
    })
  ],
  vite: {
    ssr: {
      external: ["@11ty/eleventy-img"],
    },
  },

デフォルト設定で良いなら以下のように書く。

//省略
export default defineConfig({
  integrations: [sitemap(),astroImageTools,mdx(),remarkEleventyImage()],
  vite: {
    ssr: {
      external: ["@11ty/eleventy-img"],
    },
  },
});

viteの記述についてGithubによると

Astroが利用しているバージョンのViteではeleventy-imgでエラーが発生するため、このパッケージを使用するにはこのスニペットをastro-configに含めます

とのこと(Google日本語翻訳)

カスタムマークアップ

customMarkupは独自のマークアップをしたいときに指定する。同ファイル内に記述する。

export function customMarkup({ src, sources, width, height, alt }) {
  return `
  <picture>
  ${sources}
  <img
    class="u-photo"
    src="${src}"
    width="${width}"
    height="${height}"
    alt="${alt}"
    loading="lazy"
    decoding="async">
   </picture>
   `;
}

これでclassにu-photoがつけられたのでわざわざ<img>タグをMarkdownファイル内に書いてBridgy-Fedに合わせる必要はなくなった。

build時に画像が生成される

これでbuild時にMarkdownから参照されている画像が設定に合わせた画像最適化が行われ、最適化された画像が元画像と同じフォルダに出力されるようになる。

カテゴリーページの修正

ややこしい手順でカテゴリーページが生成されていたものを以下のように修正した。

---
// /src/pages/note/category.astro
import BaseLayout from "@layouts/NoteLayout.astro";
import { getCollection } from "astro:content";
import NoteList from "@components/NoteList.astro";
import Tags from "@components/Tags.astro";
import type { CollectionEntry } from "astro:content";
import { sortByDate } from "@utils/sortByDate";
import Section from "@components/Section.astro";

const collection_name = "note";
const blogEntries = await getCollection(collection_name);
const tags = [...new Set(blogEntries.map((post) => post.data.tags).flat())];
const all_name = "すべてのNote";
interface NAMES_OF_CATEGORY {
  [key: string]: CollectionEntry<typeof collection_name>[];
}
const namesOfCategory: NAMES_OF_CATEGORY = {};
const category = [
  ...new Set(blogEntries.map((post) => post.data.category).flat()),
];
category.sort();
category.push(all_name);

// undefined要素の除去
const category_list = category.filter(
  (category): category is Exclude<typeof category, undefined> =>
    category !== undefined
);

category_list.map(async (cats) => {
  namesOfCategory[cats] = await getCollection(collection_name, ({ data }) => {
    return data.category?.includes(cats) === true;
  });
  namesOfCategory[cats]?.sort(sortByDate);
});
/* 2023-01-28 */
/* なぜか一度はここで配列を読み込まないと上記で読み込んだものが反映されない awaitのせい? */
namesOfCategory[all_name] = (await getCollection(collection_name)).sort(
  sortByDate
);
---

<BaseLayout pageTitle="カテゴリー別NOTE" description="個人的なノート">
  <Section>
    <h1>カテゴリー別NOTE</h1>
    <Tags tags={tags} baseUrl="/note/" />
    {
      (
        <>
          {category_list.map((cats) => {
            return (
              <>
                <h2>{cats}</h2>
                <ul style="list-style:none;">
                  {namesOfCategory[cats]?.map((posts) => {
                    return (
                      <NoteList entry_name={collection_name} post={posts} />
                    );
                  })}
                </ul>
              </>
            );
          })}
        </>
      )
    }
  </Section>
</BaseLayout>

ここは今もよくわからない。

---
/* 2023-01-28 */
/* なぜか一度はここで配列を読み込まないと上記で読み込んだものが反映されない awaitのせい? */
namesOfCategory[all_name] = (await getCollection(collection_name)).sort(
  sortByDate
);

最後に

Astroのバージョンアップの速さは異常。