mcpField
M
morphe

morphe

github.com/zenmuxクラウド・DevOps20180 回インストール6 週間前に更新
リポジトリ

morphe について

morphe は、Next.js、Bigfish、Vite のプロジェクトをパッケージ化して Morphe にデプロイするスキルです。静的 SPA と Vite のカスタムサーバーに対応した実行可能な ZIP を作成します。

主な機能

  1. 01Next.js・Bigfish・Vite プロジェクトの検出
  2. 02Next.js standalone ビルドの組み立て
  3. 03静的アプリ向けゼロ依存サーバーの生成
  4. 04Vite カスタムサーバーの単一ファイル化
  5. 05パッケージ化・アップロード・検証・デプロイ

活用シーン

  1. 01Next.js standalone ビルドのデプロイ
  2. 02Bigfish 静的サイトの Morphe へのデプロイ
  3. 03Vite SPA のデプロイ
  4. 04API ルート付き Vite カスタムサーバーのパッケージ化

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/zenmux/skills --skill morphe

インストール後、Claude Code で/morpheを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
api.md
nextjs-config.md
scripts/
auth-callback.mjs
login.sh
morphe.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 化を行いますが、インストール時に実際にダウンロードされたバイナリしか同梱できません。

設定をその場で編集し、次の条件を満たしてください。

  1. standalone 出力 — output: "standalone"(そうしないと、zip 化する .next/standalone/ がありません)。

  2. ビルドホストに 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。
  3. (任意)バンドルをさらに削減します。 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 にします。サーバーが以下を満たしていることを確認してください。

    1. process.env.PORT || 3000 でリッスンし、0.0.0.0 にバインドすること(ランタイムは PORT を設定し、すべてのインターフェースにルーティングします)。
    2. 静的ファイルのディレクトリを process.cwd() から読み込むこと(例:path.join(process.cwd(), "dist"))。zip にはビルドディレクトリが server.js とともにランタイムの作業ディレクトリに含まれるためです。
    3. 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_session Cookie と 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。

コメント