Closed12

AstroでWeb制作する時のTips集 🚀

Y.Y.

Sassを使う

インストール

npm i sass

mixinを各SCSSファイルにimportする

下記を追加することで@useでファイルを読み込まなくても全CSSファイルでstyles/_variables.scssに記述したmixinが使えるようになる。

astro.config.mjs
import { defineConfig } from "astro/config";

// https://astro.build/config
export default defineConfig({
  vite: {
    css: {
      preprocessorOptions: {
        scss: {
          additionalData: '@use "src/styles/_variables.scss" as *;',
        },
      },
    },
  },
});

こんな感じ👇

Header.astro
.header {
    margin: 0;
    padding: 0 1em;
    background: white;

    @include mq(sm) {
        display: none;
    }
}
Y.Y.

Vercelへデプロイする

Vercelアダプターのインストール

npx astro add vercel

質問に答えていく

Yes

 Astro will run the following command:
  If you skip this step, you can always run it yourself late

 npm install @astrojs/vercel 

No(SSRする場合はyes)

 Astro will make the following changes to your config file:

- astro.config.mjs
import { defineConfig } from "astro/config"; 
import vercel from "@astrojs/vercel/serverless";

export default defineConfig({ ・・・ 省略

リポジトリをインポート

Vercelの管理画面で対象のリポジトリをインポートして、各設定をすればデプロイ完了 🎊

Y.Y.

Prettierを導入する

インストール

PrerrierとAstro用のPrettierをインストールする。

npm install prettier-plugin-astro prettier

設定ファイルをつくる

ルート直下のファイルで次の設定を行う

/.prettierrc.cjs
module.exports = {
  plugins: [require.resolve('prettier-plugin-astro')],
  overrides: [
    {
      files: '*.astro',
      options: {
        parser: 'astro',
      },
    },
  ],
};
Y.Y.

pnpm を使用したときにbuildが通らないエラーの解決法

事象

pnpm buildをすると次のエラーがでる

generating optimized images
node:internal/process/promises:288
            triggerUncaughtException(err, true /* fromPromise */);
            ^

MissingSharp: Could not find Sharp. Please install Sharp (`sharp`) manually into your project or migrate to another image service.

解決策

sharp をインストールすればビルドが通るようになる。

pnpm i sharp

何が悪かったのか?

Astroは画像処理にSharpを使用しているが、pnpmのような厳格なパッケージマネージャを使用している場合は、手動でSharpをインストールする必要がある。

参考:https://docs.astro.build/ja/reference/errors/missing-sharp/#what-went-wrong

Y.Y.

フォントのパフォーマンスを最適化する

下記のパッケージをインストールしてフォントを読み込むことでパフォーマンスがあがる。Next.jsのフォント最適化にインスパイアされて作られたらしい。
https://github.com/sebholstein/astro-google-fonts-optimizer

使い方

  1. 依存関係をインストール
pnpm add astro-google-fonts-optimizer
  1. <head>内に埋め込む
layout.astro
---
+ import { GoogleFontsOptimizer } from 'astro-google-fonts-optimizer';

・・・省略
---

  <head>
    <meta charset="UTF-8" />
    <meta name="description" content="Astro description" />
    <meta name="viewport" content="width=device-width" />
    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
    <meta name="generator" content={Astro.generator} />
+   <GoogleFontsOptimizer url="https://fonts.googleapis.com/css2family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" />
    <title>{title}</title>
  </head>
  1. CSSでフォントを指定する
global.css
body {
    font-family: Montserrat, sans-serif;
}

※Tailwind CSSの時

tailwind.config.js
/** @type {import('tailwindcss').Config} */
export default {
  content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
  theme: {
    extend: {
+    fontFamily: {
+      montserrat: ['Montserrat', 'sans-serif'],
+    },
    },
  },
 ・・・省略
};
global.css
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  html,
  body {
    @apply font-montserrat;
  }
}
Y.Y.

Astro Sitemapで XMLサイトマップを生成する

公式のインテグレーションがあるのでインストールする。
https://docs.astro.build/en/guides/integrations-guide/sitemap/

pnpm astro add sitemap

astro.config.mjsintegrationssiteプロパティを追記する。

astro.config.mjs
import { defineConfig } from 'astro/config';
import sitemap from '@astrojs/sitemap';

export default defineConfig({
  // ...
  site: 'https://example.jp',
  integrations: [sitemap()],
});
Y.Y.

astro-seoを使ったメタタグの設定方法

https://github.com/jonasmerlin/astro-seo

Head.astro
---
import "@styles/global.css";

import { SEO } from "astro-seo";

export interface Props {
  title?: string;
  description?: string;
  noindex?: boolean;
}

const props = Astro.props;

const BASE_TITLE = "Title";
const title = props.title ? `${props.title} | ${BASE_TITLE}` : BASE_TITLE;

const BASE_DESCRIPTION ="Base description";
const description = props.description ?? BASE_DESCRIPTION;
---

<!DOCTYPE html>
<html lang="ja">
  <head>
    <SEO
      title={title}
      description={description}
      noindex={props.noindex ?? false}
      charset="UTF-8"
      openGraph={{
        basic: {
          title,
          type: "website",
          image: "/opengraph.png",
        },
      }}
      extend={{
        link: [{ rel: "icon", href: "/favicon.ico" }],

        meta: [
          { name: "viewport", content: "width=device-width" },
          { name: "twitter:card", content: "summary_large_image" },
        ],
      }}
    />
Y.Y.

インポートエイリアスの設定

importをすべて相対パスで書くのは大変なので、インポートエイリアスで絶対パスでimportする。
https://docs.astro.build/ja/guides/aliases/

astro.config.ts
{
  "extends": "astro/tsconfigs/base",
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"],
      "@/js/*": ["src/assets/js/*"]
    }
  }
}
Y.Y.

カレントページを取得する

src/components/NavLink.astro
---
const { pathname } = Astro.url;

// pathname(URLのパス部分を表す文字列)からスラッシュ(/)によって区切られたすべての部分(サブパス)を抽出
// pathnameが ./blog/article であれば blog と article を取得する
const subpath = pathname.match(/[^\/]+/g);

// 現在アクセスされているページ(pathnameで表される)と同じであるか、またはpathnameの最初のサブパスに相当するかどうかをチェック。
const isActive = href === pathname || href === `/${subpath?.[0]}`;
---

<a href={href} class:list={["link",className, { active: isActive }]} {...props}>
    Link
</a>
.active {
    text-decoration: underline;
    text-underline-offset: 6px;
    text-decoration-thickness: 2px;
}
Y.Y.

class:listでclassを動的に制御する

Astro.propsからclassプロパティを取得し、それをclassNameという名前の変数に割り当て、Astroのclass:list属性でcontainerというクラス名と、className変数の値が含まれる配列を渡す。

<div>要素には常にcontainerクラスが適用され、さらにclassName変数に値があれば、そのクラスも適用されるようになる。

src/components/Container.astro
---
const { class: className} = Astro.props
---

<div class:list={["container", className]} {...props}>
    <slot/>
</div>

<style>
  .container {
    max-width: 1200px;
    margin-inline: auto;
  }
</style>

こうすることで子コンポーネント側でのみwideクラスにCSSを設定できる。classが空の場合はデフォルトのスタイルのみ適用される。

index.astro
<Container class="wide">
    <h1>Title</h1>
</Container>
Y.Y.

動的ルートでtransition:nameを使用する

前提

  • AstroのView Transitions APIを利用していること
  • src/blog/[...slug].astroのような動的ルーティングを行なっていること
このスクラップは2024/04/15にクローズされました