0

Đừng trả về cục HTML qua AJAX nữa! Đã đến lúc Backend của bạn cần được "giải thoát".

Chào anh em thiện lành! Dạo này lướt Viblo thấy anh em bàn nhiều về Microservices, Kafka, K8s... nghe đao to búa lớn quá. Hôm nay, mình xin phép rủ anh em "quay xe" về một khái niệm nền tảng nhưng đã định hình lại toàn bộ kiến trúc Web hiện đại: AJAX JSON Pattern.

Nếu bạn thuộc thế hệ Gen Z lớn lên cùng React, Vue hay Next.js, có lẽ bạn sẽ thấy pattern này là "chuyện hiển nhiên". Nhưng với những anh em đi lên từ thời đồ đá của jQuery và PHP/ASP.NET, thì đây là cả một cuộc cách mạng đẫm máu và nước mắt. Hãy để mình kể cho anh em nghe về một cú sốc đầu đời của mình.

1. Mở bài: Cú sốc "Làm thêm cái App Mobile nha em!"

Đó là năm thứ 2 mình đi code dạo, dự án là một trang web rao vặt. Hồi đó kỹ năng "trấn phái" của mình là jQuery AJAX. Mỗi khi người dùng bấm lọc sản phẩm, mình sẽ gửi request xuống Backend. Backend (hồi đó mình dùng PHP) sẽ chọc vào Database, loop qua mớ data, "nhét" nó vào một cục HTML siêu to khổng lồ, và trả về cho Frontend.

Frontend lúc đó nhàn lắm, chỉ việc nhận cục HTML và nhét vào DOM:

// Ngày xưa code thế này là xịn lắm rồi...
$.ajax({
    url: '/filter-products',
    type: 'GET',
    data: { category: 'laptop' },
    success: function(htmlResponse) {
        // Nhận nguyên 1 nùi <div>...</div> từ server và đắp lên UI
        $('#product-list').html(htmlResponse); 
    }
});

Dự án chạy bon bon, sếp vỗ vai khen ngợi. Cho đến một ngày đẹp trời, sếp gọi mình vào phòng họp và chốt một câu xanh rờn: "Web chạy ngon rồi, tháng sau công ty mình thuê team Outsource làm thêm cái App Mobile (iOS/Android). Em lấy cái Backend hiện tại cấp API cho bên đó xài nhé!".

Mình như sét đánh ngang tai. Backend của mình đang trả về... HTML (<div>, <span>, <img>)! Ứng dụng Mobile (viết bằng Swift/Java) thì làm quái gì biết đọc và render cái đống thẻ HTML đó? Chúng nó cần Dữ liệu thô (Data).

Thế là, thay vì tái sử dụng được Backend, mình phải hì hục cày ngày cày đêm để viết ra một bộ API thứ 2 chạy song song chỉ để phục vụ cho Mobile. Code duplicate khắp nơi, sửa logic một chỗ là phải nhớ sửa chỗ kia. Một cơn ác mộng bảo trì thực sự!

2. Hành trình giác ngộ: AJAX JSON Pattern là gì?

Sự cố đó dạy cho mình một bài học cốt lõi: Sự dính chặt (Tight Coupling) giữa Dữ liệu và Giao diện. Backend của mình đã ôm đồm quá nhiều việc, nó không chỉ lấy data mà còn quyết định luôn việc data đó sẽ hiển thị như thế nào (màu gì, nằm ở thẻ nào).

Và đó là lúc mình đập đi xây lại theo AJAX JSON Pattern (tiền đề của kiến trúc Client-Server / RESTful API ngày nay).

Khái niệm này cực kỳ đơn giản:

  • Backend chỉ nói chuyện bằng DỮ LIỆU (JSON), tuyệt đối không đụng chạm đến HTML/UI. Nó trở thành một API thuần túy.
  • Frontend chịu trách nhiệm GIAO DIỆN. Khi cần data, Frontend gửi AJAX call. Backend trả về cục JSON nhẹ tênh. Frontend sẽ tự parse cục JSON đó và quyết định vẽ lên màn hình như thế nào.

Mình đã cấu trúc lại như sau:

Phía Backend (Chỉ trả về JSON thô):

// Backend bây giờ "trong sáng" và "vô lo"
public function filterProducts(Request $request) 
{
    $products = Product::where('category', $request->category)->get();
    
    // Trả về dữ liệu chuẩn JSON
    return response()->json([
        'status' => 'success',
        'data' => $products
    ]);
}

Phía Frontend (Lấy data và tự Render):

// Dùng Fetch API hiện đại
fetch('/api/products?category=laptop')
  .then(res => res.json())
  .then(response => {
      const products = response.data;
      
      // Frontend tự quyết định việc vẽ UI
      const htmlString = products.map(p => `
          <div class="product-card">
              <h3>${p.name}</h3>
              <p>Giá: ${p.price} VNĐ</p>
          </div>
      `).join('');
      
      document.getElementById('product-list').innerHTML = htmlString;
  });

Phép màu xuất hiện: Khi team Mobile nhảy vào, họ dùng ĐÚNG CÁI API /api/products đó. Họ nhận được JSON, và trên Mobile họ tự parse để vẽ ra giao diện Native (Swift/Kotlin). Sếp muốn làm thêm App cho Smart TV? Cứ vô tư đi, gọi API lấy JSON về tự vẽ!

3. Bài học xương máu rút ra (The Takeaways)

  1. Decoupling (Tách biệt UI và Data): Backend giờ đây trở thành một "kho dữ liệu" độc lập, ngu ngơ về UI. Frontend/Mobile trở thành những "khách hàng" tiêu thụ dữ liệu.
  2. Reusability (Tái sử dụng 100%): Viết logic Backend một lần, phục vụ cho Web, iOS, Android, Apple Watch, và cả việc cấp API cho bên thứ 3 (3rd party).
  3. Tiết kiệm Băng thông: Chuyển một file JSON chứa [{"id": 1, "name": "Laptop"}] nhẹ hơn gấp chục lần so với việc phải truyền tải nguyên một khối HTML đầy rẫy class Tailwind hay Bootstrap.

Lời kết

AJAX JSON Pattern đã mở ra một kỷ nguyên mới, làm bệ phóng cho sự bùng nổ của các SPA Framework (Single Page Application) như React, Vue, Angular ngày nay. Chúng ta không còn gửi HTML qua mạng lưới (network) nữa, chúng ta chỉ gửi Data.

Nhưng cuộc đời coder lạ lắm anh em ạ. Lịch sử công nghệ luôn có tính chu kỳ! Sau hơn một thập kỷ đắm chìm trong JSON và SPA, dạo gần đây thế giới lại đang phát cuồng vì những cái tên như HTMX hay Laravel Livewire – những công nghệ... đem việc trả về HTML qua AJAX quay trở lại, nhằm giảm bớt sự phức tạp của Javascript ở Frontend.

Đúng là giang hồ hiểm ác, framework quay xe không biết đường nào mà lần! 😅

Anh em ở đây thuộc phe nào? Trung thành với kiến trúc Backend API (JSON) + Frontend (React/Vue) kinh điển, hay đang nhăm nhe "quay về tuổi thơ" với HTMX / Livewire? Cùng comment chém gió phía dưới nhé!


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí