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é.
Nội dung chính của bài viết
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}`);
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.
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é.
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à name và year.
Thử thay đổi query, khi mình chỉ muốn lấy mỗi tên phim thôi.
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:
Bình luận. Cùng nhau thảo luận nhé!