要約
- Flutter WebはSEOが弱いため、DartベースのJasprでWebサイトを構築
- daisyUIでTailwind CSSを簡素化し、美しいデザインを効率的に実現
- GitHub ActionsとCloudflare Pagesで自動デプロイを構築
はじめに
FlutterでモバイルアプリやWebアプリを開発している皆さんは、LPやブログサイトのSEO対策に悩んだことはありませんか?
Flutter WebはSPAとしては優秀ですが、SEOの観点では課題があります。かといってNext.jsなどのWeb開発特有のフレームワークで実装すると、普段Dartを使っているチームでは言語的な混乱が生じたり、保守性に欠けてしまいます。せっかくならDartで書きたいですよね。
そこで今回は、DartでかつFlutterライクにWebサイトを実装できるJasprを使って、SEO対策万全のWebサイトを構築した経験をお話しします。
実際に作成したサイトはこちらです。
対象読者
- Flutterを使ったことがある人
- SEO対策が必要なWebサイトを作りたい人
- DartでWebサイトを作ってみたい人
- Jasprが気になる人
Jasprの導入
Jasprとは
JasprはDartで開発できるWebアプリケーションフレームワークで、Flutterのような宣言的なUI構築を可能にします。サーバーサイドレンダリング(SSR)や静的サイト生成(SSG)にも対応しており、SEO対策にも効果的です。
jaspr_cliをインストールすることで、開発サーバーの起動やビルドを実行できます。簡単に始められるのが魅力です。
今回は触れませんが、JasprはFlutterウィジェットの埋め込みも可能なため、Flutterアプリと連携したLPの作成にも最適です。
daisyUIの活用
SSGにするということは、結局はHTMLを生成することです。そのため、デザインはCSSで行う必要があります。
CSSを一から書くのは大変なので、daisyUIを採用しました。daisyUIはTailwind CSSの上に構築されたコンポーネントライブラリで、事前にスタイリングされたUIコンポーネントを提供します。
JasprでdaisyUIを使う方法
パッケージが用意されているので、組み込むだけです。ただし、tailwindcssというCLIが必要です。詳しいセットアップはパッケージのREADMEを参照してください。
以下のような流れで組み込むことができます。
- TailwindCSS CLIをインストール
- jaspr_daisyuiをpubspec.yamlに追加
-
web/ディレクトリにDaisyUIのプラグインファイル(daisyui.js,daisyui-theme.js)とstyles.tw.cssファイルを作成 - linkタグを追加してCSSを読み込む
jaspr_daisyuiはbuild_runnerを活用し、styles.tw.cssをビルドしてくれます。
daisyUIの利点
daisyUIの最大の利点は、複雑なTailwindクラスをシンプルに表現できることです。Tailwindはカスタマイズ性を売りにしていますが、そのカスタマイズ性ゆえ、複雑なクラスの列挙になりがちです。daisyUIはそのTailwindを基盤にし、カスタマイズ性は維持しつつ、よく使用されるボイラープレートをまとめたクラスを提供してくれます。
// Before: Tailwindクラスの羅列
div(classes: 'bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded', [
text('ボタン')
]);
// After: daisyUIコンポーネント
button(classes: 'btn btn-primary', [
text('ボタン')
]);
また、daisyUIには多数の事前定義テーマが用意されており、styles.tw.cssに設定するだけで簡単にテーマを変更できます。
既存のテーマをベースに、細かい部分だけをカスタマイズすることも可能です。これにより、迅速に美しいデザインを実現できます。丸みを帯びたデザインが可愛いですよね。
最終的に、以下のようなstyles.tw.cssを作成しました。ほぼgardenというテーマのコピーで、primaryの色だけを変更しています。CSSに慣れていない私でも簡単に可愛らしいデザインを実装できて驚きです。
@import "tailwindcss";
@plugin "./daisyui.js";
@plugin "./daisyui-theme.js" {
name: "garden";
default: true;
prefersdark: false;
color-scheme: "light";
--color-base-100: oklch(92.951% 0.002 17.197);
--color-base-200: oklch(86.445% 0.002 17.197);
--color-base-300: oklch(79.938% 0.001 17.197);
--color-base-content: oklch(16.961% 0.001 17.32);
--color-primary: oklch(60% 0.118 184.704);
--color-primary-content: oklch(100% 0 0);
--color-secondary: oklch(48.495% 0.11 355.095);
--color-secondary-content: oklch(89.699% 0.022 355.095);
--color-accent: oklch(56.273% 0.054 154.39);
--color-accent-content: oklch(100% 0 0);
--color-neutral: oklch(24.155% 0.049 89.07);
--color-neutral-content: oklch(92.951% 0.002 17.197);
--color-info: oklch(72.06% 0.191 231.6);
--color-info-content: oklch(0% 0 0);
--color-success: oklch(64.8% 0.15 160);
--color-success-content: oklch(0% 0 0);
--color-warning: oklch(84.71% 0.199 83.87);
--color-warning-content: oklch(0% 0 0);
--color-error: oklch(71.76% 0.221 22.18);
--color-error-content: oklch(0% 0 0);
--radius-selector: 1rem;
--radius-field: 0.5rem;
--radius-box: 1rem;
--size-selector: 0.25rem;
--size-field: 0.25rem;
--border: 1px;
--depth: 0;
--noise: 0;
}
SEO対策
メタタグの設定
HTMLなので、何もしなくてもある程度検索エンジンに認識されますが、メタタグを適切に設定することで、より効果的なSEO対策が可能です。
特にOpen GraphやTwitter Cardの設定は、SNSやLINE、Discordなどでのシェア時に重要な役割を果たします。
head([
// 基本的なメタタグ
meta(name: 'description', content: 'サイトの説明'),
// Open Graph
meta(attributes: {'property': 'og:title'}, content: 'ページタイトル'),
meta(attributes: {'property': 'og:description'}, content: 'ページの説明'),
meta(attributes: {'property': 'og:type'}, content: 'website'),
meta(attributes: {'property': 'og:image'}, content: 'https://example.com/image.jpg'),
meta(attributes: {'property': 'og:url'}, content: 'https://example.com'),
// Twitter Card
meta(name: 'twitter:card', content: 'summary_large_image'),
meta(name: 'twitter:title', content: 'ページタイトル'),
meta(name: 'twitter:description', content: 'ページの説明'),
meta(name: 'twitter:image', content: 'https://example.com/image.jpg'),
])
Open Graphでは、属性名にpropertyを使用するのが公式の仕様に沿っています。
Jasprのmetaの引数にpropertyはないので、attributesを使って設定します。
構造化データ(JSON-LD)
JSON-LDを用いた構造化データも設定することで、検索エンジンに対してサイトの内容を明確に伝えることができます。
script(
attributes: {'type': 'application/ld+json'},
content: '''
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "会社名",
"url": "https://nekonata.dev",
"description": "会社の説明"
}
''')
細かい構文はSchema.orgを参照してください。たくさんの種類があり、サイトの内容に応じて適切なものを選ぶことができます。AIなどを活用して生成するとよいでしょう。
サイトのデータを構造化して提供することで、AIとの相性も良くなります。
プレビューツールの活用
設定したメタタグは以下のようなツールで確認できます。
リッチリザルト テストでは、コードを貼り付けるだけでも確認できるので、デプロイ前に手軽に検証できます。
デプロイの自動化
Cloudflareでドメインを管理している場合、Cloudflare Pagesを利用すると便利です。
ただし、JasprはNext.jsのような有名フレームワークではないため、Cloudflare Pagesにビルド環境がプリセットされていません。通常はGitHubのリポジトリと連携し、簡単な設定だけでビルドできるようになるのですが、専用のビルド環境が用意されていないため、GitHub Actionsを利用してビルドとデプロイを自動化する必要があります。
wranglerを用いればそれほど難しくはありません。
GitHub Actionsの設定
jasprはjaspr buildでビルドした後、build/jasprディレクトリに静的ファイルを生成します。これをCloudflare Pagesにデプロイします。
name: Build and Deploy
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# Flutter環境がないとビルドエラーが発生するため、dartだけではなく、Flutterをインストール
- uses: subosito/flutter-action@v2
with:
channel: stable
- name: Install Jaspr CLI
run: dart pub global activate jaspr_cli
- name: Get dependencies
run: dart pub get
- name: Download TailwindCSS CLI
run: curl -sLO https://github.com/tailwindlabs/tailwindcss/releases/latest/download/tailwindcss-linux-x64
- name: Make TailwindCSS executable
run: chmod +x tailwindcss-linux-x64
- name: Move TailwindCSS to /usr/local/bin
run: sudo mv tailwindcss-linux-x64 /usr/local/bin/tailwindcss
- name: Build
run: jaspr build
- name: Deploy to Cloudflare Pages
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy ./build/jaspr --project-name=your-project-name
secretsの値はリポジトリの設定から追加してください。
私が試したところ、CLOUDFLARE_ACCOUNT_IDを指定しないとエラーになります。Cloudflareのダッシュボードから確認できます。
先ほど触れたように、jaspr_daisyuiにはTailwindCSSのCLIツールが必要です。この環境を用意しないと、CSSが適切に生成されずスタイルが適用されないので注意が必要です。
なぜかビルドは失敗せず、HTMLファイルだけが生成されるので少し沼にハマりました😮💨
Cloudflare APIトークンの設定
CloudflareのAPIトークンを生成する際は、適切な権限設定が必要です。以下の権限が必要でした。
- All accounts - Cloudflare Pages:Edit
- All zones - Zone:Read
- All users - User Details:Read
- Zone:ドメイン関係の権限
- Pages:Cloudflare Pagesの権限
- User:ユーザーデータを読むための権限
これらを適切に設定しないと、デプロイが失敗します。
まとめ
今回はJaspr + daisyUI + Cloudflareの組み合わせでWebサイトを構築しました。
- JasprでDartの知識を活かしつつ、SEO対策万全のサイトを構築
- daisyUIでTailwind CSSを簡素化し、美しいデザインを効率的に実現
- GitHub Actions + Cloudflare Pagesで自動デプロイを構築
Flutter開発者の皆さんも、ぜひJasprを試してみてはいかがでしょうか?慣れ親しんだDartでWebサイトが作れるのはとても快適でした。
