morphe について
morphe は、Next.js、Bigfish、Vite のプロジェクトをパッケージ化して Morphe にデプロイするスキルです。静的 SPA と Vite のカスタムサーバーに対応した実行可能な ZIP を作成します。
主な機能
- 01Next.js・Bigfish・Vite プロジェクトの検出
- 02Next.js standalone ビルドの組み立て
- 03静的アプリ向けゼロ依存サーバーの生成
- 04Vite カスタムサーバーの単一ファイル化
- 05パッケージ化・アップロード・検証・デプロイ
活用シーン
- 01Next.js standalone ビルドのデプロイ
- 02Bigfish 静的サイトの Morphe へのデプロイ
- 03Vite SPA のデプロイ
- 04API ルート付き Vite カスタムサーバーのパッケージ化
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ zenmux/ skills --skill morpheインストール後、Claude Code で/morpheを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/api.mdnextjs-config.mdscripts/auth-callback.mjslogin.shmorphe.py詳細
Morphe Deploy
概要
Next.js、Bigfish(@alipay/bigfish)、または Vite のプロジェクトを
Morphe(ランタイム custom.debian11、linux-x64-gnu)にデプロイします。ランタイムは常に
node server.js で関数を起動するため、どのフレームワークでも、ルートに server.js がある
zip にパッケージ化します。
- Next.js → スタンドアロンサーバー(
.next/standalone/server.js)と、そのトレース対象のnode_modules。パッケージ化時にプラットフォームが異なるネイティブバインディングを除外し、 pnpm の部分パッケージを修復します。 - Bigfish → 静的/SPA ビルド(
dist/)。パッケージ化時に、ビルドディレクトリを配信し、 SPA フォールバックでindex.htmlを返す、依存関係ゼロの静的server.js(Node の組み込み機能のみを使用し、インストール不要)を生成します。 - Vite → 2 つのモードがあります。純粋な SPA(
vite build→dist/、サーバーなし)では、 Bigfish と同じ依存関係ゼロの静的ラッパーを再利用します。dist/とバックエンド API ルートの両方を 配信する Express などのserver.ts/server.jsを持つ カスタムサーバーアプリは、 esbuild でバンドルされ、zip のルートに自己完結型のserver.jsを作成します。ビルドディレクトリも同じ階層に配置されます。
壊れやすく決定的な API 処理(認証、署名付き URL の生成、アップロード、CRC64、.morphe.json、
デプロイ)は scripts/morphe.py にあります。ビルドと設定に関する判断は、あなたが行います。
scripts/morphe.py のすべてのコマンドはプロジェクトのルートから実行してください。以下の SKILL_DIR は、このスキルのディレクトリ(このファイルを含むフォルダー)に置き換えてください。
ワークフロー
以下の手順を順番に実行してください。いずれかの手順で失敗したら、停止して報告してください。
1. ログイン状態を確認する
ブラウザー経由でログインします。ユーザーにユーザー名やパスワードを尋ねてはいけません。
bash SKILL_DIR/scripts/login.sh
これは gh auth login/vercel login と同様に動作します。ユーザーはブラウザーでクリックするだけで、トークンをコピー&ペーストする必要はありません。
~/.morphe/auth.jsonに有効なaccessTokenがすでにある場合、スクリプトはそれを再利用してブラウザーを開かず、直ちにAUTH_OK=1を出力します。- それ以外の場合は、ローカルのコールバックサーバーを起動し、ブラウザーで
morphe.zenmux.app/cli-authを開きます(OPEN_AUTH=<url>を出力します。ブラウザーが自動で開かない場合に備え、これをユーザーに提示してください)。そのまま待機します。ユーザーがログイン(パスワードまたは Google)して 「授权并返回终端」 をクリックすると、ブラウザーがトークンを POST し、スクリプトがトークンを~/.morphe/auth.jsonに書き込みます。 - 成功すると、スクリプトは
AUTH_OK=1を出力します。ログインし直す場合(アカウントの切り替えなど)は、bash SKILL_DIR/scripts/login.sh --forceを実行します。 - スクリプトでエラーが発生するか、タイムアウトした場合(
AUTH_OK=1が出力されない場合)は、エラーを報告して停止してください。
2. フレームワークを検出する
python3 SKILL_DIR/scripts/morphe.py detect-framework --project-root .
nextjs、bigfish、vite、または unknown(終了コード 1)を出力します。検出は次の順序で行われます(最初に一致したものを採用します)。
- bigfish —
package.jsonの依存関係に@alipay/bigfishがある、またはconfig/config.tsが存在する(最初に確認します。Bigfish プロジェクトには next に似たビルドスクリプトや vite スタイルのツールも含まれるためです)。 - nextjs — 依存関係に
nextがある、またはnext.config.{js,mjs,ts}が存在する。 - vite — 依存関係に
viteがある、またはvite.config.{js,mjs,ts,mts,cjs}が存在する(最後に確認します。最も広く該当するためです)。
unknown が出力された場合は、ユーザーに「暂不支持该项目类型(仅支持 Next.js、Bigfish 与 Vite)」と伝えて停止してください。それ以外の場合はフレームワークを記憶してください。以下のビルドとパッケージ化の手順は、フレームワークに応じて選択します。
3. 関数名を決める
デプロイする関数名をユーザーに尋ねてください。次のように伝えます。不知道填什么,
可以留空,会自动生成一个 user-xxxxxxxx 格式的随机函数名。
.morphe.jsonにすでにfunction_nameがある場合は、現在のデフォルト値として伝え、Enter キーを押してそのまま使うか、別の値を指定するか選んでもらいます。- 選択した値を保存します(入力が空の場合は、既存の名前を維持するか、新しい名前を生成します)。
# user provided a name:
python3 SKILL_DIR/scripts/morphe.py set-function-name --name "NAME" --project-root .
# user left it blank:
python3 SKILL_DIR/scripts/morphe.py set-function-name --project-root .
コマンドは最終的な関数名を出力し、.morphe.json に書き込みます。この名前はデプロイのたびに再利用され、同じ関数が更新されます。
4. ビルド設定を検証して修正する
手順 4~6 はフレームワークによって異なります。 手順 2 で検出したフレームワークの分岐に従ってください。
4a. Next.js
目標は、すべてのネイティブ依存関係のランタイムターゲット(linux-x64-gnu)バイナリが、ビルド前にディスク上にインストールされていることです。Next のトレーサーがそれを取り込めるようにします。morphe.py package の手順(手順 6)では、トップレベルへの配置、不要ファイルの除外、zip 化を行いますが、インストール時に実際にダウンロードされたバイナリしか同梱できません。
設定をその場で編集し、次の条件を満たしてください。
-
standalone 出力 —
output: "standalone"(そうしないと、zip 化する.next/standalone/がありません)。 -
ビルドホストに Linux バイナリをインストールします。 ネイティブアドオンはプラットフォームごとのオプション依存関係として配布されます。macOS でインストールすると、darwin 用のものだけが取得されます。
- pnpm(
pnpm-workspace.yaml)—supportedArchitecturesを追加して、linux-x64-gnu バイナリも取得します。これが最も重要な修正です。これを設定すると、トレーサーがバインディングを自動的に含めるため、通常はoutputFileTracingIncludesがまったく不要になります。
その後、supportedArchitectures: os: [current, linux] cpu: [current, x64] libc: [current, glibc]pnpm installを再実行します。 - npm/yarn — ターゲット用の特定のバインディングをインストールします。例:
npm i --no-save @resvg/resvg-js-linux-x64-gnu --force --os=linux --cpu=x64 --libc=glibc。
- pnpm(
-
(任意)バンドルをさらに削減します。
morphe.py packageは、linux-x64-gnu 以外のネイティブバイナリをすべて除外するため、それらに対するoutputFileTracingExcludesは不要です。除外を追加するのは、ランタイムにサーバーが必要としないプロジェクトデータ(大きなフィクスチャ、未加工のデータセット、ドキュメント)だけにしてください。process.cwd()経由でランタイムに読み込まれるもの(フォント、ルートが読み込む JSON)は残してください。
詳細、パッケージごとのバインディング名、Linux バイナリがディスク上にあることの確認方法については、references/nextjs-config.md を参照してください。
4b. Bigfish
ネイティブバインディングの作業は不要です。Bigfish は静的/SPA バンドルをビルドし、morphe.py package は依存関係ゼロの server.js(Node 組み込み機能のみ)を生成します。Linux ターゲット用にインストールするものはなく、通常は修正が必要な設定もありません。
- アプリのビルド成果物が静的バンドルであることを確認します。Bigfish のデフォルトの
siteビルドはdist/(index.html+ ハッシュ付き JS/CSS)を出力します。生成された静的サーバーは、このファイルを配信します。deployMode: 'render'(SSR)はこの静的ラッパーの対象外です。実行時にサーバーサイドレンダリングが本当に必要な場合は、作業を中止し、静的な方法では SSR ルートを配信できないことをユーザーに伝えてください。 - ビルド出力ディレクトリが
dist/ではない場合(Bigfish では変更できます)は、そのディレクトリ名を控えてください。手順 6 で--static-dirを指定します。
4c. Vite
Vite には 2 つのモードがあり、morphe.py package(ステップ 6)はサーバーエントリ(server.{ts,js,mjs,cjs}。src/ 配下も含みます)を調べて、どちらのモードかを自動判定します。
-
純粋な SPA(サーバーエントリなし)— Bigfish と同様に、インストールやパッチは不要です。
vite buildはdist/(index.htmlとハッシュ付きアセット)を出力し、生成された依存関係ゼロの静的なserver.jsが SPA フォールバック付きで配信します。出力ディレクトリがdist/でない場合は、ステップ 6 で--static-dirに指定するため、記録しておいてください。 -
カスタムサーバー(
dist/を配信し、API ルートも備えたserver.ts/server.js)—packageはそのエントリを esbuild でバンドルし、自己完結型のserver.jsにします。サーバーが以下を満たしていることを確認してください。process.env.PORT || 3000でリッスンし、0.0.0.0にバインドすること(ランタイムはPORTを設定し、すべてのインターフェースにルーティングします)。- 静的ファイルのディレクトリを
process.cwd()から読み込むこと(例:path.join(process.cwd(), "dist"))。zip にはビルドディレクトリがserver.jsとともにランタイムの作業ディレクトリに含まれるためです。 viteのインポートを開発時専用にすること。viteはバンドルから常に外部化されます(非常に大きく、バンドルできないネイティブの.nodeアドオン(esbuild/lightningcss/fsevents)を取り込むため、ビルドが失敗します)。本番サーバーでは読み込まないでください。開発用ミドルウェアでviteを使う場合は、次のように遅延読み込みする非本番用の分岐に入れてください。if (process.env.NODE_ENV !== "production") { const { createServer } = await import("vite"); // 遅延読み込み:バンドル対象にならない // ... 開発用ミドルウェア }
実行時のシークレット(API キーなど)は zip ではなく、関数の環境変数に設定してください。ビルドで
.envがバンドルされることはありません。- バンドルから除外する追加パッケージが必要な場合(例:esbuild でインライン化できないネイティブの
.nodeアドオン)は、ステップ 6 で--external NAMEを指定してください。ただし、そのパッケージが実行時に利用可能である必要があります(これは例外的なケースで、ほとんどの純粋な JavaScript 依存関係は問題なくバンドルできます)。
5. ビルド
npm run build # or: pnpm build / yarn build (Bigfish: also `bigfish build`)
アセットを手作業でコピーしたり、zip を手作業で作成したりしないでください。組み立てはすべてステップ 6 で行います。(Vite の場合、ここでは dist/ を作成するためにフロントエンドのビルドのみ実行します。カスタムサーバーアプリでは、サーバーを自分でバンドルする必要はありません。ステップ 6 で package が esbuild を実行します。build スクリプトがすでにサーバーを esbuild でバンドルしている場合も問題ありません。いずれにしても package がステージングされた zip に再バンドルします。)
6. 最小限のデプロイ用 zip を作成する
python3 SKILL_DIR/scripts/morphe.py package --project-root .
package はフレームワークを自動検出します(--framework nextjs|bigfish|vite で上書きできます)。べき等性があるため安全に再実行できますが、コードを変更した場合は先にビルドを再実行してください。
Next.js — .next/standalone を実行可能な zip にまとめます。
.next/staticとpublic/をバンドルにコピーします(ビルドではトレースされません)。- pnpm の不完全なパッケージを修復します — 実際のファイルは
.pnpmにある一方で、トップレベルのnode_modules/<pkg>ディレクトリにはpackage.jsonしかないケースに対応します(このシャドーイングが原因で、たとえば Cannot find module@swc/helpers/cjs/_interop_require_default.cjsが発生し、node server.jsがクラッシュします)。 linux-x64-gnu以外のすべてのネイティブバインディングを削除します(darwin/musl/arm64 など。多くの場合 100M+ になります)。さらに、保持した Linux バインディングをトップレベルのnode_modulesにシンボリックリンクします。ランタイムはそこでrequire("<pkg>-linux-x64-gnu")によってバインディングを解決します。これを省略すると、SVG 形式のコードパスは動作する一方で、ネイティブアドオンを使う処理は Cannot find module…-linux-x64-gnuで 500 エラーになります。- **シンボリックリンクを保持して zip 化(
zip -y)**し、スタンドアロンディレクトリの外に./code.zipを作成します(以前のcode.zipが中に入ることはありません)。ランタイムはシンボリックリンクを保持し、pnpm のレイアウトの大半は.pnpmへのシンボリックリンクなので、zip のサイズをおよそ半分にできます。
Bigfish — 静的サーバー用の zip を作成します。
- ビルド出力ディレクトリを特定します(
index.htmlを含むdist、build、outを自動的に調べます。--static-dir DIRで上書きできます)。 - 依存関係ゼロの
server.js(Node のhttp/fs/pathのみを使用)を 生成 し、ビルドディレクトリを配信します。また、クライアント側のルートにはindex.htmlをフォールバックとして返します。 server.jsとビルドディレクトリをステージングし、server.jsがビルドディレクトリとともに zip のルートに配置されるよう zip 化します。node_modulesは含まれないため、zip は小さくなります。
Vite — サーバーエントリの有無を調べて、2 つのモードから自動選択します。
- SPA(サーバーエントリが見つからない場合) — 上記の Bigfish と同じ方法です。生成した依存関係ゼロの静的
server.jsとビルドディレクトリを使用します。 - カスタムサーバー(
server.{ts,js,mjs,cjs}エントリを自動的に調べます。--server-entry PATHで強制または上書きできます) — エントリを esbuild でバンドルします(--bundle --platform=node --format=cjs。viteは常に external とし、渡された--external NAMEも適用します)。自己完結型のserver.jsを生成したあと、ビルドディレクトリ(dist/build/outを自動的に調べます。--static-dirで上書きできます)とともにステージングし、server.jsが zip のルートに配置されるよう zip 化します。依存関係はインライン化されるため、node_modulesは含まれません。
最終パス、サイズ、フレームワークを出力します。例:
packaged: …/code.zip (25M)、packaged: …/code.zip (0.2M, framework=bigfish)、または
packaged: …/code.zip (0.7M, framework=vite, mode=server, entry=server.ts)。
7–11. アップロード、チェックサム、デプロイ
1 つのコマンドで、事前署名 → curl PUT アップロード → CRC64 チェックサム計算 →
.morphe.json の更新(checksum を書き込みます。ステップ 3 で解決した function_name を使用し、まだ存在しない場合に限り生成します)→ /api/deploy の呼び出しを実行します。
python3 SKILL_DIR/scripts/morphe.py deploy --zip code.zip --project-root .
成功すると、デプロイ結果の JSON が出力されます(利用可能な場合は action、functionName、triggerUrl を含みます)。その後、ローカルの code.zip を 削除します(すでに OSS にアップロード済みで、サイズの大きい一時ファイルであるためです)。確認用に保持するには --keep-zip を渡してください。失敗した場合は、再デプロイで再試行できるよう zip を保持します。結果をユーザーに伝え、triggerUrl がある場合は提示してください。not-logged-in または HTTP エラーが出力された場合は、ステップ 1 に戻ってください(トークンの有効期限が切れている可能性があります)。または、失敗を報告してください。
注意事項
- Morphe API は Cookie 認証を案内していますが、ログイン時には
accessTokenが返されます。スクリプトはこれをmorphe_sessionCookie と Bearer ヘッダーの両方に設定して送信します。 .morphe.jsonのfunction_nameは一度だけ生成され、以降の再デプロイでも毎回再利用されるため、同じ関数が更新され、重複して作成されることはありません。手動で編集したり、再生成したりしないでください。- すべてのフレームワークは、デフォルトの
command="node server.js"、port=3000でデプロイされます。フレームワークごとのデプロイ用フラグはありません。Bigfish/Vite-SPA の静的サーバーはprocess.env.PORTを使用(デフォルトは 3000)して設定に合わせます。Vite のカスタムサーバーでも同様にする必要があります(手順 4c)。 - (Next.js)
code.zipを小さく保つ方法は、ほとんどがmorphe.py packageによって自動的に行われます(バインディングの整理とシンボリックリンクを保持した ZIP の作成)。残る大きな要因は通常、ビルド時にトレースされたプロジェクトデータです(生データセット、フィクスチャ、サーバーコンポーネントがreaddirするディレクトリ内の生成物など)。Next の設定でoutputFileTracingExcludesを使ってこれらを削減してください。ただし、process.cwd()経由で実行時に読み込まれるファイル(フォント、ルートで解析する JSON など)は除外しないでください。(Bigfish の ZIP に含まれるのは静的ビルドのみのため、もともと小さく、node_modulesも含まれません。) - (Next.js)実行時にネイティブアドオンが引き続き 500 エラーになり、Cannot find module
<pkg>-linux-x64-gnuが表示される場合、ビルドホストにバイナリがインストールされていません。インストール方法を修正し(手順 4a:pnpm ではsupportedArchitecturesを設定するか、npm i --os=linux --cpu=x64 --libc=glibc …を実行)、再インストール、再ビルド、再パッケージしてください。packageは、必要な Linux バインディングが見つからない場合に警告します。 - (Bigfish)ページが空白になる、またはクライアントルートで 404 になる場合、SPA のフォールバックが
index.htmlに届いていないか、ビルドディレクトリがdist/ではありません。ビルドディレクトリにindex.htmlがあることを確認し、dist/build/outのいずれでもない場合は--static-dirを渡してください。生成される静的サーバーは静的ビルド用です。SSR(deployMode: 'render')アプリには、このラッパーではなく実際のサーバーエントリが必要です。 - (Vite)
packageの esbuild ステップが失敗する(例:No loader is configured for ".node" files、またはvite/lightningcss/fseventsからの glob/require.resolveエラー)場合、サーバーエントリでvite(または別のネイティブアドオン依存関係)をトップレベルでインポートしています。そのインポートを開発時のみのものにするか、遅延読み込みにして(手順 4c)外部化するか、依存関係を--external NAMEで渡してください。 - (Vite)SPA のページが空白になる、またはクライアントルートで 404 になる場合は、Bigfish の場合と同様です。ビルドディレクトリに
index.htmlがあることを確認し、dist/build/outのいずれでもない場合は--static-dirを渡してください。カスタムサーバーのルートが 500 エラーになる場合、依存関係が外部化されているものの実行時に必要であるか、サーバーが静的ディレクトリをprocess.cwd()以外のパスから読み込んでいる可能性があります。手順 4c に従って修正してください。 - (Vite)ローカルでは発生しないのに、実行時にバックエンドルートが 500 エラーになる場合、実行時シークレットの不足が原因であることがよくあります。API キーなどを関数環境に設定してください(
.envから ZIP にバンドルされることはありません)。 - API リファレンス全文:
references/api.md。