モダンWeb開発の最前線!Next.js & Nest.js & Prismaで創るGraphQLアプリ

Next.js & Nest.js & Prisma を利用してGraphQLを使ったアプリケーションを作成する

目次

最新のWebアプリケーション開発において、パフォーマンス、スケーラビリティ、そして開発者体験の向上は常に重要な課題です。もしあなたが、これらの課題を解決し、高品質なアプリケーションを効率的に開発したいと考えているなら、本記事で紹介する「Next.js(フロントエンド)」「Nest.js(バックエンド)」「Prisma(ORM)」「GraphQL(API)」の強力な組み合わせは、まさにあなたの探しているソリューションかもしれません。この記事では、これらのモダンな技術スタックを統合し、スケーラブルでメンテナンス性の高いアプリケーションを構築する具体的な方法を、実践的なコード例を交えながら詳しく解説します。さあ、あなたの開発スキルを次のレベルへ引き上げましょう。

なぜ今、モダンなGraphQLアプリケーション開発が注目されるのか?

近年、Webアプリケーションの複雑化に伴い、フロントエンドとバックエンドの連携方法が開発効率を大きく左右するようになりました。特にAPI設計においては、RESTful APIの課題(オーバーフェッチ・アンダーフェッチ)が顕在化し、より柔軟で効率的なデータ取得が求められています。そこで登場するのがGraphQLです。

GraphQLは、クライアントが必要なデータだけを要求できるため、通信量を最適化し、フロントエンドの開発体験を大幅に向上させます。さらに、Next.js、Nest.js、Prismaといった最新技術と組み合わせることで、開発の生産性、アプリケーションの堅牢性、そして将来的な拡張性を飛躍的に高めることが可能です。

各技術スタックの役割とメリット

  • Next.js (フロントエンド): Reactをベースとしたフレームワークで、SSR(サーバーサイドレンダリング)やSSG(静的サイト生成)に対応し、高速なページ表示とSEOに強いアプリケーションを構築できます。ファイルシステムベースのルーティングやAPI Routesなど、開発を加速する機能が豊富です。
  • Nest.js (バックエンド): Node.jsのフレームワークで、TypeScriptファースト、モジュール化されたアーキテクチャ、DI(依存性注入)が特徴です。エンタープライズレベルの堅牢なAPIサーバーを効率的に構築でき、GraphQLとの統合も非常にスムーズです。
  • Prisma (ORM): 次世代のデータベースツールキットで、型安全なデータベースアクセスを提供します。スキーマ定義からマイグレーション、クエリ生成までを一元管理し、開発者がSQLを直接書く手間を省き、エラーを減らします。PostgreSQL、MySQL、SQLiteなど主要なRDBをサポートしています。
  • GraphQL (API): Facebookが開発したAPIクエリ言語です。クライアントがどのようなデータを必要とするかを定義できるため、必要なデータだけを一度のリクエストで取得でき、フロントエンドとバックエンド間の密結合を防ぎます。
エンジニア

この組み合わせの最大のメリットは、型安全性がフロントエンドからバックエンド、データベースまで一貫して保たれることですね。開発中のエラーを早期に発見しやすくなります。

デザイナー

なるほど!フロントエンド側で必要なデータ構造がはっきりわかるから、デザインやUI実装もスムーズに進められそうです。

開発環境のセットアップから基本構成まで

実際にこれらの技術スタックを使ってアプリケーションを構築する方法を見ていきましょう。ここでは、pnpmを使ったモノレポ構成とTypeScriptを前提とします。

Prismaの導入とデータベース連携

まず、Prisma CLIをインストールし、データベーススキーマを定義します。ここではSQLiteを例にしますが、PostgreSQLなど他のデータベースでも同様です。

pnpm add -D prisma
pnpm prisma init --datasource-provider sqlite

`prisma/schema.prisma` にモデルを定義します。例えば、ユーザーモデルは以下のように記述できます。

// prisma/schema.prisma
generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "sqlite"
  url      = env("DATABASE_URL")
}

model User {
  id    Int     @id @default(autoincrement())
  email String  @unique
  name  String?
  posts Post[]
}

model Post {
  id        Int      @id @default(autoincrement())
  title     String
  content   String?
  published Boolean  @default(false)
  author    User     @relation(fields: [authorId], references: [id])
  authorId  Int
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

スキーマ定義後、マイグレーションを実行し、データベースにテーブルを作成します。

pnpm prisma migrate dev --name init

Nest.jsでのAPIサーバー構築とGraphQL統合

Nest.jsプロジェクトを作成し、GraphQLモジュールを導入します。ここではコードファーストでスキーマを自動生成する方法を採用します。

pnpm add @nestjs/graphql @nestjs/apollo apollo-server-express graphql

`app.module.ts`でGraphQLモジュールを設定します。

// src/app.module.ts
import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { UserModule } from './user/user.module'; // 後述のUserモジュール

@Module({
  imports: [
    GraphQLModule.forRoot({
      driver: ApolloDriver,
      autoSchemaFile: 'schema.gql', // スキーマファイルを自動生成
      sortSchema: true,
    }),
    UserModule, // 作成したUserモジュールをインポート
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

Userモジュールとリゾルバ、サービスを作成します。Prismaクライアントを注入し、データベース操作を行います。

// src/user/user.module.ts
import { Module } from '@nestjs/common';
import { UserResolver } from './user.resolver';
import { UserService } from './user.service';
import { PrismaService } from '../prisma/prisma.service'; // Prismaサービスを別途作成

@Module({
  providers: [UserResolver, UserService, PrismaService],
})
export class UserModule {}
// src/user/user.resolver.ts
import { Resolver, Query, Mutation, Args } from '@nestjs/graphql';
import { User } from './models/user.model';
import { UserService } from './user.service';
import { CreateUserInput } from './dto/create-user.input';

@Resolver(() => User)
export class UserResolver {
  constructor(private readonly userService: UserService) {}

  @Query(() => [User])
  async users(): Promise {
    return this.userService.findAll();
  }

  @Mutation(() => User)
  async createUser(@Args('input') input: CreateUserInput): Promise {
    return this.userService.create(input);
  }
}

Next.jsとApollo Clientでデータフェッチ

Next.jsプロジェクトでApollo Clientをセットアップし、バックエンドのGraphQL APIからデータを取得します。

pnpm add @apollo/client graphql

Apollo Clientの設定を行います。通常はカスタム`_app.tsx`でラップします。

// components/ApolloProviderWrapper.tsx
import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client';

const client = new ApolloClient({
  uri: 'http://localhost:3000/graphql', // Nest.jsのGraphQLエンドポイント
  cache: new InMemoryCache(),
});

export function ApolloProviderWrapper({ children }: { children: React.ReactNode }) {
  return {children};
}

そして、Next.jsのページコンポーネントでGraphQLクエリを実行します。

// pages/index.tsx
import { gql, useQuery } from '@apollo/client';
import { ApolloProviderWrapper } from '../components/ApolloProviderWrapper';

const GET_USERS = gql`
  query GetUsers {
    users {
      id
      name
      email
    }
  }
`;

function UsersList() {
  const { loading, error, data } = useQuery(GET_USERS);

  if (loading) return 

Loading users...

; if (error) return

Error: {error.message}

; return (

Users

    {data.users.map((user: { id: number; name: string; email: string }) => (
  • {user.name} ({user.email})
  • ))}
); } export default function Home() { return ( ); }

GraphQLがもたらす開発体験の向上

GraphQLは、単にデータを取得するだけでなく、開発体験そのものを大きく向上させます。特に注目すべきは以下の点です。

  • 必要なデータだけを取得: クライアントがクエリで欲しいフィールドだけを指定できるため、不要なデータを取得する「オーバーフェッチ」や、複数のAPIリクエストが必要となる「アンダーフェッチ」の問題を解消します。これにより、ネットワーク帯域の消費を抑え、アプリケーションのパフォーマンスを向上させます。
  • 強力な型システム: スキーマ定義により、APIの型が明確になります。これにより、フロントエンドとバックエンドの連携がスムーズになり、開発時の型不整合によるエラーを大幅に削減できます。自動補完やエラーチェックの恩恵も受けられます。
  • 単一のエンドポイント: 複数のリソースに対して一つのエンドポイントでアクセスできるため、クライアント側でのAPI管理がシンプルになります。
エンジニア

GraphQLのおかげで、フロントエンドとバックエンドの「契約」が明確になります。バックエンド開発者はAPIの変更でフロントエンドに与える影響を予測しやすくなり、フロントエンド開発者はバックエンドの仕様変更に怯える必要がなくなります。

デザイナー

それは安心感がありますね!デザイン変更でデータの追加が必要になっても、スムーズに対応できそうです。

まとめ

  • Next.js、Nest.js、Prisma、GraphQLの組み合わせは、モダンなWebアプリケーション開発における強力な選択肢です。
  • これらの技術スタックを連携させることで、高い開発効率とパフォーマンスを実現できます。
  • GraphQLは柔軟なデータ取得と強力な型システムを提供し、開発者体験を大きく向上させます。
  • Prismaは型安全なデータベースアクセスを提供し、Nest.jsは堅牢なバックエンドを構築します。
  • Next.jsはSSR/SSGにより高速なフロントエンドを実現し、スケーラブルでメンテナンス性の高いアプリケーション構築を可能にします。

本記事で紹介した内容が、あなたの次のプロジェクトのインスピレーションとなり、より効率的でパワフルなアプリケーション開発の一助となれば幸いです。ぜひ、この最先端の技術スタックをあなたの開発に導入してみてください。

ソースコード

https://github.com/isystk/nextjs-nestjs-graphql

コメントを残す

入力エリアすべてが必須項目です。メールアドレスが公開されることはありません。

内容をご確認の上、送信してください。