GraphQL là gì? Có ưu việt hơn Rest API không. Cùng bắt đầu sử dụng GraphQL

0
Dịch vụ dạy kèm gia sư lập trình

Mình vừa kết thúc một dự án sử dụng tới GraphQL, thấy cũng hay hay. Nó như một luồng gió mới làm thay đổi cách mà chúng ta vẫn làm với các APIs.

Bài viết hôm nay, mình sẽ giới thiệu với các bạn xem GraphQL là gì? Nó có ưu điểm gì so với Rest API truyền thống và cách sử dụng GraphQL như nào nhé.

GraphQL là gì?

Hiểu đơn giản thì GraphQL là ngôn ngữ truy vấn cho API.

GraphQL hiển thị những loại dữ liệu mà server cung cấp và sau đó thì client có tùy ý lựa chọn nhận những gì mà nó muốn (tránh việc tạo thêm enpoint API hoặc tránh việc dư thừa dữ liệu).

Ngoài ra, GraphQL có thể giúp bạn kết hợp nhiều loại dữ liệu trong một lần gọi thay vì phải request tới nhiều REST API.

GraphQL được Facebook phát triển nội bộ vào năm 2012 trước khi phát hành công khai vào năm 2015. Các bạn có thể tham khảo thêm tại trang web chính thức của GraphQL: https://graphql.org

Để các bạn dễ hình dung hơn về GraphQL là gì, chúng ta sẽ cùng nhau thực hành một dự án minh họa kết hợp NodeJS + GraphQL.

Sử dụng GraphQL với NodeJS

GraphQL có thể kết hợp với rất nhiều ngôn ngữ lập trình. Do thói quen nên mình sẽ chọn NodeJS để minh họa cho bài viết này nhé.

Đầu tiên, chúng ta tạo một thư mục graphql-with-nodejs. Sau đó sẽ khởi tạo dự án nodejs trong thư mục này bằng lệnh: npm init

cd graphql-with-nodejs
npm init

Tiếp theo là cài đặt các thư viện cần thiết như expressjs, express-graphql và graphql

npm install express nodemon
npm install express-graphql graphql

Trong thư mục chính của dự án, chúng ta tạo file server.js với nội dung quen thuộc sau:

// server.js
const express = require('express');
const port = 5000;
const app = express();

app.get('/', (req,res) => {
  res.send("Xin chào ACE VNTALKING");
});

app.listen(port);
console.log(`Server Running at localhost:${port}`);
Lưu ý: Bạn nhớ chỉnh lại cấu hình chạy ứng dụng trong package.json trỏ tới file server.js nhé: “scripts”: { “start”: “nodemon server.js” }

Như vậy là chúng ta đã tạo xong một http server. Giờ bạn chạy dự án bằng lệnh npm start và kiểm tra trên trình duyệt: http://localhost:5000

Phần tiếp theo, chúng ta sẽ cùng nhau cấu hình để bật GraphQL.

Cài đặt và Cấu hình GraphQL

GraphQL có một endpoint duy nhất /graphql  để xử lý mọi request tới.

Chúng ta sẽ sử dụng graphqlHTTP của thư viện express-graphql để cài đặt graphQL server tại endpoint  /graphql  

// server.js
const { graphqlHTTP } = require('express-graphql');
const {GraphQLSchema} = require('graphql');
const {queryType} = require('./query.js');

// Define the Schema
const schema = new GraphQLSchema({ query: queryType });

//Setup the nodejs GraphQL server
app.use('/graphql', graphqlHTTP({
    schema: schema,
    graphiql: true,
}));

Mặc dù, chúng ta chỉ có một endpoint tổng duy nhất /graphql để xử lý mọi request. Nhưng vấn đề là request sẽ lại có yêu cầu riêng. Do đó, chúng ta phải định nghĩa Schema để có thể thực hiện nhiều công việc khác nhau.

Các endpoint cụ thể khác sẽ được định nghĩa ở trong Schema.

Schema GraphQL

Schema có chức năng sau:

  • Chỉ định các endpoint cụ thể.
  • Định nghĩa trường đầu vào và đầu ra cho mỗi request.
  • Xác định hành động cụ thể nào được gọi mỗi khi có request tới.

Trong đoạn code trên, mình có định nghĩa trước một schema đơn giản, bạn có thể tham khảo.

//server.js
const {queryType} = require('./query.js');
// Define the Schema
const schema = new GraphQLSchema({ query: queryType });

Nội dung file query.js (bạn có thể tạo mới và điền nội dung dưới đây):

//query.js
const { GraphQLObjectType,
  GraphQLString
} = require('graphql');

//Define the Query
const queryType = new GraphQLObjectType({
  name: 'Query',
  fields: {
    hello: {
      type: GraphQLString,
      resolve: function () {
          return "Xin Chào";
      }
    }
  }
});

exports.queryType = queryType;

Mình sẽ giải thích sơ lược về các trường trong phần định nghĩa schema ở trên.

  • fields: Là nơi chúng ta định nghĩa các endpoint. Ví dụ, như ở đây sẽ là /hello

Với endpoint /hello có kiểu dữ liệu là GraphQLString (tức là dữ liệu trả về tương ứng là String). Hàm sẽ phụ trách xử lý khi endpoint này được gọi là resolve(). Trong ví dụ này, mình chỉ đơn giản là trả về một string “Xin Chào”

Ok, giờ mình sẽ chạy thử ứng dụng và kiểm tra kết quả.

Chạy ứng dụng và test thử GraphQL

Để kiểm tra xem GraphQL hoạt động như nào, mình sẽ chạy thử trên trình duyệt: http://localhost:5000/graphql

Bạn sẽ có thấy giao diện đồ họa WebGUI như dưới đây.

graphql-hello-world

Như vậy là GraphQL đã hoạt động ngon lành rồi đấy.

Để chúng ta có thể trải nghiệm và cảm nhận nhiều hơn ưu điểm của GraphQL, mình sẽ tạo thêm một ví dụ phức tạp hơn một chút nhé.

Thêm endpoint GraphQL

Tương tự như phần tạo endpoint hello, mình sẽ tạo một endpoint có tên /movie, có nhiệm vụ trả về thông tin một bộ phim khi truyền vào ID.

Giả sử mình có dữ liệu danh sách các bộ phim như sau (hiện mình fix cứng, với dự án thực tế thì nó có thể được lấy từ trong DB).

Để tạo mới một endpoint, gồm có 3 bước: tạo dữ liệu, tạo kiểu dữ liệu trả về và cuối cùng là định nghĩa endpoint – kèm hành động xử lý tương ứng

Tạo file movieData.js có nội dung sau:

// movieData.js
let movies = [{
  id: 1,
  name: "Thần điêu đại hiệp 1986",
  year: 1986,
},
{
  id: 2,
  name: "Hoàn châu cách cách",
  year: 2000,
},
{
  id: 3,
  name: "Quá nhanh, quá nguy hiểm 5",
  year: 1999,
}
];

exports.movies = movies;

Trong phần định nghĩa endpoint, bạn để ý là phải định nghĩa kiểu dữ liệu trả về. Nếu endpoint trả về các kiểu dữ liệu nguyên thủy, ví dụ: number, string… thì GraphQL đã có hỗ trợ sẵn tương ứng như: GraphQLInt , GraphQLString…

Tuy nhiên, với kiểu dữ liệu dạng Object thì bạn sẽ phải tự định nghĩa. Do đó, mình sẽ tạo file movieType.js để định nghĩa kiểu dữ liệu cho movie.

// movieType.js
const {
  GraphQLObjectType,
  GraphQLID,
  GraphQLString,
  GraphQLInt
} = require('graphql');

// Define Movie Type
movieType = new GraphQLObjectType({
  name: 'Movie',
  fields: {
      id: { type: GraphQLID },
      name: { type: GraphQLString },
      year: { type: GraphQLInt },
  }
});

exports.movieType = movieType;

Quay trở lại query.js và thêm endpoint /movie

// query.js 
let {movieType} = require('./movieType')
...
movie: {
      type: movieType,
      args: {
          id: { type: GraphQLInt }
      },
      resolve: function (source, args) {
          return movies.find(m => m.id == args.id);
      }
    }

Chạy thử và kiểm tra kết quả nhé.

graphql-movie-query

Như câu lệnh query thử ở trên. Mình muốn lấy thông tin của movie có ID = 2, dữ liệu trả về thì chỉ lấy 2 trường thông tin là nameyear.

Thử thay đổi query, khi mình chỉ muốn lấy mỗi tên phim thôi.

graphql-movie-query-2

Như vậy là mình chỉ cần thay đổi tham số là có kết quả như ý muốn, không cần phải request tới endpoint khác. Như với Rest API bình thường, bạn sẽ phải tạo 2 endpoint tương ứng với 2 trường hợp test ở trên.

Cũng hay đúng không nhỉ?

Các bạn tải mã nguồn đầy đủ tại đây nhé:

Tạm kết

Qua bài viết này, minh hi vọng bạn đã hiểu rõ GraphQL là gì, cũng như ưu điểm của nó so với Rest API truyền thống.

Cá nhân mình nghĩ, với ưu điểm về tốc độ và độ linh hoạt thì sớm muộn gì GraphQL cũng sẽ ngày càng phổ biến hơn nữa.

Bạn có đồng quan điểm với mình không? Để lại bình luận bên dưới nhé!

💥 Đọc thêm bài viết hay ho khác về NodeJS:

Dịch vụ phát triển ứng dụng mobile giá rẻ - chất lượng
Bài trướcMô hình MVC là gì? Giải thích dễ hiểu về MVC (Model – View – Controller)
Bài tiếp theoTại sao Vue.js được nhiều frontend developer lựa chọn
Tên đầy đủ là Dương Anh Sơn. Tốt nghiệp ĐH Bách Khoa Hà Nội. Mình bắt đầu nghiệp coder khi mà ra trường chẳng xin được việc đúng chuyên ngành. Mình tin rằng chỉ có chia sẻ kiến thức mới là cách học tập nhanh nhất. Các bạn góp ý bài viết của mình bằng cách comment bên dưới nhé !

Bình luận. Cùng nhau thảo luận nhé!

avatar
  Theo dõi bình luận  
Thông báo