
Web Development Essentials 032.3: Tham chiếu HTML và Tài nguyên Nhúng
Hiểu href, src, neo trang, target, alt và định dạng ảnh; thực hành URL tương đối, iframe có tên và tab mới trên dữ liệu DEMO, ghi rõ giới hạn kiểm chứng.

Phân biệt trình duyệt, web server, API và database; hiểu REST, GraphQL, SPA, PWA và WebAssembly; thực hành tách phản hồi HTML, JSON cùng lỗi HTTP cục bộ.
Một nhân viên mở cổng hỗ trợ, thấy logo và menu nhưng danh sách yêu cầu trống. Người khác đề nghị cài lại trình duyệt. Trước khi làm vậy, Help Desk cần biết trang đã tải được phần nào: tài liệu HTML, mã giao diện hay phản hồi dữ liệu? Ba phần có thể được phục vụ theo đường khác nhau và thất bại độc lập.
Bài học thuộc 031.2, dựa trên khung PDF 030-100-vi, trang in 17–31, tương ứng trang vật lý 25–39. Nội dung được viết mới với một cổng hỗ trợ giả lập. Sau bài, bạn nên vẽ được các thành phần, giải thích nơi chạy mã và chọn bằng chứng giúp khoanh vùng lỗi. Bạn cần biết khái niệm mã nguồn và cách chạy tệp JavaScript từ bài trước.
Kiến thức được đối chiếu ngày 23/10/2026. Lab dùng Node.js 24.22.0, không có tài khoản, database thật hoặc dữ liệu công việc. Sơ đồ mô tả vai trò, không bắt buộc mỗi vai trò phải nằm trên một máy riêng.
Client chủ động gửi yêu cầu; server nhận và xử lý theo giao thức cùng quy tắc ứng dụng. Trình duyệt có thể làm client, nhưng công cụ dòng lệnh hoặc ứng dụng di động cũng có thể gửi HTTP. Server có thể chỉ máy, tiến trình hoặc phần mềm tùy câu nói, nên khi điều tra cần chỉ rõ bạn đang nói về thành phần nào.
MDN mô tả chu trình client và server. Trong ví dụ tự biên soạn này, trình duyệt lấy trang trước rồi yêu cầu danh sách DEMO. Server tạo phản hồi từ dữ liệu có sẵn. Việc lấy trang thành công chỉ xác nhận một phần luồng; chưa chứng minh API hay nơi lưu trữ đang hoạt động đúng.
Hai vai trò có thể chạy trên cùng máy khi học. Mã phía server vẫn không biến thành mã trong trình duyệt chỉ vì cùng viết bằng JavaScript. Một tiến trình cũng có thể là server với trình duyệt và là client khi gọi dịch vụ khác.
HTML mô tả cấu trúc cùng ý nghĩa nội dung. CSS điều khiển cách trình bày. JavaScript bổ sung logic và tương tác thông qua các API được môi trường cung cấp. Một trang hướng dẫn có liên kết và biểu mẫu vẫn có thể hữu ích khi chưa thêm JavaScript riêng; không phải mọi website đều cần ứng dụng giao diện phức tạp.
Chrome, Edge, Firefox và Safari là những trình duyệt cần nhận diện trong bối cảnh học web. Internet Explorer xuất hiện trong danh sách giáo trình cũ, không phải môi trường lab của chuỗi này. Khả năng tương thích phải xét tính năng, phiên bản và thiết bị cụ thể; cùng mở được trang chưa đồng nghĩa mọi hành vi giống nhau.
Trình duyệt có các ranh giới quyền và nguồn. Trang không tự có toàn quyền đọc tệp hay thiết bị. API nhạy cảm có điều kiện riêng về quyền, môi trường bảo mật và chính sách. Không nên khái quát rằng mọi truy cập tài nguyên cục bộ đều hiện cùng một hộp hỏi quyền.
Web server có thể phục vụ các tài nguyên tĩnh hoặc chuyển yêu cầu sang ứng dụng. Ứng dụng đọc đường dẫn, phương thức và dữ liệu, áp dụng quy tắc rồi tạo phản hồi. Apache HTTP Server, NGINX và runtime ứng dụng có thể tham gia theo những cách triển khai khác nhau; bài này chưa cấu hình chúng.
Với cổng hỗ trợ, tệp CSS có thể được trả trực tiếp, còn /api/tickets gọi phần xử lý để lấy danh sách. Một URL không bắt buộc tương ứng với tệp cùng tên trên ổ đĩa. Route là quy tắc xử lý của ứng dụng, khác đường dẫn filesystem.
Nếu giao diện lỗi, Help Desk nên ghi URL yêu cầu, thời điểm, mã trạng thái và phạm vi ảnh hưởng. Trước khi khởi động lại dịch vụ, xác nhận dịch vụ nào chịu trách nhiệm và quyền được phép thao tác. Restart làm mất trạng thái hoặc ngắt kết nối đang dùng tùy ứng dụng; không chọn bước đó chỉ vì thấy chữ “server”.

API mô tả cách một thành phần sử dụng chức năng hoặc dữ liệu của thành phần khác. Trong HTTP API, thỏa thuận có thể gồm đường dẫn, phương thức, dữ liệu gửi, phản hồi, xác thực và lỗi. JSON là một định dạng dữ liệu thường dùng, không phải tên của kiến trúc hoặc bằng chứng API an toàn.
REST là tập ràng buộc thiết kế kiến trúc. Có endpoint HTTP trả JSON chưa đủ để kết luận ứng dụng tuân thủ đầy đủ REST. Ở mức nhập môn, bạn cần hiểu tài nguyên và ý nghĩa thao tác, thay vì chỉ ghi nhớ một sơ đồ tên phương thức.
GraphQL cung cấp ngôn ngữ truy vấn và cơ chế thực thi theo schema. Client có thể chỉ định những trường cần lấy; server vẫn quyết định quyền và cách xử lý. Nó không tự thay thế database hay bảo đảm truy vấn rẻ. Chọn REST hoặc GraphQL cần nhu cầu cụ thể, không phải cứ ứng dụng phức tạp là phải chuyển sang GraphQL.
Một lỗi trả dữ liệu cần được phân biệt với mất kết nối. Client nhận phản hồi HTTP lỗi khác với chưa nhận được phản hồi nào. Việc thông báo cho người dùng cũng nên phản ánh khác biệt đó, tránh hiển thị “không có yêu cầu” khi thật ra API thất bại.
Database quan hệ tổ chức dữ liệu bằng bảng và quan hệ cùng các quy tắc áp dụng. SQLite, MySQL, MariaDB và PostgreSQL là những tên trong mục tiêu. Cùng hỗ trợ SQL không có nghĩa cú pháp, kiểu dữ liệu hoặc cách vận hành hoàn toàn giống nhau.
SQLite không cần một tiến trình database server trung gian. Ứng dụng có thể dùng thư viện để làm việc với file database. Vì vậy, hình vẽ có “database” nên được hiểu là một vai trò lưu trữ; đừng tự suy ra luôn có kết nối TCP hoặc một máy database riêng.
NoSQL bao gồm các cách tổ chức khác mô hình quan hệ truyền thống. MongoDB và CouchDB thường gắn với tài liệu; Redis có các cấu trúc dữ liệu phục vụ những nhu cầu riêng. Không gọi mọi NoSQL là cùng một loại kho tài liệu hoặc mặc định dễ vận hành hơn SQL.
Tài liệu mô hình dữ liệu MongoDB cho thấy schema linh hoạt vẫn cần thiết kế theo cách truy cập. MongoDB cũng có schema validation. “Linh hoạt” không có nghĩa không còn hợp đồng dữ liệu, không cần migration hay không thể sinh lỗi kiểu dữ liệu.
Ứng dụng một trang, hay SPA, có thể cập nhật vùng nội dung bằng JavaScript thay vì tải lại toàn bộ tài liệu cho mỗi tương tác. Nó vẫn cần xử lý điều hướng, trạng thái chờ và lỗi. Trang trống sau khi tải có thể liên quan mã client hoặc yêu cầu tiếp theo; chưa thể kết luận do database.
PWA sử dụng công nghệ web với những khả năng như cài đặt hoặc hỗ trợ hoạt động ngoại tuyến tùy thiết kế và nền tảng. Có manifest hay biểu tượng không tự chứng minh mọi chức năng làm việc khi mất mạng. Cần xác định tài nguyên được cache và dữ liệu nào phải hỏi server.
Ứng dụng cũng có thể được đóng gói với một webview hoặc runtime desktop. Hình thức đóng gói ảnh hưởng phân phối, cập nhật và quyền truy cập; không nên suy từ giao diện giống website rằng mọi gói có cùng ranh giới với tab trình duyệt. Chuỗi chỉ giới thiệu khái niệm này, chưa tạo gói cài đặt.
WebAssembly là định dạng bytecode và đích biên dịch cho nhiều ngôn ngữ, không phải một loại JavaScript. Nó có thể phối hợp với JavaScript cho các phần việc phù hợp. Không bảo đảm mọi chương trình dùng Wasm sẽ nhanh hơn; cần đo đúng workload và tính cả chi phí tích hợp.
Hệ thống quản lý nội dung giúp biên tập bài, media và quy trình xuất bản. Màn hình quản trị và trang cho người đọc có thể tách riêng, nhưng quyền phải được thực thi ở phía server. Ẩn nút “xuất bản” trong giao diện chưa ngăn một yêu cầu trực tiếp không được phép.
Với portal giả lập, hãy vẽ riêng người đọc và người biên tập, nội dung đã duyệt và dữ liệu chưa công bố. Một bản draft có thể chịu chính sách truy cập riêng; tên trạng thái không tự bảo đảm nó được giữ kín. Cần kiểm tra hành vi thực tế trước khi đưa nội dung nhạy cảm vào hệ thống.

Tạo architecture.mjs trong thư mục lab trống. Mã tự mở HTTP server trên loopback ở cổng tạm, dùng Node.js làm client rồi đóng server. Nó không mở dịch vụ ra LAN và không cần cài dependency:
import http from 'node:http';
import assert from 'node:assert/strict';
const seen = [];
const server = http.createServer((req, res) => {
seen.push([req.method, req.url]);
if (req.method !== 'GET') {
res.writeHead(405, {'Allow':'GET'});
return res.end('method not allowed');
}
if (req.url === '/') {
res.writeHead(200, {'Content-Type':'text/html; charset=utf-8'});
return res.end('<!doctype html><title>DEMO</title><h1>Help portal</h1>');
}
if (req.url === '/api/tickets') {
res.writeHead(200, {'Content-Type':'application/json'});
return res.end(JSON.stringify({open:2}));
}
res.writeHead(404);
res.end('not found');
});
await new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
const base = `http://127.0.0.1:${server.address().port}`;
try {
const page = await fetch(base + '/');
assert.equal(page.status, 200);
assert.match(await page.text(), /Help portal/);
const api = await fetch(base + '/api/tickets');
assert.equal(api.status, 200);
assert.match(api.headers.get('content-type'), /application\/json/);
assert.deepEqual(await api.json(), {open:2});
const missing = await fetch(base + '/missing');
assert.equal(missing.status, 404);
await missing.text();
const rejected = await fetch(base + '/api/tickets', {method:'POST'});
assert.equal(rejected.status, 405);
await rejected.text();
assert.equal(seen.length, 4);
console.log('PASS: HTML, JSON, 404, 405; requests:', seen.length);
} finally {
await new Promise(resolve => server.close(resolve));
}
Chạy node architecture.mjs. API HTTP của Node.js là nguồn đối chiếu cho server. Kết quả mong đợi là dòng PASS với bốn yêu cầu. Kiểm chứng trên Node.js 24.22.0 trong container Alpine, user node, tắt mạng ngoài và chỉ dùng loopback nội bộ, đã đạt các điều kiện trong mã.
JSON trong lab là dữ liệu cố định trong bộ nhớ chương trình, không phải truy vấn database. Phép thử xác nhận xử lý route và phương thức đã chọn; chưa thử render trình duyệt, REST đầy đủ, GraphQL, xác thực, tải đồng thời, PWA hay Wasm. Nếu lỗi cổng hoặc kết nối, giữ thông báo và kiểm tra tiến trình thay vì mở firewall máy thật.
Vẽ lại tình huống đầu bài với hai yêu cầu riêng: lấy trang và lấy dữ liệu. Đánh dấu nơi có HTML, nơi có JSON và nơi database sẽ tham gia nếu ứng dụng có lưu trữ. Nêu một bằng chứng giúp phân biệt lỗi tải trang với lỗi API, cùng một phần lab chưa chứng minh.
Bạn đạt mục tiêu khi giải thích được một vai trò có thể nằm chung tiến trình với vai trò khác, phân biệt route với file và không dùng một phản hồi 200 để kết luận toàn bộ ứng dụng khỏe. Giữ sơ đồ và output để sang bài HTTP, nơi ta sẽ xem kỹ hơn phương thức, header, cache và trạng thái.

Hiểu href, src, neo trang, target, alt và định dạng ảnh; thực hành URL tương đối, iframe có tên và tab mới trên dữ liệu DEMO, ghi rõ giới hạn kiểm chứng.

Chọn heading, danh sách và vùng nội dung theo ý nghĩa; hiểu strong, em, code, div, span; thực hành DOM, vai trò và liên kết chuyển focus bằng bàn phím.

Tạo tài liệu HTML tiếng Việt; hiểu doctype, head, body, title, metadata và UTF-8; thử ba biến thể trong trình duyệt để nhận diện lỗi cấu trúc, thuộc tính.

Đọc URL, phương thức, header và trạng thái HTTP; phân biệt cookie, phiên, HTTPS và HTTP/3; thực hành ETag với chuỗi 200, 304, 200 trên tệp DEMO cục bộ.