Single Page Applications, Server Side Rendering, Client Side Rendering and so on.

Single Page Applications, hay mình thường gọi là Single Page App - SPA giờ đã trở nên quá đỗi quen thuộc và là một xu hướng của web. Vậy bạn đã thực sự hiểu rõ nó chưa? Bài viết này với mục đích cung cấp một cái nhìn "nông dân" hết sức có thể để chỉ với kiến thức về HTML, CSS, JQuery là đã có thể nắm bắt được. Đây không phải là một bài dịch từ một nguồn nào đó hoặc là kể ra lịch sử hình thành phát triển và các công nghệ hiện tại áp dụng cho SPA, chỉ đơn thuần là kể lại quá trình một lập trình viên frontend như mình tiếp cận nó và làm việc cho tới bây giờ mà thôi. Nào bắt đầu. Nếu bạn không thích đọc nhiều, có thể kéo xuống và đọc tới phần "Cốt lõi của một SPA" luôn :)

Yêu từ cái nhìn đầu tiên

Tôi bắt đầu học lập trình web khá muộn, khi đó đang là sinh viên năm ba và đang theo học một ngành chẳng liên quan gì tới web. Ấy vậy mà sau một tuần bắt đầu làm việc với HTML, CSS và JQuery, tôi đã yêu cái hướng đi này. Ban đầu, cũng như ai khác, tôi tập tành mò mẫm từng file .PSD, chăm chút từng pixel để CSS chuẩn, sau đó đến sử dụng JQuery. Cho tới giờ, khỏi phải bàn cãi JQuery vẫn là thư viện phổ biến nhất thế giới, dù bạn có là fan của Angular, React hay Vue gì gì đi chăng nữa. Sau một thời gian dùng JQuery, vào một ngày đẹp trời tôi tự hỏi cái trang gmail mình hay dùng nó viết sao mà không cần phải load lại trang mà vẫn làm được hàng tá thứ như vậy nhỉ? Nếu mình dùng JQuery mà gọi ajax như vậy thì phải dùng bao nhiêu hàm html(), append(), prepend()... cho đủ nhỉ?
Gmail là sự khởi đầu của tôi với SPA, cũng là một trong những lý do tôi thích Google.

Bắt đầu với SPA

Câu hỏi trên tôi đặt ra nhưng chẳng chịu giải quyết, vì hồi đó còn cố gắng học để lấy cái bằng, mà bây giờ mới thấy là tôi còn chẳng nhớ để nó ở xó nào. Đi làm rồi, chả ai hỏi bằng gì, chẳng một chỗ nào, sự thật 100%. Nếu mà hồi đó chịu khó tìm hiểu thì giờ chắc trình cũng kha khá rồi :D
Dù hơi lâu, nhưng cuối cùng cũng tới, tôi được tiếp cận với Angular 1.5 và từ đó mình mới ngộ ra cái thực sự làm nên những điều kì diệu như Gmail vẫn làm là như thế nào. Lúc đó mới vỡ lẽ ra mình không phải trả lời cho câu hỏi cần gọi bao nhiêu hàm $.ajax() hay html() của JQuery nữa :D

Nãy giờ là nói dông dài thôi =)) giờ mới bắt đầu.

Sự ra đời

Chúng ta bắt đầu từ kiến trúc của công nghệ web, phổ biến hiện tại là Server-Client. Về phía Server, dù là ngôn ngữ nào, tóm lại cũng chỉ là database, một hệ thống backend để lấy dữ liệu từ database, một hệ thống làm việc với các giao thức (ví dụ HTTP) để gửi và nhận request, xử lý request và trả lại response cho phía client.
Về phía client, cuối cùng những cái mà một lập trình viên cần giải quyết không gì hơn là HTML, CSS và Javascript.

Quay trở về thời gian trước khi những ứng dụng SPA còn chưa phổ biến, sự tách biệt giữa client và server còn thực sự chưa rõ ràng, khi đó chỉ cần 1 framework như Laravel của PHP là đủ xử hết mọi thứ. Ứng dụng web lúc đó là Server Side Rendering, nghĩa là server hoàn toàn render ra mã HTML, CSS và cả Javascript để trả về hết cho client một lần, mình nói một lần chứ không phải là một request nhé. Bạn có thể thấy dễ dàng các trang web lúc trước trả về hẳn một trang HTML với CSS và Jascript đầy đủ ở request đầu tiên khi bật chrome devtool lên xem.
Khi mà SPA ra đời, mọi thứ được nghĩ theo một hướng hoàn toàn khác, khi server không phải làm công việc nặng nhọc đó là render ra toàn bộ mã HTML, CSS, JS nữa vì ứng dụng web ngày càng trở nên phức tạp, và quan trọng hơn hết là lượng người dùng truy cập càng ngày càng đông, việc giảm tải cho server là cực kỳ cần thiết. Bởi vậy, người ta mới nghĩ ra cách, cái gì thuộc về client thì để cho client làm, ý tưởng về SPA ra đời, kèm theo một cụm từ là Client Side Rendering.
Tôi sẽ không so sánh giữa Server Side Rendering và Client Side Rendering vì nó có quá nhiều trên mạng. Và đó cũng là một cuộc chiến, giống như giữa PHP và NodeJS, giữa Angular - React - VueJS bây giờ vậy.

Cốt lõi của một SPA

Xin lỗi vì tôi đã nói quá dài =))
Như đã nói ở trên, dù là SPA hay không thì client và server cũng đều làm nhiệm vụ của nó, chỉ là với SPA hay Client Side Rendering, client làm nhiều việc hơn và sự tách biệt giữa client và server rõ ràng hơn bao giờ hết. Ngày trước, bạn hầu như chỉ có thể dùng JQuery và một số thư viện, plugin cho frontend, chứ không thể hoàn toàn tách biệt giữa backend và frontend khi làm việc với một framework, ví dụ Laravel. Nhưng với SPA, thì frontend và backend có thể tách biệt hoàn toàn và làm việc thông qua cái gọi là API. API là bản lề để nối giữa phần backend (xử lý data và logic) với frontend (xử lý giao diện, hiệu ứng). API là một trong những cái lõi của ứng dụng SPA, thường gặp là có RESTful API, và một cái tên mới nổi là GraphQL (lại một cuộc chiến khác, nhưng tôi nghĩ phần thắng chắc chắn sẽ thuộc về GraphQL).
Như vậy về phía server, những thứ cần có là:

  • Database.
  • Một hạ tầng thao tác với database, tiêu biểu là ORM, hiểu nôm na là một công cụ giúp lập trình viên không phải trực tiếp thao tác với database, ví dụ viết SQL.
  • Một tập hợp những controller (xử lý logic) để lấy dữ liệu từ database (có thể thông qua ORM hoặc không) để trả về dạng API, thường là JSON.
  • Dĩ nhiên không thể thiếu là hệ thống lắng nghe request, gửi trả response.

Về phía client, cần phải có:

  • Một bộ phận gửi request và nhận response qua API. Điển hình là $.ajax() trong JQuery, $http trong Angular...
  • Routing. Đây là sự khác biệt lớn nhất giữa SPA và multipage app khi SPA sử dụng routing ở client.
  • Model: hãy hiểu đơn giản như khái niệm model mà bạn biết trong mô hình MVC.
  • View: không cần phải nói thêm, là cái bạn nhìn thấy, là mã HTML, CSS...
  • Controller/ViewModel tùy vào framework: ví dụ như Angular dùng Controller, VueJS hay React dùng ViewModel, thực chất là khối xử lý logic.
  • Cơ chế render giữa Model - View - Controller / ViewModel, có thể kể tới One-way binding và Two-way binding.

Hãy nghĩ lại về câu hỏi của tôi khi muốn viết một trang web như gmail mà dùng JQuery thì cần dùng bao nhiêu lần gọi ajax?
Nếu bạn đã có câu trả lời thì thật mừng vì hồi trước tôi còn không hiểu cơ :D câu hỏi đó quả là khập khiễng vì bản thân JQuery không phải sinh ra để làm việc đó, nó chỉ support một phần rất nhỏ trong những thứ ở trên thôi, cụ thể là một hàm gọi ajax thuận tiện hơn, và vài hàm xử lý DOM. JQuery không có khái niệm Controller hay Model hay View, vì tư duy của JQuery là làm việc với DOM, là thao tác bằng tay, chuyển đoạn HTML này qua chỗ kia, sửa text, thay đổi CSS, chỉ vậy thôi.
Tiếp theo, nếu dùng JQuery gọi ajax, mục đích của bạn là gì? Để khỏi load lại trang, thì SPA đáp ứng được nhu cầu đó vì nó có cái gọi là cơ chế hoạt động giữa Model - View - Controller/ViewModel, nghĩa là khi View thay đổi (ví dụ người dùng click một button), kéo theo model thay đổi (vì Model và View luôn liên kết chặt chẽ với nhau) thì bản thân framework sẽ kiểm tra cho mình sự thay đổi đó và xử lý logic trong Controller/ViewModel và phản ứng lại sự thay đổi đó ngược lại vào view. Cái bạn cần làm là gì? Là báo cho framework biết, khi nào View thay đổi, View đang gắn với Model nào, và khi View thay đổi, Controller/ViewModel cần phải làm gì chứ không phải tự mình đi làm việc đó. Không giống JQuery, bạn sẽ phải xử lý sự kiện click, tự mình gán lại một biến nào đó trong javascript, rồi tự mình thay đổi DOM bằng những hàm JQuery cung cấp, thì trong một SPA framework, bạn chỉ cần chỉ cho nó bạn muốn làm gì.
Angular và React có cơ chế binding khác nhau nhưng dù có one-way, two-way, three-way gì đi chăng nữa, cái nó muốn làm cũng chỉ là phản ứng lại sự thay đổi của view và render lại trên trình duyệt.
Tôi muốn nói thêm một chút về Routing. Hầu hết các ứng dụng đều có một layout chung, và khi tới một URL nào khác, chỉ có một số phần thay đổi, còn một số giữ nguyên. Bởi vậy người ta mới nảy ra ý tưởng là chỉ load những cái nào thay đổi thôi, rất đơn giản. Nếu như Server Side Rendering sử dụng ý tưởng include những phần layout vào chỗ thay đổi tương ứng, Client Side Render cũng tương tự, mỗi route sẽ load dữ liệu cần thiết cho sự thay đổi đó. Và khi làm việc với dữ liệu như vậy, bạn sẽ thấy việc tách biệt giữa xử lý logic và xử lý giao diện nó giúp người lập trình thoải mái như thế nào, và dễ dàng mở rộng cũng như sửa chữa hơn.

Tóm lại

Có một ai đó đã từng nói, nếu như bạn không thể trình bày cho một đứa bé tám tuổi hiểu về một điều, có nghĩa là bạn chưa thực sự hiểu về nó. Tôi thì luôn tin vào câu nói đó, và có lẽ đó là lý do khiến tôi viết luôn dài dòng và lê thê =)) nhưng hơn hết, những bài viết của tôi không bao giờ chỉ là đơn thuần dịch lại một bài viết của ai đó hay dịch lại document gốc, mục đích của tôi là muốn chứng mình rằng mình hiểu những gì mình đang nói.
Một lần nữa, hi vọng các bạn sẽ chọn được những gì bổ ích cho mình qua bài viết này, và hi vọng cộng đồng developer Việt Nam sẽ ngày càng lớn mạnh, và sẵn sàng chia sẻ, học hỏi cùng nhau :)

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

ShinaBR2

10 bài viết.
93 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
57 16
Đây là một vấn đề kinh điển, và có rất nhiều bài viết về nó, tuy nhiên đa phần là dịch từ bản gốc ra và sao chép lại một vài câu lệnh, và câu hỏi t...
ShinaBR2 viết 1 năm trước
57 16
White
39 10
Vào một ngày đẹp trời, khi bạn nhận được yêu cầu phải thiết kế database cho một hệ thống, câu hỏi đầu tiên được đặt ra, quy trình làm ra nó sẽ cụ t...
ShinaBR2 viết 1 năm trước
39 10
White
32 10
Bàn về code thối Hãy tự đặt câu hỏi cho bạn, khi bắt đầu lập trình, bạn nghĩ tới điều gì? Đi phỏng vấn Điều đầu tiên tôi muốn nói về những câu hỏ...
ShinaBR2 viết 8 tháng trước
32 10
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
10 bài viết.
93 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!