ネットソリューション

Astroで静的HTML納品データを作る

こんにちは。ネットソリューション事業部の山下です。
Astro使ってますか?

コンポーネントベースで構築しながら、最終的には静的HTMLで書き出しもできる!というのが便利に感じており、いまでは新規案件では可能な限りAstroを使って製作を進めるようにしてきました。
(あと単純に開発環境が軽い)

今回は、そんな私のAstro環境についてご紹介します。

※クライアントには静的HTML一式での納品をするという前提でのお話です。

package.json

プロジェクトで使用している主なパッケージは以下の通りです。
画像軽量化の設定も組み込んでいます(詳細は第4回の記事build時にpublicフォルダ内の画像も軽量化するを参照してください)。

package.json
{
  "name": "my-astro-project",
  "type": "module",
  "version": "0.0.1",
  "scripts": {
    "dev": "astro dev",
    "start": "astro dev",
    "build": "astro check && astro build",
    "postbuild": "npm run optimize-images && npm run prettier",
    "preview": "astro preview",
    "astro": "astro",
    "prettier": "prettier --write './dist/**/*.{css,html}' --ignore-path .prettierignore",
    "optimize-images": "node optimize-images.mjs"
  },
  "browserslist": [
    "iOS >= 15",
    "last 2 ChromeAndroid versions",
    "last 2 Chrome versions",
    "last 2 Edge versions",
    "last 2 Firefox versions",
    "last 2 safari major versions"
  ],
  "volta": {
    "node": "20.10.0",
    "npm": "10.2.3"
  },
  "dependencies": {
    "@astrojs/check": "^0.9.3",
    "astro": "^4.15.10",
    "sass-embedded": "^1.79.4",
    "typescript": "^5.6.2"
  },
  "devDependencies": {
    "autoprefixer": "^10.4.19",
    "imagemin-cli": "^8.0.0",
    "imagemin-mozjpeg": "^10.0.0",
    "imagemin-pngquant": "^10.0.0",
    "imagemin-svgo": "^11.0.1",
    "postcss-sort-media-queries": "^5.2.0",
    "prettier": "^3.3.3",
    "prettier-plugin-astro": "^0.14.1"
  }
}

npm run builddistフォルダに静的HTML一式を出力し、なおかつ画像軽量化とPrettierによるHTMLとCSSの自動整形をするにしております。

Prettierの設定

Prettierの設定では、--ignore-path .prettierignoreオプションを使用して、distディレクトリ内のファイルを整形しています。
しかし、Prettierは.gitignoreの設定を共有しているため、もしdistディレクトリが.gitignoreに含まれていると、自動的に整形対象から外れてしまいます。
distディレクトリはGitの管理対象外とするため、.gitignoreからdistを削除することはありません。
.gitignoreからdistを削除せず、Prettierの整形対象にするために、.prettierignoreを利用しています。.prettierignore.gitignoreの内容を複製し、その中からdist/の記述を削除する形で作成しています。

astro.config.mjs

astro.config.mjsは下記のように設定しました。
Astroのバージョンアップに伴い、第1回の解説時から、rollupOptions内のファイル名を取得する引数がうまく返り値を取れなくなっていたので下記のように変更しました。
(ここらへんは仕様を確認するとじつはちがう、とかありそう)
あとビルド対象はcssのみとしました。
assetInfo.name.split('.')[0]→assetInfo.names[0].split('.').at(-1)

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

// https://astro.build/config
export default defineConfig({
  trailingSlash: 'ignore',
  plugins: ['prettier-plugin-astro'],
  compressHTML: false,
  scopedStyleStrategy: "attribute",
  build: {
    inlineStylesheets: 'never',
    format: 'preserve'
  },
  vite: {
    css: {
      preprocessorOptions: {
        scss: {
          api: 'modern-compiler',
          additionalData: `
            @use "src/styles/imports/_mixins.scss" as *;
            @use "src/styles/imports/_variables.scss" as *;
          `
        }
      }
    },
    build: {
      cssMinify: false,
      cssCodeSplit: false,
      rollupOptions: {
        output: {
          assetFileNames: assetInfo => {
            const fileName = assetInfo?.names;
            if (fileName && Array.isArray(fileName)) {
              const extType = fileName[0].split('.').at(-1);
              if (extType === 'css') {
                return 'css/[name][extname]';
              }
            }
            return `assets/[name][extname]`;
          },
        },
      }
    }
  }
});

この記事執筆にあたって、SCSSの@import@useに変更しました。その影響で、以前はadditionalDataでインポートした変数がどのファイルでも参照できましたが、@useで使用する場合、.astroファイルではそのまま使用できるものの、.scssファイルでは各ファイルで再度@useを追加しなければならなくなりました。

sample.scss
@use "src/styles/imports/_mixins.scss" as *;
@use "src/styles/imports/_variables.scss" as *;

// 各ファイルでも@useを追加する

良き解決方法があれば教えてください。(¯人¯)

PostCSSの設定

Astroには、Viteの一部としてPostCSSが同梱されています。プロジェクトにPostCSSを設定するには、プロジェクトルートにpostcss.config.cjsファイルを作成しています。

postcss.config.cjs
const autoprefixer = require('autoprefixer');

const config = {
plugins: [
  require('postcss-sort-media-queries')({
    sort: 'mobile-first', // default value
  }),
  autoprefixer(),
],
};

module.exports = config;

postcss-sort-media-queries

メディアクエリの順序をmobile-first(モバイル優先)に並べ替えます。

autoprefixer

ブラウザ間の互換性を高めるために、ベンダープレフィックス(-webkit-、-moz-など)を自動的に追加します。

tsconfig.json

Astroファイルからコンポーネントをインポートする際に、冗長なパスを書かずに済むように、tsconfig.jsonを以下のように設定しています。

tsconfig.json
{
  "extends": "astro/tsconfigs/strict",
  "compilerOptions": {
    "jsx": "preserve",
    "baseUrl": ".",
    "paths": {
      "@components/*": ["src/components/*"],
      "@layouts/*": ["src/layouts/*"],
      "@styles/*": ["src/styles/*"]
    }
  }
}

例えばこのように記述できます。

---
import Layout from "@layouts/Layout.astro";
---

CSSの分離

.astroファイル上にHTML、CSSを記述し1ファイルで管理できるのもAstroのメリットですが、今回の環境ではCSSを分離して記述しています。
ビルド時の読み込み順によって最終的なCSSファイルの記述順が変更されることがあるためです。

src/styles/global.scssを作成してLayout.astro上で読み込むように設定しています。

Layout.astro
---
import "@styles/global.scss";
---

簡単ではありましたが、私の環境をご紹介させていただきました。
古い開発環境をそのまま引き継いでいるような部分もありまだまだ改善の余地はありますが、そこは都度都度バージョンアップしていこうと思っています。

さて、勘のいい方はお気づきかと思いますが、JavaScriptに触れていないですね?
JavaScriptは…public内に直ファイルを置いています。
JavaScriptのビルド環境もお勉強しないとなー…とお茶を濁したところで、今回はここまで!

Webの進化の速さにアップアップですがなんとか喰らいついていきたい。

山下 X@Frencel_ns

フロントエンドエンジニア
フレームワーク頑張りたい人
モンハンワイルズではキアヌ・リーブス似のイケオジでプレイしたい

好きなモンスターハンターの武器

双剣・狩猟笛

mail お問い合わせ

ご覧いただきありがとうございます。
当メディアへのご質問や各事業部へのお仕事のご相談がありましたら、お気軽にお問い合わせください。

article 過去記事