Astroアプリをデプロイする方法|静的サイトとSSRの公開手順と注意点

Astroのデプロイは、アダプタを入れていなければ静的サイトとして、@astrojs/nodeを入れていればサーバーで動く形で公開されます。npm run devで開いたブログは手元のブラウザでは見えていても、URLを送れる相手はまだいません。どこで、どのように公開すればいいのか、迷っていませんか。この記事では、どちらの形で公開されるかの見分け方と公開までの手順、公開後に初めて出るつまずきを解説します。

  • Astroのサイトは、アダプタを入れていなければ静的サイトとして、@astrojs/nodeを入れていればサーバーで動く形で公開されます
  • ブログやドキュメントなど、閲覧者ごとに中身を変えず送信も受け取らないサイトは、静的サイトのまま公開するのがおすすめです
  • ロリポップ!デプロイナウでは、フレームワークにastroを選ぶだけで、どちらで公開するかはビルドの結果から自動で決まります
  • サーバーで動かすときは、astro.configのsecurity.allowedDomainsに公開するドメインを書かないと、フォームの送信が失敗します

Astroのデプロイは2通り。静的サイトかサーバーかはアダプタで決まる

npm run buildを実行すると、Astroはサイトをビルドして、公開用のファイルをdistというフォルダに書き出します(Astro公式のデプロイガイド)。デプロイは、このdistの中身を誰でもアクセスできる場所に置いて動かす作業です。作業の全体像はデプロイとは?意味・仕組みの記事で整理しています。

Astroのデプロイで静的サイトとサーバーのどちらになるかの違い

何も足さなければ静的サイトとして公開される

Astro公式のレンダリングの説明によると、Astroはデフォルトで、サイトの全ページをビルドの時点でHTMLにします。筆者がnpm create astroのブログテンプレートで作ったサイトをそのままビルドすると、distにはindex.htmlと、記事ごとのblog/<記事名>/index.htmlが並びました。アクセスが来たときに返すのはできあがったHTMLだけなので、配信する側でプログラムを動かす必要はありません。

@astrojs/nodeを入れるとサーバーで動く

アダプタは、ビルドしたサイトを特定の実行環境で動かすための部品で、Node.jsで動かすためのものが@astrojs/nodeです。これを入れたうえでページの先頭にexport const prerender = falseと書くと、そのページだけがアクセスのたびにサーバーで組み立てられ、残りのページは静的なまま残ります。アクセスのたびにサーバーでページを組み立てるこの形が、SSR(サーバーサイドレンダリング)です。同じブログに@astrojs/nodeを足してビルドし直すと、distの中はclientとserverの2つに分かれ、server/entry.mjsというファイルができていました。

ロリポップ!デプロイナウでは、どちらの形で公開するかをビルドの結果から自動で決めます。フレームワークに選ぶのはどちらもastroで、切り替える設定はありません。

どちらにするかの判断の分かれ目

分かれ目は、閲覧する人やタイミングによってページの中身を変えたり、送られてきた内容を受け取ったりする必要があるかどうかです。

サイトの中身公開の形追加で要る設定・制約
ブログ、ポートフォリオ、ドキュメント静的サイト(アダプタなし)siteの設定(サーバー向けの設定は要らない)
お問い合わせフォームなど、一部のページだけ送信を受け付ける一部だけサーバー(@astrojs/node+そのページにprerender = false)siteに加えて、@astrojs/nodeの追加とsecurity.allowedDomainsの設定
ログインがある、閲覧者ごとに内容が変わるサーバー上に加えて、Sessionsを使う場合は保存先に外部のデータストア(Redisなど)を指定する

サーバーが要る機能が無いサイトは、アダプタを入れずに静的サイトのまま公開するのがおすすめです。アダプタやサーバー向けの設定を足さずに済みます。サーバーで動かす場合は、ローカルでは問題なく送れたフォームが公開後に403で止まるという失敗に気をつける必要が出てきます。

【手順】Astroのサイトをデプロイして公開する

デプロイナウでは、静的サイトでもサーバーでも手順は同じです。デプロイ先の選び方はNext.jsのデプロイ方法の記事で比べています。

事前確認:package-lock.jsonとsiteの設定

デプロイナウでastroを選ぶと、インストールコマンドはnpm ci --ignore-scripts、ビルドコマンドはnpm run build、出力ディレクトリはdistがデフォルト値です(デプロイナウのAstro向けドキュメント)。筆者がnpm create astroのブログテンプレートで作った静的サイトは、このデフォルト値のまま設定に手を付けずに公開できました。

確かめておくのは2点です。1つ目はpackage-lock.jsonで、npmのドキュメントにあるとおりnpm ciはこのファイルを前提に動くため、リポジトリに含めておきます。デプロイナウのインストールとビルドはnpmが前提で、pnpmとyarnには対応していません(デプロイナウのCLIリファレンス)。

2つ目はastro.configのsiteです。Astro公式の設定リファレンスによると、Astroはこの値を使ってcanonical URLとサイトマップを作ります。デプロイナウでは、静的サイトでもこの値を設定します。公開URLはhttps://<サブドメイン>.lolipop-now.appの形です。サブドメインは指定しなければプロジェクト名と同じになるので(CLIでデプロイする手順)、プロジェクト名を決めた時点でsiteを書けます。

// astro.config.mjs
export default defineConfig({
  site: 'https://<プロジェクト名>.lolipop-now.app',
})

siteが公開URLと違っていても、画面を見ただけでは分かりません。筆者はsiteを別のURLにしたままビルドしたdistを、別のサブドメインで公開してみました。ページは崩れずに表示されたので、問題ないと思っていました。ところがHTMLのソースを開いて確かめると、canonicalとog:url、RSS、サイトマップのURLが、どれもビルドしたときのsiteのドメインのままでした。ずれるのは検索エンジンやSNSに渡るURLだけで、ページ内のリンクと画像は相対パスなので表示は崩れません。

ステップ1:CLIをインストールする

ターミナルでの作業と聞くと構えるかもしれませんが、この手順で打つのはnpm i -g lolipop、lolipop login、lolipop deployの3行です。ターミナルで次のコマンドを実行すると、デプロイの操作を文字入力で進めるCLIツールのlolipopコマンドが入ります。

npm i -g lolipop

動作にはNode.js 22.12.0以上が要ります(CLIでデプロイする手順)。Astro 7も同じくNode.js 22.12.0以上を求めるので、Astroが手元で動いているときは、この条件を満たしています。

ステップ2:ログインする

続けて次のコマンドを実行し、ロリポップ!アカウントで認証します。

lolipop login

ステップ3:デプロイする

ログインまで済んだら、Astroのプロジェクトのフォルダで次のコマンドを実行します。

lolipop deploy --name <プロジェクト名> --framework astro

プロジェクトがリポジトリのサブフォルダにある場合は、--root apps/webのようにフォルダを指定します。outDirで出力先を変えているときは、lolipop build-config update --project <id> --output buildで同じ値に合わせます。

フレームワークの名前はlolipop frameworks listで確認でき、執筆時点ではnext、nuxt、staticと並んでastroが表示されました。実行するとプロジェクトのフォルダがアップロードされ、ビルドの進行を確認できるダッシュボードのURLが表示されます。

Astroのサイトをlolipop deployでデプロイした実行結果

ダッシュボードでビルドが終わったのを確かめたら、https://<プロジェクト名>.lolipop-now.appを開きます。

デプロイナウで公開したAstroのブログサイト

ステップ4:更新を反映する(CLI/GitHub連携)

記事を足したりデザインを直したりしたあとは、もう一度デプロイします。lolipop project linkでフォルダとプロジェクトを紐付けておけば、2回目から打つのはlolipop deployだけです。

ソースをGitHubで管理している場合は、リポジトリをプロジェクトに接続すると、指定したブランチにpushするたびにビルドとデプロイが自動で始まります。プルリクエストを作ると、その内容が本番とは別のURLで公開されます。このURLは知っていれば誰でも開けるため、公開前の内容を第三者に見せたくない場合はアプリ側でアクセス制限をかけます(プレビューの説明)。

環境変数と独自ドメインを設定する

ローカルの.envに書いた値は、ビルド時にも公開時にも読まれません(環境変数の説明)。外部APIのキーのようにコードに書きたくない値は、ダッシュボードの「環境変数」タブか、lolipop env create API_URL https://api.example.comのようなコマンドで登録します。

ドメインをまだ持っていない場合は、AIエージェントからムームードメインを操作するためのムームードメインのMCPサーバーを使うと、ドメインの検索・取得からDNS設定までをClaude CodeなどのAIエージェントとの会話で進められます。MCPサーバー自体の利用は無料で、ドメインの取得・更新にはムームードメインの通常料金がかかります。

自分のドメインで公開したい場合は、プロジェクト詳細画面の「ドメイン」タブでドメインを追加すると、設定すべきDNSレコードが表示されます(独自ドメインの説明)。そのレコードをDNSの管理画面で設定し、反映後に検証を実行する流れです。SSL証明書は自動で発行されます。ドメインを追加したら、siteを独自ドメインのURLに書き換えてデプロイし直します。

SSRで動かす場合の設定(@astrojs/node)

お問い合わせフォームのように、送られてきた内容をサーバーで受け取るページを足す場合は、デプロイのコマンドは変えずに、astro.configへ設定を加えます。

@astrojs/nodeを追加する

Astroのプロジェクトのフォルダで次のコマンドを実行すると、@astrojs/nodeが入り、astro.configにアダプタの設定が書き足されます。

npx astro add node

Astro公式の@astrojs/nodeのガイドによると、@astrojs/nodeにはstandaloneとmiddlewareの2つのモードがあります。standaloneはそれ自体で起動するサーバーを作り、middlewareはExpressのような別のNode.jsサーバーに組み込んで使う形です。デプロイナウで使うのはstandaloneで、npx astro add nodeで追加した場合はこの設定になっています。

astro.configに書く3つの設定

デプロイナウでサーバーとして動かす場合は、astro.configを次の形にします(デプロイナウのAstro向けドキュメント)。

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

export default defineConfig({
  site: 'https://<プロジェクト名>.lolipop-now.app',
  adapter: node({ mode: 'standalone' }),
  security: {
    allowedDomains: [
      { hostname: '<プロジェクト名>.lolipop-now.app', protocol: 'https' },
      { hostname: '*.preview.lolipop-now.app', protocol: 'https' },
      { hostname: 'www.example.com', protocol: 'https' },
    ],
  },
})

siteは静的サイトと同じく公開するURLで、adapterは前の手順で追加された設定です。新しく書くのはsecurity.allowedDomainsで、公開するドメインを並べます。1行目が公開URL、2行目がプルリクエストのプレビュー、3行目が独自ドメインです。独自ドメインを使わない場合は3行目を消し、あとから独自ドメインを追加したときは、ここにも足してデプロイし直します。

allowedDomainsが要る理由

ローカルでは送れたフォームが、公開すると403になるのはなぜでしょうか。関係するのはAstroの2つの設定です。

1つはsecurity.checkOriginで、Astro公式の設定リファレンスによるとデフォルトで有効です。サーバーで描画するページがフォームのPOSTを受けると、ブラウザが付けるOriginヘッダーとリクエストされたURLが一致するかを確かめ、一致しなければ403を返します。他のサイトから勝手にフォームを送りつける攻撃への対策です。

もう1つがsecurity.allowedDomainsです。ここに書いたホストに一致する場合だけ、AstroはリクエストのX-Forwarded-Hostヘッダーを読んで、自分のURLを組み立てます。一致しなければこのヘッダーは無視されます。デプロイナウでは、allowedDomainsに書いていないドメインからフォームを送ると403で失敗し、Astro.urlも公開しているURLと異なる値になります。

筆者はサーバー版のブログに、描画した時刻とAstro.url、Node.jsのバージョンを表示し、感想を送るフォームを置いた/serverというページを足して公開しました。再読み込みのたびに時刻が変わり、Astro.urlには公開URLがそのまま、Node.jsはv22.23.3と出ました。フォームから送信すると受け取った内容が表示され、別のサイトのOriginを付けて同じページにPOSTすると403が返りました。allowedDomainsを書いても、他のサイトからの送信は止まったままです。

Astroの@astrojs/nodeでサーバー描画したページをデプロイナウで公開した画面

一部のページだけサーバーで描画する

先ほどの/serverは、先頭にexport const prerender = falseを書いたページで、記事一覧や記事ページはアダプタを入れたあともビルド時のHTMLのままです。サイト全体をサーバーで描画する設定(output: 'server')に切り替えなくても、アダプタが入っていればデプロイナウはサーバーで動く形で公開します。

Astroのデプロイでつまずきやすいポイント

デプロイが途中で止まったのか、公開されたのに動かないのかで、見る場所が変わります。

デプロイが通らない(アダプタ・ロックファイル)

デプロイナウでは@astrojs/cloudflare、@astrojs/netlify、@astrojs/vercelのアダプタは使えず、サーバーで動かす場合は@astrojs/nodeを使います。別のデプロイ先向けの記事を見ながらこれらを入れていたときは、npx astro add nodeで入れ直し、元のアダプタをpackage.jsonとastro.configから外すのが筆者のおすすめの直し方です。@astrojs/nodeのmode: 'middleware'にも対応していないため、standaloneにします。

インストールの段階で止まるときは、package-lock.jsonがリポジトリに入っているかを確かめます。pnpmやyarnで管理してきたプロジェクトは、npm installで作ってからデプロイし直します。

公開したのに動かない(フォーム・環境変数)

フォームを送ると403が返る、またはAstro.urlが公開URLと違う値になるときは、security.allowedDomainsに公開URLが入っているかを確かめます(デプロイナウのAstro向けドキュメント)。独自ドメインのURLでだけ403になるときは、ドメインを追加したあとにallowedDomainsへも足したかを見ます。環境変数の値が空になるときは、.envに書いたままになっていないかを見ます。GitHub連携のプレビューには本番の変数が渡らないため、「環境変数」タブの「プレビュー」側にも登録が要ります。どちらも、直したあとにデプロイし直すと反映されます。

デプロイナウで使えないAstroの機能

アダプタのほかに、デプロイナウでサーバーとして動かす場合は、次の機能に代わりの方法が必要です。

機能代わりの方法
Sessions(Astro.session)のデフォルトの保存先session.driverで外部のデータストア(Redisなど)を指定する
route caching(Astro.cache、routeRules)なし
build.serverの変更デフォルトの./serverのまま使う

表は執筆時点の内容です。最新の情報は、デプロイナウのAstro向けドキュメントの「対応していない機能」を参照してください。

AIエージェントにデプロイを頼む

AIエージェントとサイトを作成した場合は、公開も同じ会話の続きで頼めます。AIエージェントでデプロイする手順の対象は、Claude Code、Codex、Cursor、Antigravityなどです。

CLIを入れてlolipop skill installでエージェントを選び、サイトのフォルダで「このアプリをlolipopにデプロイして」と頼むと、エージェントがlolipop deployを実行してプロジェクトの作成から公開まで進めます。エージェントに頼む場合も、siteの設定は必要です。サーバーで動かすサイトでは、allowedDomainsも設定します。公開するURLを依頼文に書き、これらの設定に入れるよう指示します。

Astroのサイトを公開するならロリポップ!デプロイナウ

デプロイナウは、静的サイトとNode.jsで動くサイトの公開、GitHub連携、独自ドメイン、SSL証明書の自動発行に対応したうえで、次の3つに特徴があります。

ロリポップ!デプロイナウの公式サイト

  • コマンドひとつで公開できる:lolipop deployでアップロードからビルド、公開まで進み、静的サイトかサーバーかもビルドの結果から自動で決まります。GitHubと接続すればpushで自動デプロイされ、プルリクエストごとのプレビューも使えます
  • 無料から始められる定額制:執筆時点で、Freeプランは無料、Personalプランは月額980円です。どちらのプランでも商用利用ができます
  • 日本語の画面とドキュメントで完結する:設定画面もドキュメントも日本語で読めて、困ったときに英語の資料を探しに行かずに済みます

DDoS対策とWAFはどちらのプランでも有効です。プランごとの上限はプランのページを参照してください。

よくある質問(FAQ)

Astroのデプロイでアダプタは必要ですか?

静的サイトとして公開する場合は不要です。アクセスのたびにサーバーで処理するページがある場合は、デプロイナウでは@astrojs/nodeを使います。

npm run buildでできたdistフォルダをそのままアップロードして公開できますか?

できます。フレームワークにstaticを選ぶと、アップロードしたフォルダの中身がそのまま公開されます(静的サイトをデプロイする方法)。筆者はdistをリポジトリの外のフォルダにコピーし、その中でlolipop deploy --name <プロジェクト名> --framework staticを実行しました。21ファイルすべてが手元のdistと同じ中身で公開されました。外にコピーしたのは、git管理下のフォルダでは、まだ追跡されておらず.gitignoreで無視されているファイルがアップロードの対象から外れ(アップロードされるファイルの説明)、npm create astroのテンプレートはdistを無視する設定になっているためです。同じdistを--framework astroでアップロードすると、ビルドに進む前に「ERROR: package.json が見つかりません。」と出て止まります。astroはソースからビルドする前提だからです。この方法ではsiteを公開するURLに合わせてからビルドし、更新のたびに手元でビルドし直します。ソースごとデプロイすれば、ビルドはデプロイナウ側で行われます。

Astroのデプロイ先はどこを選べばいいですか?

サーバーの管理に時間を使いたくない個人の開発では、ホスティングサービスが向いています。OSやミドルウェアから自分で決めたい場合は、自前のサーバーやクラウドが選択肢です。手元に残る作業の量が3つの系統でどう変わるかは、Webアプリを公開する方法にまとめています。同じ手順でNuxtのアプリを公開する場合はNuxtのデプロイ方法を参照してください。

まとめ

  • Astroのサイトは、アダプタが無ければ静的サイト、@astrojs/nodeがあればサーバーで動く形で公開される。デプロイナウではどちらになるかをビルドの結果から自動で判断するので、フレームワークの指定はどちらもastroのままでよい
  • siteは静的サイトでもサーバーでも公開URLに合わせ、サーバーで動かす場合はsecurity.allowedDomainsに公開するドメインを並べる
  • ビルド前に止まったらアダプタとロックファイル、公開後にフォームが動かなければallowedDomainsと環境変数を確かめる

フォームを足すかどうかで迷っているときは、先に静的サイトのまま公開する手があります。あとから@astrojs/nodeを足しても、デプロイのコマンドは同じです。

npm run devのターミナルを閉じたあとも、ブログはURLの先で表示され続け、そのURLを送れば誰でも読めるようになります。

「デプロイナウコンテスト」開催中!

デプロイナウコンテスト グランプリ賞金100万円 応募締切:2026年12月8日(火)まで

この記事をシェア

ロリポップ!デプロイナウ アイデアを、いますぐ公開 詳しく見る