Node.jsベースのオープンソースECプラットフォームMedusaの基本からカスタマイズまで
Medusa.jsは、開発者向けに設計されたオープンソースのヘッドレスコマースプラットフォームです。柔軟性と拡張性の高さが特徴で、Node.jsをベースに構築されています。ヘッドレスアーキテクチャを採用しているため、バックエンドのコマース機能とフロントエンドの表示レイヤーが完全に分離されており、開発者は好みのフロントエンド技術(React, Vue, Next.jsなど)を使って自由なUI/UXを構築できます。ShopifyなどのSaaS型プラットフォームと比較して、より高度なカスタマイズや独自のビジネスロジックの実装を求める場合に強力な選択肢となります。このガイドでは、Medusaの基本的な使い方から、カスタマイズ、応用までを詳しく解説していきます。
Medusaとは何か? 🤔
Medusaは、単なるECプラットフォームではなく、「コマースエンジン」や「コマースフレームワーク」とも呼ばれます。これは、ECサイトに必要な基本的な機能(商品管理、カート、注文管理、顧客管理など)を提供するだけでなく、それらをカスタマイズしたり、独自の機能を追加したりするための基盤(フレームワーク)を提供しているからです。
主な特徴は以下の通りです。
- ヘッドレスアーキテクチャ: フロントエンドとバックエンドを分離。APIを通じてデータをやり取りするため、自由な技術選択とマルチチャネル展開(Web, モバイルアプリ, POSなど)が可能です。
- モジュラー設計: 機能がモジュール化されており、必要な機能だけを選んで利用したり、特定のモジュールを独自実装に置き換えたりできます。カートロジック、商品管理、支払い、配送などが独立しています。
- 開発者フレンドリー: Node.js (TypeScript) ベースで開発されており、最新のJavaScript開発環境との親和性が高いです。拡張のためのツールやドキュメントが充実しています。
- カスタマイズ性: APIエンドポイントの追加、ビジネスロジックの変更、管理画面の拡張など、高度なカスタマイズが可能です。
- オープンソース: MITライセンスで公開されており、無料で利用できます。GitHub上で活発に開発が進められており、コミュニティも存在します。
2024年後半にはメジャーバージョンである Medusa v2.0 がリリースされ、アーキテクチャが刷新され、パフォーマンスや拡張性がさらに向上しました。D2C(Direct-to-Consumer)だけでなく、B2B、マーケットプレイス、サブスクリプションなど、多様なビジネスモデルに対応できる柔軟性を持っています。
🛠️ 始める前の準備
Medusaを始める前に、以下の環境が整っていることを確認してください。
-
Node.js: Medusa v2.0以降では、Node.js v20以上が推奨されています。バージョンを確認するには、ターミナルで以下のコマンドを実行します。
Node.jsがインストールされていない場合やバージョンが古い場合は、公式サイトやnvm (Node Version Manager) を使ってインストール・アップデートしてください。node -v
-
パッケージマネージャー: npm (Node.jsに同梱) または Yarn。このガイドでは主にnpmを使用します。
npm -v yarn -v
-
Git: バージョン管理システム。Medusaプロジェクトの作成や管理に内部的に使用されることがあります。
git --version
- PostgreSQL: Medusaのデフォルトデータベースです。ローカルにインストールするか、クラウド上のデータベースサービス(例: Neon, Supabase, AWS RDS)を利用できます。Medusaのセットアッププロセス中にデータベース接続情報が必要になります。
これらのツールがインストールされ、正しく設定されていることを確認してから、次のステップに進んでください。
🚀 Medusaプロジェクトの作成とインストール
Medusaプロジェクトの作成は、`create-medusa-app` というCLIツールを使って簡単に行うことができます。このツールはMedusaバックエンド、管理画面(Admin)、そしてオプションでNext.js製のストアフロントを一度にセットアップしてくれます。
ターミナルを開き、以下のコマンドを実行します。
npx create-medusa-app@latest
このコマンドを実行すると、対話形式で設定が進みます。
- プロジェクト名: プロジェクト(フォルダ)の名前を入力します。例: `my-medusa-store`
- スターター選択: どのテンプレートを使用するか選択します。通常は `medusa-starter-default` (バックエンド+管理画面) または `Next.js Starter` (バックエンド+管理画面+Next.jsストアフロント) を選びます。ここでは `Next.js Starter` を選択する例で進めます。
- PostgreSQLデータベースの設定:
- データベース名: 使用するデータベース名を入力します (例: `medusa-db`)。
- ユーザー名: PostgreSQLのユーザー名。
- パスワード: PostgreSQLのパスワード。
インストールプロセスが完了すると、指定したプロジェクト名のフォルダ内に以下の構造でファイルが生成されます(Next.js Starterを選択した場合)。
my-medusa-store/
backend/
: Medusaバックエンドサーバーのコードadmin/
: Medusa管理画面のコード (Viteベース)storefront/
: Next.js製のストアフロントのコード
これでMedusaプロジェクトの基本的なセットアップは完了です。🎉
DATABASE_URL=postgres://[USER]:[PASSWORD]@[HOST]:[PORT]/[DB_NAME]
🏃♀️ Medusaの起動
`create-medusa-app` でプロジェクトを作成した後、各コンポーネント(バックエンド、管理画面、ストアフロント)を起動してみましょう。それぞれのディレクトリに移動して開発サーバーを起動します。
1. バックエンドサーバーの起動
バックエンドサーバーは、APIを提供し、ビジネスロジックを実行する中心部分です。
cd my-medusa-store/backend
npm run dev
デフォルトでは、バックエンドサーバーは `http://localhost:9000` で起動します。初回起動時にはデータベースのマイグレーション(テーブル作成など)が実行されます。
2. 管理画面 (Admin) の起動
管理画面は、商品登録、注文管理、顧客管理などを行うためのWebインターフェースです。
cd my-medusa-store/admin
npm run dev
デフォルトでは、管理画面は `http://localhost:7001` で起動します。初回アクセス時には管理者ユーザーの作成を求められます。メールアドレスとパスワードを設定してログインしてください。
3. ストアフロント (Storefront) の起動
Next.js Starterを選択した場合、顧客向けのECサイト(ストアフロント)も起動できます。
cd my-medusa-store/storefront
npm run dev
デフォルトでは、ストアフロントは `http://localhost:8000` で起動します。バックエンドサーバーから商品情報を取得して表示します。
これで、Medusaのバックエンド、管理画面、ストアフロントがローカル環境で動作している状態になります。管理画面で商品を登録したり、ストアフロントで商品を表示・購入(テスト)したりすることができます。
⚙️ Medusaのコアコンセプト
Medusaを効果的にカスタマイズ・拡張するためには、いくつかのコアコンセプトを理解しておくことが重要です。
コンセプト | 説明 |
---|---|
Modules (モジュール) | 特定の機能(カート、注文、商品、支払いなど)を担当する独立したコードの集まり。Medusaはこれらのモジュールを組み合わせて構成されています。一部のモジュールは独自のものに置き換えることが可能です。 |
Services (サービス) | ビジネスロジックをカプセル化するクラス。データベース操作や外部APIとの連携など、特定のタスクを実行します。例えば `ProductService` は商品の取得や作成ロジックを持ちます。DI (Dependency Injection) コンテナを通じて他のサービスやリポジトリを利用できます。 |
Entities (エンティティ) | データベースのテーブルに対応するクラス。TypeORMというORM (Object-Relational Mapper) を使用しており、エンティティ定義がデータベーススキーマを決定します。例: `Product`, `Order`, `Customer` など。 |
Repositories (リポジトリ) | エンティティに対するデータベース操作(CRUD: Create, Read, Update, Delete)を抽象化するクラス。TypeORMのリポジトリパターンに基づいています。サービス内でリポジトリを使ってデータアクセスを行います。 |
API Routes (APIルート) | Express.jsのルーターを使用して定義されるHTTPエンドポイント。ストアフロントや管理画面、外部システムからのリクエストを受け付け、対応するサービスを呼び出して処理を実行します。カスタムAPIエンドポイントを追加することも容易です。 |
Subscribers (サブスクライバー) | 特定のイベント(例: `order.placed`, `product.created`)が発生したときに非同期で処理を実行するクラス。イベント駆動型のアーキテクチャを実現します。メール送信、在庫更新、外部システム連携などに利用されます。 |
Loaders (ローダー) | サーバー起動時にカスタムロジックを実行するための仕組み。Expressミドルウェアの登録、カスタムジョブスケジューラの初期化などに使用できます。 |
Workflows (ワークフロー) | Medusa v2.0で導入された主要な機能。複数のステップ(アクション)からなる複雑なビジネスプロセスを定義・実行するための仕組み。注文処理、返品処理などがワークフローとして実装されています。トランザクション管理や補償(失敗時のロールバック)機能も備えています。 |
Plugins (プラグイン) | Medusaの機能を拡張するためのパッケージ。支払いゲートウェイ(Stripe, PayPalなど)、配送業者連携、検索エンジン(Meilisearch, Algolia)、CMS連携(Contentful, Strapi)など、様々なプラグインが公式やコミュニティから提供されています。自作することも可能です。 |
これらのコンセプトを理解することで、Medusaの内部構造を把握し、ドキュメントを読み解きながら効果的なカスタマイズや機能追加を行えるようになります。
🔧 Medusaのカスタマイズ例
Medusaの大きな魅力はそのカスタマイズ性の高さです。ここではいくつかの一般的なカスタマイズ例を紹介します。コードはバックエンドプロジェクト (`my-medusa-store/backend`) 内の `src` ディレクトリに配置します。
1. カスタムAPIエンドポイントの追加
独自のAPIエンドポイントを追加して、特定の機能を提供できます。例えば、特別な商品リストを取得するAPIを作成する場合:
src/api/store/custom-products/route.ts
(または .js
) を作成します。
// src/api/store/custom-products/route.ts
import type { MedusaRequest, MedusaResponse } from "@medusajs/medusa";
import ProductService from "../../../../services/product"; // 仮のパス
export async function GET(
req: MedusaRequest,
res: MedusaResponse
): Promise<void> {
// DIコンテナからProductServiceを取得
const productService = req.scope.resolve<ProductService>("productService");
try {
// 独自のロジックで商品を取得 (例: 特定のタグを持つ商品)
const [products, count] = await productService.listAndCount(
{ tags: { value: ['featured'] } }, // 例: 'featured' タグを持つ商品
{ relations: ["variants", "options", "images"] }
);
res.status(200).json({ products, count });
} catch (error) {
console.error("Error fetching custom products:", error);
res.status(500).json({ message: "Internal server error" });
}
}
このファイルを配置すると、Medusaサーバーが自動的に検出し、 `http://localhost:9000/store/custom-products` というエンドポイントが利用可能になります。
2. 既存サービスの拡張 (Service Override)
既存のサービスのメソッドをオーバーライドして、挙動を変更できます。例えば、商品作成時にカスタムフィールドを追加する処理を入れる場合:
src/services/product.ts
(または .js
) を作成します。
// src/services/product.ts
import { ProductService as MedusaProductService } from "@medusajs/medusa";
import { Product } from "../models/product"; // カスタムエンティティを使用する場合
import { CreateProductInput, UpdateProductInput } from "@medusajs/medusa/dist/types/product"; // 型定義
class ProductService extends MedusaProductService {
// 例: 商品作成メソッドをオーバーライド
async create(productObject: CreateProductInput): Promise<Product> {
// --- ここにカスタムロジックを追加 ---
console.log("Custom logic before creating product:", productObject.title);
// 例: 特定のメタデータを自動付与
if (!productObject.metadata) {
productObject.metadata = {};
}
productObject.metadata.custom_flag = true;
// --- カスタムロジックここまで ---
// 元の作成メソッドを呼び出す
const newProduct = await super.create(productObject);
// --- ここに作成後のカスタムロジックを追加 ---
console.log("Custom logic after creating product:", newProduct.id);
// --- カスタムロジックここまで ---
return newProduct;
}
// 他のメソッドも必要に応じてオーバーライド可能
// async update(productId: string, update: UpdateProductInput): Promise<Product> { ... }
}
export default ProductService;
このようにクラスを継承して同名のファイルを作成すると、Medusaは自動的にカスタムサービスを使用するようになります。
3. イベントの購読 (Subscriber)
注文確定時などに特定の処理(例: 外部システムへの通知)を行いたい場合、サブスクライバーを作成します。
src/subscribers/order-notifier.ts
(または .js
) を作成します。
// src/subscribers/order-notifier.ts
import { OrderService, type SubscriberConfig, type SubscriberArgs } from "@medusajs/medusa";
export default async function handleOrderPlaced({
data,
eventName,
container,
pluginOptions,
}: SubscriberArgs<Record<string, any>>) {
console.log(`Received event: ${eventName} with data:`, data);
const orderService = container.resolve<OrderService>("orderService");
const order = await orderService.retrieve(data.id, { relations: ["items", "customer"] });
// --- ここにカスタム処理を実装 ---
console.log(`Order ${order.display_id} placed by ${order.customer.email}`);
// 例: 外部APIに注文情報を送信
// await notifyExternalSystem(order);
// --- カスタム処理ここまで ---
}
// 購読するイベントを設定
export const config: SubscriberConfig = {
event: OrderService.Events.PLACED, // 注文確定イベント
context: {
subscriberId: "order-placed-notifier",
},
};
このファイルを配置すると、注文が確定するたびに `handleOrderPlaced` 関数が実行されるようになります。
これらはカスタマイズのほんの一例です。Medusaの柔軟なアーキテクチャにより、ビジネス要件に合わせて様々な拡張が可能です。詳細は公式ドキュメントを参照してください。
🌐 デプロイと運用
開発が完了したら、Medusaアプリケーションを本番環境にデプロイする必要があります。MedusaはNode.jsアプリケーションなので、様々なホスティングオプションが利用可能です。
デプロイオプション
- PaaS (Platform as a Service): Heroku, Render, DigitalOcean App Platform など。設定済みの環境でNode.jsアプリを簡単にデプロイできます。
- IaaS (Infrastructure as a Service): AWS EC2, Google Compute Engine, Azure Virtual Machines など。サーバーインフラを自分で管理する必要がありますが、自由度は最も高いです。
- コンテナオーケストレーション: Docker と Kubernetes。スケーラビリティと管理性に優れていますが、設定が複雑になる場合があります。
- Medusa Cloud (公式ホスティング): Medusaチームが提供するマネージドホスティングサービス。インフラ管理の手間を省き、開発に集中できます。(利用可能性や料金は公式サイトを確認してください)
デプロイ時の考慮事項
- 環境変数: データベース接続情報、外部サービスAPIキー、JWTシークレットなどを環境変数で設定します。`.env` ファイルは本番環境に含めず、ホスティングサービスの環境変数設定機能を使用します。
- データベース: 本番環境用のPostgreSQLデータベースを用意します。クラウドデータベースサービス (AWS RDS, Google Cloud SQL, Neonなど) の利用が一般的です。
- Redis: イベントキューやキャッシュのためにRedisの導入が推奨されます。これもクラウドサービスを利用できます。
- ビルドプロセス: TypeScriptで開発している場合、JavaScriptにトランスパイルする必要があります。バックエンドでは `npm run build` コマンドを実行します。
- 起動コマンド: 本番環境では `npm run start` コマンドでサーバーを起動します。パフォーマンス向上のためにクラスターモード (`npm run start:cluster`) を利用することも検討します。
- 管理画面とストアフロント: これらは静的サイトまたはNode.jsアプリケーションとして別途デプロイします。Vercel, Netlify, AWS Amplifyなどがよく利用されます。
- ファイルストレージ: 商品画像などのファイルは、ローカルストレージではなく、AWS S3, Google Cloud Storage, DigitalOcean Spaces などのオブジェクトストレージを使用することが推奨されます。対応するファイルサービスプラグインをインストール・設定します。
- CORS設定: バックエンドの環境変数 (`STORE_CORS`, `ADMIN_CORS`) で、ストアフロントや管理画面のドメインからのアクセスを許可するように設定します。
まとめと次のステップ ✨
このガイドでは、オープンソースのヘッドレスコマースプラットフォームであるMedusa.jsの基本的な使い方、コアコンセプト、カスタマイズ方法、そしてデプロイについて解説しました。Medusaは、その柔軟性と拡張性により、開発者が独自のEC体験を構築するための強力な基盤を提供します。
主なポイント:
- MedusaはNode.jsベースのヘッドレス・モジュラーコマースプラットフォーム。
- `create-medusa-app` で簡単にプロジェクトを開始できる。
- バックエンド、管理画面、ストアフロントの3つの主要コンポーネントで構成される。
- サービス、エンティティ、APIルート、サブスクライバーなどのコアコンセプトを理解することがカスタマイズの鍵。
- APIエンドポイントの追加、サービスのオーバーライド、イベントの購読など、様々なカスタマイズが可能。
- デプロイには様々なオプションがあるが、環境変数、データベース、ファイルストレージなどの設定が重要。
今後の学習や開発のためのステップ:
- 公式ドキュメントの深掘り: Medusa V2 Documentationには、各機能やAPIに関する詳細な情報が網羅されています。
- プラグインの活用: 支払い、配送、検索、CMS連携など、必要な公式・コミュニティプラグインを探して導入してみましょう。
- チュートリアルと事例研究: 公式チュートリアルやブログ記事で、具体的なユースケースの実装方法を学びましょう。
- コミュニティへの参加: DiscordサーバーやGitHub Discussionsで質問したり、他の開発者と交流したりできます。
Medusaを使って、あなたのビジネスに最適な、ユニークで高性能なEコマース体験を構築してみてください! Happy coding! 💻
コメント