Trong bài viết này, chúng ta sẽ tìm hiểu cách sử dụng NestJS, MySQL và GraphQL để xây dựng một backend server.

1.Giới thiệu qua các công nghệ

NestJS là một framework Node.js được phát triển trên kiến trúc của Angular, giúp cho việc phát triển ứng dụng backend Node.js trở nên dễ dàng hơn.

MySQL là một hệ quản trị cơ sở dữ liệu phổ biến được sử dụng rộng rãi trong các ứng dụng web.

GraphQL là một ngôn ngữ truy vấn được phát triển bởi Facebook, cho phép các ứng dụng client truy vấn dữ liệu một cách linh hoạt và hiệu quả.

2.Khởi tạo ứng dụng nestjs

Mình sẽ làm theo các bước trong document sau

https://docs.nestjs.com/first-steps

cài đặt nestjs-cli

npm i -g @nestjs/cli

khở tạo nestjs project bằng câu lệnh

nest new project-name

câu lệnh trên sẽ tạo ra một folder có tên là project-name chứa source code do nest-cli sinh ra.

Run thử server bằng một trong hai câu lệnh sau, và truy cập vào http://localhost:3000/ để xem thử response trả về.

npm run start

hoặc nếu muốn server tự restart khi nội dung file thay đổi thì chạy câu lệnh

npm run start:dev

Tất cả các câu lệnh này đều được ghi tại file package.json.

3.Tạo docker-compose file

Hệ thống backend trong bài này sẽ gồm 2 service là server và mysql. Server ta đã khởi tạo ở trên. Tiếp theo ta sẽ tạo một mysql server dùng docker.

File docker-compose sẽ có dạng như sau:

version: "3"
services:
  server:
    build:
      context: ../project-name    --> name of backend folder
      dockerfile: Dockerfile
    environment:
      DB_USERNAME: <-your-db-user->
      DB_PASSWORD: <-your-db-password->
      DB_HOST: mysql
      DB_DATABASE: <-db-name->
    volumes:
      - /usr/src/app/node_modules
    ports:
      - 3001:3001
  mysql:
    image: mysql:8.0.24
    container_name: mysql
    environment:
      MYSQL_ROOT_PASSWORD: <-your-db-password->
      MYSQL_DATABASE: <-db-name->
    volumes:
      - ./docker/mysql/data:/var/lib/mysql
      - ./docker/mysql/my.cnf:/etc/mysql/conf.d/my.cnf
      - ./docker/mysql/initdata:/docker-entrypoint-initdb.d
    ports:
      - 3306:3306

4.Config nestjs server connect tới mysql

Ta sẽ làm theo tài liệu dưới đây để setup database connection.

https://docs.nestjs.com/techniques/database

Thư viện typeorm được sử dụng để thao tác với dữ liệu từ DB.

Cài đặt thư viện cần thiết:

npm install --save @nestjs/typeorm typeorm mysql2

Thêm config database vào file app.module.ts:


import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';

@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'mysql',
      host: 'localhost',
      port: 3306,
      username: '<-your-db-user->',
      password: '<-your-db-password->',
      database: '<-db-name->',
      entities: [<-your-tables->],
      synchronize: true,
    }),
  ],
})
export class AppModule {}

synchronize: true sẽ tự động migrate DB khi ta sửa file model.

5. Config graphql

Ta sẽ làm theo tài liệu dưới đây để setup graphql cho project.

https://docs.nestjs.com/graphql/quick-start

Install thư viện cần thiết

npm i @nestjs/graphql @nestjs/apollo @apollo/server graphql

Thêm config sau vào app.module.ts

import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';

@Module({
  imports: [
    GraphQLModule.forRoot<ApolloDriverConfig>({
      driver: ApolloDriver,
      debug: false,
      playground: true,
      autoSchemaFile: join(process.cwd(), 'src/schema.gql')
    }),
  ],
})
export class AppModule {}

Option playground: true giúp ta có thể mở ra trang giao diện để thao tác với các graphql API thông qua địa chỉ sau http://localhost:3000/graphql.

Tiếp theo ta sẽ tạo một module và resolver cho module đó như hướng dẫn dưới đây.

https://docs.nestjs.com/graphql/resolvers

Tạo file author.model.ts

import { Field, ID, Int, ObjectType } from '@nestjs/graphql';
import { Column, Entity, Index, PrimaryGeneratedColumn } from 'typeorm';

@ObjectType()
@Entity()
export class Author {
  @PrimaryGeneratedColumn('increment')
  @Field((type) => ID)
  readonly id?: number;

  @Column({ length: 32 })
  @Index({ unique: true })
  @Field()
  public name: string;
}

Tạo file authors.resolver.ts

@Resolver(of => Author)
export class AuthorsResolver {
  constructor(
    private authorsService: AuthorsService,
  ) {}

  @Query(returns => Author, { name: 'author' })
  async getAuthor(@Args('id', { type: () => Int }) id: number) {
    return this.authorsService.findOneById(id);
  }

}

Tạo file authors.service.ts

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Author } from './author.model';

@Injectable()
export class AuthorsService {
  constructor(
    @InjectRepository(Author)
    private authorsRepository: Repository<Author>,
  ) {}

  findOneById(id: number): Promise<Author> {
    return this.authorsRepository.findOneBy({ id });
  }

}

Tạo file authors.module.ts

@Module({
  imports: [PostsModule],
  providers: [AuthorsService, AuthorsResolver],
})
export class AuthorsModule {}

Import author module vào app.module.ts

import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';

@Module({
  imports: [
    GraphQLModule.forRoot<ApolloDriverConfig>({
      driver: ApolloDriver,
      debug: false,
      playground: true,
      autoSchemaFile: join(process.cwd(), 'src/schema.gql')
    }),
    AuthorsModule,
  ],
})
export class AppModule {}

Như vậy ta đã code xong các file cần thiết. Ta có thể mở playground để thao tác thử với query graphql vừa tạo.

Kết luận

Bài viết đã trình bày các bước để xây dựng một project backend bằng các công nghệ nestjs, graphql, mysql, docker-compose.

Trong bài tiếp theo, mình sẽ tạo một project front-end dùng nextjs để giao tiếp với server đã xây dựng.