Buổi 15: Triển khai Website và tổng kết khóa
Bạn đã có trong tay một trang web chạy đẹp trên máy tính của mình: HTML ngữ nghĩa, CSS đáp ứng, JavaScript tương tác, mã nguồn quản lý bằng Git. Nhưng trang web đó mới chỉ "sống" ở địa chỉ localhost hoặc trong thư mục trên laptop — bạn bè, khách hàng, giảng viên chưa thể mở được. Buổi cuối cùng của khóa học trả lời câu hỏi: làm thế nào để đưa Website lên Internet (có tên gọi dễ nhớ, có nơi lưu trữ, có khóa HTTPS), làm sao biết nó chạy đúng, làm sao để Google tìm thấy nó và làm sao giữ cho nó chạy tốt về lâu dài. Sau đó, chúng ta nhìn lại toàn bộ hành trình 15 buổi và vạch ra dự án cuối kỳ cùng lộ trình học tiếp.
Mục tiêu buổi học
- Sau buổi này bạn có thể giải thích tên miền (domain), quy tắc đặt nhãn, tên miền cấp cao nhất (TLD) và vai trò của hệ thống tên miền DNS cùng các loại bản ghi A, AAAA, CNAME, MX, TXT, NS.
- Sau buổi này bạn có thể phân biệt các loại Web host (Shared, VPS, Cloud, Dedicated, Static hosting...) và chọn nơi lưu trữ phù hợp với Website của mình.
- Sau buổi này bạn có thể đưa mã nguồn lên Web host bằng FTP/SFTP hoặc nền tảng triển khai từ Git, và bật HTTPS bằng chứng chỉ SSL/TLS (Let's Encrypt), chuyển hướng HTTP sang HTTPS.
- Sau buổi này bạn có thể kiểm thử Website sau khi tải lên, khai báo với Google Search Console, viết
robots.txt,sitemap.xml, thẻmeta robots, và biết cách chuyển hướng trang đã xóa. - Sau buổi này bạn có thể áp dụng các biện pháp tối ưu tốc độ tải trang (ảnh, nén, cache, minify, CDN) và dùng các công cụ phân tích để bảo trì Website.
- Sau buổi này bạn có thể hệ thống hóa kiến thức cả khóa, lập kế hoạch dự án cuối kỳ và định hướng học tiếp.
Bản đồ buổi học
| Phần | Nội dung | Thời lượng gợi ý |
|---|---|---|
| 1. Đăng ký tên miền | Khái niệm tên miền, DNS và bản ghi, nơi mua tên miền | 30 phút |
| 2. Lưu trữ Website trên không gian mạng | Các loại Web host, chọn nơi mua, FTP, SSL/HTTPS | 35 phút |
| 3. Kiểm thử, tối ưu hóa và bảo trì | Kiểm thử sau triển khai, khai báo công cụ tìm kiếm, robots.txt, sitemap.xml, tốc độ, bảo trì | 45 phút |
| Thực hành theo giáo trình | Bài 8.1, 8.2, 8.3 và bài tự thực hành 8.4 (Vercel) | 25 phút |
| Câu hỏi ôn tập & tổng kết khóa | 10 câu ôn tập chương 8, bản đồ 15 buổi, dự án cuối kỳ, lộ trình học tiếp | 30 phút |
| Bài tập trên Codelab | Năm nhóm bài về tên miền, DNS, chuyển hướng, robots.txt, tối ưu | 15 phút |
Khoảng một nửa thời gian của buổi là thực hành: bạn chạy thử các ví dụ ngay trong bài và làm nhóm bài tập tương ứng trên Codelab sau mỗi phần.
1. Đăng ký tên miền
Giáo trình: Chương 8 — mục "Đăng ký tên miền" (Khái niệm về tên miền; Hệ thống tên miền DNS; Lựa chọn nơi mua tên miền).
1.1. Khái niệm về tên miền
Tên miền (domain) là địa chỉ của một Website hoạt động trên môi trường mạng Internet. Mục đích của tên miền là cung cấp một hình thức đại diện: dùng tên gọi dễ nhận biết thay cho địa chỉ của máy chủ lưu trữ Website (địa chỉ IP). Thay vì phải nhớ dãy số, người dùng chỉ cần nhớ một địa chỉ "dạng chữ cái" không trùng nhau, nhờ đó dễ dàng tìm kiếm và truy cập Website.
Hệ thống tên miền rất uyển chuyển: nhiều địa chỉ IP có thể được gán vào một tên miền, hoặc nhiều tên miền cùng trỏ đến một địa chỉ IP. Nói cách khác, một máy chủ gắn với một địa chỉ IP có thể lưu trữ nhiều Website khác nhau, cho nhiều tên miền khác nhau.
- Ví dụ 1: người dùng có thể gõ tên miền
neu.edu.vnthay vì địa chỉ IP125.212.138.22. - Ví dụ 2: máy chủ tại địa chỉ IP
113.161.108.140vận hành đồng thời các Websitekilo.vn,cokhikhaviet.com.vn,drgauges.netvàpretem.com.
Trước bước ① trình duyệt và hệ điều hành đã tra bộ nhớ đệm; nếu đã có IP thì bỏ qua cả chuỗi hỏi đáp.
Trong lúc này một số người vẫn vào địa chỉ cũ: bình thường, không phải lỗi cấu hình.
Người dùng gõ tên dễ nhớ; hệ thống DNS (danh bạ phân tán toàn cầu) dịch tên miền thành địa chỉ IP của máy chủ rồi trình duyệt mới kết nối được.
Sơ đồ trên cho thấy hành trình từ tên miền đến máy chủ: bạn gõ tên miền vào trình duyệt, hệ thống DNS tra ra địa chỉ IP, rồi trình duyệt mới gửi yêu cầu HTTP tới máy chủ đó. Hãy đọc từ trái sang phải và để ý rằng tên miền chỉ là "tên", còn IP mới là "số nhà" thực sự.
Quy tắc đặt tên miền
Tên miền được tạo thành từ các nhãn (label) khác rỗng phân cách nhau bằng dấu chấm (.). Mỗi nhãn và cả tên miền phải tuân theo các quy tắc sau:
| Quy tắc | Chi tiết |
|---|---|
| Ký tự cho phép | Chữ cái a–z (không phân biệt hoa/thường), chữ số 0–9 và dấu gạch ngang - |
| Dấu gạch ngang | Không được xuất hiện ở đầu hoặc cuối của nhãn |
| Độ dài mỗi nhãn | Không vượt quá 63 ký tự |
| Tổng độ dài tên miền | Không vượt quá 253 ký tự (tương ứng 255 octet ở dạng mã hóa) |
Hãy viết thử một hàm kiểm tra các quy tắc này. Mỗi tên miền được tách thành nhãn bằng split("."), sau đó từng nhãn được kiểm tra ký tự, độ dài và vị trí dấu gạch ngang:
function kiemTraTenMien(ten) {
const loi = [];
if (ten.length > 253) loi.push("dài quá 253 ký tự");
for (const nhan of ten.split(".")) {
if (nhan === "") { loi.push("có nhãn rỗng"); continue; }
if (nhan.length > 63) loi.push("có nhãn dài quá 63 ký tự");
if (!/^[a-z0-9-]+$/i.test(nhan)) loi.push(`nhãn "${nhan}" có ký tự không hợp lệ`);
if (nhan.startsWith("-") || nhan.endsWith("-")) loi.push(`nhãn "${nhan}" có dấu - ở đầu/cuối`);
}
return loi;
}
const thu = ["neu.edu.vn", "FIT.NEU.edu.vn", "-neu.vn", "neu_edu.vn", "neu..vn", "a".repeat(64) + ".com"];
for (const ten of thu) {
const loi = kiemTraTenMien(ten);
const hienThi = ten.length > 24 ? ten.slice(0, 24) + "…" : ten;
console.log(hienThi.padEnd(26), loi.length ? "SAI: " + loi.join("; ") : "hợp lệ");
}Kết quả cho thấy neu_edu.vn sai vì dấu gạch dưới _ không nằm trong tập ký tự cho phép, còn -neu.vn sai vì dấu gạch ngang đứng đầu nhãn.
Lưu ý: Quy tắc trên là quy tắc "kỹ thuật" của hệ thống tên miền. Nhà đăng ký còn có thêm quy định riêng (độ dài tối thiểu, tên cấm, tên đã có người đăng ký) nên một tên hợp lệ chưa chắc đã đăng ký được.
Tên miền cấp cao nhất (TLD)
Mọi tên miền đều kết thúc bằng một tên miền cấp cao nhất (TLD – Top Level Domain). TLD có hai dạng:
- TLD dùng chung như
.com,.net,.org... - Tên miền quốc gia cấp cao nhất (country code TLD) như
.vn,.uk,.us...
Việc tạo lập và ủy quyền tên miền cấp cao nhất do ICANN (Internet Corporation for Assigned Names and Numbers) quản lý, thông qua chức năng IANA (Internet Assigned Numbers Authority). Riêng tên miền quốc gia .vn do Trung tâm Internet Việt Nam (VNNIC) trực thuộc Bộ Thông tin và Truyền thông quản lý.
Từ phải sang trái, các nhãn đi từ phạm vi rộng đến hẹp. Ví dụ fit.neu.edu.vn: vn là TLD, edu.vn là tên miền cấp dưới của .vn, neu.edu.vn là tên miền của trường, còn fit là tên miền phụ (subdomain) do chủ tên miền tự tạo ra để chỉ một khu vực cụ thể của Website.
function tachTenMien(host, soNhanHauTo = 1) {
const nhan = host.toLowerCase().split(".");
return {
tld: nhan.at(-1),
hauTo: nhan.slice(-soNhanHauTo).join("."),
tenMienChinh: nhan.slice(-(soNhanHauTo + 1)).join("."),
mienPhu: nhan.slice(0, -(soNhanHauTo + 1)).join(".") || "(không có)",
};
}
console.log(JSON.stringify(tachTenMien("www.example.com")));
console.log(JSON.stringify(tachTenMien("fit.neu.edu.vn", 2)));
console.log(JSON.stringify(tachTenMien("neu.edu.vn", 2)));Mở rộng: Vì
edu.vn,com.vn... là các tên miền cấp hai nằm dưới.vnnên khi tách "tên miền chính" phải biết hậu tố gồm mấy nhãn (tham sốsoNhanHauToở trên). Các trình duyệt dùng một danh sách công khai gọi là Public Suffix List để làm việc này.
Vừa học xong quy tắc đặt tên miền, TLD và tên miền phụ, hãy làm nhóm bài sau để tự viết bộ kiểm tra và tách tên miền:
1.2. Hệ thống tên miền DNS
Tên miền chỉ là tên gọi dễ nhớ; để mở được Website, trình duyệt vẫn phải biết địa chỉ IP của máy chủ. Việc chuyển từ tên miền sang địa chỉ IP do hệ thống tên miền DNS (Domain Name System) đảm nhiệm, hoạt động như một cuốn danh bạ phân tán trên toàn cầu.
Sau khi mua tên miền và thuê Web host, người quản trị phải khai báo các bản ghi DNS (DNS record) để trỏ tên miền về máy chủ. Các loại bản ghi thường dùng:
| Bản ghi | Công dụng | Ví dụ giá trị |
|---|---|---|
| A | Trỏ tên miền tới một địa chỉ IPv4 cụ thể | 203.0.113.10 |
| AAAA | Trỏ tên miền tới một địa chỉ IPv6 | 2001:db8::10 |
| CNAME | Đặt một tên miền là bí danh của tên miền khác, thường dùng cho tên miền phụ | www → example.vn |
| MX | Chỉ định máy chủ nhận thư điện tử của tên miền | 10 mail.example.vn |
| TXT | Lưu một đoạn văn bản, dùng để xác minh quyền sở hữu tên miền hoặc khai báo SPF, DKIM | v=spf1 ... ~all |
| NS | Chỉ định máy chủ tên miền (nameserver) đang quản lý các bản ghi của tên miền đó | ns1.nhacungcap.vn |
Truy vấn DNS từ tên miền tới địa chỉ IP
nhập tên miền, chọn loại bản ghi, rồi theo dõi từng gói tinThử: truy vấn www.neu.edu.vn, rồi neu.edu.vn (bỏ qua root, TLD), rồi bấm "Hết TTL" để thấy lần sau hỏi thẳng máy chủ có thẩm quyền.
| Bản ghi | Công dụng |
|---|---|
| A | trỏ tới địa chỉ IPv4 |
| AAAA | trỏ tới địa chỉ IPv6 |
| CNAME | tên miền là bí danh của tên khác |
| MX | máy chủ nhận thư điện tử |
| TXT | văn bản (SPF, xác minh quyền sở hữu) |
| NS | máy chủ tên miền quản lý bản ghi |
Mô phỏng này cho bạn tự thực hiện một truy vấn DNS: gõ tên miền, quan sát từng bước hỏi đáp giữa trình duyệt, máy chủ DNS và nameserver cho đến khi nhận được địa chỉ IP. Hãy thử với tên miền có bản ghi CNAME để thấy chuỗi "bí danh → tên thật → IP".
Để hiểu rõ cách các bản ghi phối hợp, ta mô phỏng một "vùng DNS" nhỏ bằng một mảng đối tượng, rồi viết hàm tra cứu có đi theo chuỗi CNAME:
const vung = [
{ ten: "example.vn", loai: "A", giaTri: "203.0.113.10" },
{ ten: "www.example.vn", loai: "CNAME", giaTri: "example.vn" },
{ ten: "blog.example.vn", loai: "CNAME", giaTri: "cname.host-vi-du.net" },
{ ten: "cname.host-vi-du.net", loai: "A", giaTri: "198.51.100.7" },
{ ten: "example.vn", loai: "MX", giaTri: "10 mail.example.vn" },
{ ten: "mail.example.vn", loai: "A", giaTri: "203.0.113.25" },
];
function traCuuA(ten, buoc = []) {
if (buoc.length > 5) return { loi: "quá nhiều CNAME", buoc };
const cname = vung.find((b) => b.ten === ten && b.loai === "CNAME");
if (cname) return traCuuA(cname.giaTri, [...buoc, `${ten} là bí danh của ${cname.giaTri}`]);
const a = vung.find((b) => b.ten === ten && b.loai === "A");
return a ? { ip: a.giaTri, buoc } : { loi: "không có bản ghi A", buoc };
}
for (const ten of ["example.vn", "www.example.vn", "blog.example.vn", "shop.example.vn"]) {
const kq = traCuuA(ten);
console.log(ten, "=>", kq.ip ?? "LỖI: " + kq.loi, kq.buoc.length ? "| " + kq.buoc.join(" -> ") : "");
}Hãy để ý hai điểm: (1) shop.example.vn chưa có bản ghi nào nên tra cứu thất bại; (2) www và blog là tên miền phụ dùng CNAME, nên khi nhà cung cấp Web host đổi địa chỉ IP, bạn không phải sửa gì.
Bản ghi MX có thêm một số ưu tiên: số càng nhỏ càng được thử trước. Khi một máy chủ thư không nhận, thư sẽ được gửi sang máy chủ có số ưu tiên kế tiếp:
const mx = [
{ uuTien: 20, may: "mail-du-phong.example.vn" },
{ uuTien: 10, may: "mail.example.vn" },
{ uuTien: 30, may: "mail-cuoi.example.vn" },
];
mx.sort((a, b) => a.uuTien - b.uuTien);
mx.forEach((b, i) => console.log(`Thử lần ${i + 1}: ${b.may} (ưu tiên ${b.uuTien})`));Thời gian lan truyền bản ghi
Sau khi thay đổi bản ghi, thông tin mới cần thời gian lan truyền (propagation) tới các máy chủ DNS trên thế giới, thường từ vài phút đến 24–48 giờ. Trong khoảng thời gian này, một số người dùng vẫn truy cập vào địa chỉ cũ — đây là hiện tượng bình thường, không phải lỗi cấu hình. Nguyên nhân chính là mỗi bản ghi có một giá trị TTL (Time To Live), tính bằng giây: các máy chủ DNS trung gian được phép giữ bản ghi cũ trong bộ nhớ đệm cho đến khi hết TTL.
const batDau = Date.UTC(2026, 0, 15, 8, 0, 0); // 08:00 UTC ngày 15/01/2026
const ttl = 3600; // 1 giờ
const hetHan = new Date(batDau + ttl * 1000);
console.log("Máy chủ DNS lưu bản ghi cũ đến:", hetHan.toISOString());
for (const phut of [10, 59, 60, 61]) {
const conLai = ttl - phut * 60;
console.log(`Sau ${phut} phút:`, conLai > 0 ? `còn ${conLai} giây nên vẫn có thể thấy IP cũ` : "đã hết TTL, sẽ hỏi lại và thấy IP mới");
}Mẹo: Nếu sắp chuyển Website sang máy chủ mới, hãy giảm TTL xuống thấp (ví dụ 300 giây) vài ngày trước khi đổi bản ghi để việc chuyển đổi diễn ra nhanh và ít gián đoạn.
Ví dụ thực tế: Bạn mua tên miền
cuahangminh.vn, thuê Web host và nhận được địa chỉ IP203.0.113.10. Bạn vào trang quản lý DNS của nhà đăng ký, thêm bản ghi A chocuahangminh.vntrỏ về IP đó và bản ghi CNAME chowwwtrỏ vềcuahangminh.vn; thêm bản ghi MX nếu dùng email theo tên miền. Vài giờ sau, mọi người đều mở được Website bằng tên miền của bạn.
Công cụ minh họa của tác giả giáo trình về bản ghi DNS: DNS: từ tên miền đến máy chủ.
Vừa học xong các loại bản ghi DNS, hãy làm các bài sau để thống kê, đề xuất loại bản ghi và phát hiện xung đột CNAME:
1.3. Lựa chọn nơi mua tên miền
Tổ chức, cá nhân đăng ký tên miền được gọi là chủ thể đăng ký. Chủ thể có quyền sử dụng tên miền đó trong thời hạn đã đăng ký và phải gia hạn định kỳ; hết hạn mà không gia hạn thì tên miền bị thu hồi. Hiện có khá nhiều công ty cung cấp dịch vụ đăng ký tên miền. Ở Việt Nam, giáo trình nêu một số công ty uy tín:
| Công ty | Địa chỉ |
|---|---|
| Công ty P.A Việt Nam (máy chủ, hosting và dịch vụ CNTT) | https://www.pavietnam.vn |
| Công ty TNHH Phần mềm Nhân Hòa (Nhân Hòa) | https://nhanhoa.com |
| Công ty Cổ phần Giải pháp mạng Bạch Kim (BKNS) | https://www.bkns.vn |
| Công ty Cổ phần Mắt Bão (Mắt Bão) | https://www.matbao.com |
| Công ty TNHH Phần mềm iNET (iNET) | https://inet.vn |
Bên cạnh đó, cũng có thể chọn một số tổ chức cung cấp tên miền miễn phí như https://pages.github.com và https://www.hostinger.com.
Cảnh báo: Hãy đăng ký tên miền bằng thông tin chủ thể của chính bạn (hoặc tổ chức của bạn) và ghi nhớ ngày hết hạn. Quên gia hạn là nguyên nhân phổ biến khiến Website "biến mất" đột ngột và tên miền có thể bị người khác đăng ký mất.
Ví dụ tính số ngày còn lại để cảnh báo trước khi hết hạn (dùng ngày cố định để kết quả không đổi):
const homNay = Date.UTC(2026, 5, 1);
const danhSach = [
{ ten: "cuahangminh.vn", het: "2026-06-20" },
{ ten: "blog-cua-an.com", het: "2027-02-01" },
{ ten: "lop-web.edu.vn", het: "2026-05-30" },
];
for (const d of danhSach) {
const conLai = Math.round((Date.parse(d.het) - homNay) / 86400000);
const nhan = conLai < 0 ? "ĐÃ HẾT HẠN" : conLai <= 30 ? "SẮP HẾT HẠN, hãy gia hạn" : "còn lâu";
console.log(d.ten.padEnd(18), String(conLai).padStart(4), "ngày -", nhan);
}2. Lưu trữ Website trên không gian mạng
Giáo trình: Chương 8 — mục "Lưu trữ Website trên không gian mạng" (Dịch vụ lưu trữ Website (Web host); Lựa chọn nơi mua Web host; Chuyển Website lên Web host; Chứng chỉ SSL và giao thức HTTPS).
2.1. Dịch vụ lưu trữ Website (Web host)
Dịch vụ lưu trữ Website (Web host) là dịch vụ cung cấp không gian lưu trữ Website trên máy chủ. Nhà cung cấp tạo ra các "máy chủ Web" để khách hàng có chỗ vận hành Website. Các loại Web host thường được phân theo ba cách: theo mô hình chia sẻ tài nguyên (Shared, VPS, Cloud, Dedicated), theo hệ điều hành của máy chủ (Windows, Linux) hoặc theo loại dữ liệu được lưu trữ (Web tĩnh, thư điện tử, tệp tin).
| Loại | Đặc điểm theo giáo trình |
|---|---|
| Shared hosting (lưu trữ chia sẻ) | Nhiều Website trên cùng một máy chủ, mỗi Website có phân vùng riêng. Lựa chọn kinh tế vì chia sẻ chi phí thuê, quản lý, vận hành, bảo trì máy chủ |
| Windows hosting | Website vận hành trên máy chủ chạy Windows Server |
| Linux hosting | Website vận hành trên máy chủ chạy Linux |
| Free Web hosting | Miễn phí, thường có quảng cáo và một số hạn chế; cấp tên miền phụ, thư mục, hoặc cho dùng tên miền của khách hàng với vài điều kiện |
| Reseller hosting | Khách hàng được phân bổ lại tài nguyên (ổ cứng, băng thông...) cho tổ chức/cá nhân khác |
| VPS hosting | Thuê máy chủ riêng ảo (Virtual Private Server): một máy chủ vật lý chia thành nhiều máy chủ ảo, mỗi máy chạy độc lập và khởi động lại không ảnh hưởng máy khác |
| Email hosting | Lưu trữ và vận hành hộp thư điện tử theo tên miền riêng, tùy chỉnh cấu hình, số tài khoản, dung lượng |
| File hosting | Lưu trữ tệp tin trực tuyến; truy cập qua FTP hoặc công cụ chuyên biệt để tải lên, quản lý, chia sẻ |
| Cloud hosting (đám mây) | Tài nguyên cấp phát linh hoạt từ một cụm máy chủ, tăng giảm theo nhu cầu, thường tính tiền theo mức sử dụng. Ví dụ: Amazon Web Services, Google Cloud, Microsoft Azure, DigitalOcean, Viettel Cloud |
| Dedicated hosting (máy chủ riêng) | Thuê trọn một máy chủ vật lý, toàn quyền cấu hình, không chia sẻ tài nguyên. Chi phí cao nhất, hợp với hệ thống lớn |
| Static hosting (trang tĩnh) | Dành cho Website chỉ gồm HTML, CSS, JavaScript. GitHub Pages, Netlify, Vercel, Cloudflare Pages triển khai trực tiếp từ kho mã Git, có tên miền phụ và chứng chỉ HTTPS miễn phí |
Lưu ý: Giáo trình nhấn mạnh Static hosting là lựa chọn phù hợp nhất cho các bài thực hành của khóa học này, vì Website của bạn chỉ gồm HTML, CSS và JavaScript phía trình duyệt. Khi cần xử lý ở máy chủ (cơ sở dữ liệu, đăng nhập...), bạn mới cần tới Shared/VPS/Cloud.
Một cách nhớ nhanh về mức độ "riêng tư" và chi phí khi đi từ Shared sang Dedicated:
const loai = [
{ ten: "Shared", chiaSe: "nhiều Website dùng chung máy chủ", chiPhi: 1 },
{ ten: "VPS", chiaSe: "máy chủ ảo riêng trên máy vật lý chung", chiPhi: 2 },
{ ten: "Cloud", chiaSe: "cụm máy chủ, tăng giảm linh hoạt", chiPhi: 3 },
{ ten: "Dedicated", chiaSe: "trọn một máy chủ vật lý", chiPhi: 4 },
];
for (const l of loai) console.log(l.ten.padEnd(10), "chi phí tương đối", "$".repeat(l.chiPhi).padEnd(5), "-", l.chiaSe);
console.log("Hosting trang tĩnh (GitHub Pages, Netlify, Vercel...): miễn phí cho Website nhỏ.");Lưu ý: Bảng
$ở trên chỉ là thứ tự tương đối để bạn so sánh, không phải bảng giá thật. Giá cụ thể phụ thuộc nhà cung cấp và gói dịch vụ.
2.2. Lựa chọn nơi mua Web host
Hiện nay có khá nhiều công ty cung cấp dịch vụ Web host. Ở Việt Nam, bạn có thể chọn các công ty uy tín như Nhân Hòa, BKNS, Mắt Bão, iNET... Khi quyết định mua, cần cân nhắc:
- Môi trường vận hành của Web host: hệ điều hành, hệ quản trị cơ sở dữ liệu...
- Dung lượng lưu trữ.
- Chi phí duy trì hằng tháng.
- Thời gian sử dụng dự kiến.
Từ đó chọn phương án phù hợp nhất. Câu hỏi ôn tập 8.3 của giáo trình tóm tắt các yếu tố này là giá cả, tốc độ, bảo mật.
Mẹo: Trước khi mua gói dài hạn, hãy đọc kỹ điều khoản hoàn tiền, kiểm tra Website có chạy trên môi trường của host (phiên bản PHP, cơ sở dữ liệu) và thử đặt câu hỏi cho bộ phận hỗ trợ để biết họ phản hồi nhanh đến đâu.
2.3. Chuyển Website lên Web host
Để chuyển toàn bộ mã nguồn Website tới Web host, nếu Web host cung cấp dịch vụ FTP (File Transfer Protocol), bạn có thể dùng ứng dụng FTP Client. Cần lưu ý: FTP truyền tài khoản và mật khẩu ở dạng văn bản thuần, không mã hóa, vì vậy trong thực tế nên ưu tiên hai biến thể có mã hóa là SFTP hoặc FTPS.
Giáo trình giới thiệu giao diện hai ứng dụng thông dụng: FileZilla Client (Hình 8‑1) và CuteFTP (Hình 8‑2). Ngoài ra còn các công cụ FTP Client chuyên nghiệp có tính phí (CuteFTP, WS_FTP Professional, Commander One...) hoặc miễn phí (WinSCP, FTPRush, Cyberduck, Classic FTP, CoffeeCup Free FTP, CoreFTP...).
Tệp phải nằm trong thư mục gốc của Web (thường là public_html, htdocs hoặc www) và trang chủ đặt tên index.html.
Sau khi có tên miền và Web host, mã nguồn được chuyển lên thư mục gốc của host qua FTP client (nên dùng SFTP/FTPS), hoặc tự động qua Git với dịch vụ lưu trữ trang tĩnh.
Sơ đồ cho thấy hai con đường đưa Website lên mạng: (1) từ máy local, dùng FTP/SFTP tải thư mục mã nguồn lên Web host; (2) từ máy local, git push lên GitHub rồi nền tảng như Vercel, Netlify hay GitHub Pages tự động xây dựng và đăng tải. Cả hai đều kết thúc ở một máy chủ phục vụ trang web qua HTTPS.
Với FTP/SFTP, quy trình gồm ba việc chính: kết nối (địa chỉ host, tài khoản, mật khẩu), Upload thư mục hoặc tệp từ máy cá nhân lên Web host, và Download về máy để sao lưu. Hãy nhớ chuyển toàn bộ tệp mà Website cần: trang HTML, thư mục css/, js/, images/... Một liên kết trỏ tới tệp chưa upload sẽ báo lỗi 404.
Đoạn mã dưới đây "quét" một trang HTML mẫu, liệt kê các tệp mà nó cần rồi so với danh sách tệp đã upload để phát hiện tệp bị quên:
const trang = `
<link rel="stylesheet" href="css/style.css">
<script src="js/app.js"></script>
<img src="images/logo.png"> <img src="images/banner.jpg">
<a href="gioi-thieu.html">Giới thiệu</a>`;
const daUpload = new Set(["css/style.css", "js/app.js", "images/logo.png", "gioi-thieu.html"]);
const doc = new DOMParser().parseFromString(trang, "text/html");
const canCo = [...doc.querySelectorAll("[href], [src]")].map((e) => e.getAttribute("href") || e.getAttribute("src"));
console.log("Tệp trang cần:", canCo.join(", "));
const thieu = canCo.filter((t) => !daUpload.has(t));
console.log(thieu.length ? "THIẾU: " + thieu.join(", ") : "Đủ tệp");Lưu ý: Lưu ý của giáo trình: để sao lưu, bạn có thể tải mã nguồn mới nhất trên Web host về máy cá nhân (chuột phải thư mục hoặc tệp trên Web host rồi chọn "Download"). Sao lưu định kỳ giúp bạn khôi phục khi Website bị lỗi hoặc bị tấn công.
2.4. Chứng chỉ SSL và giao thức HTTPS
HTTP truyền dữ liệu dưới dạng văn bản thuần, nghĩa là mọi thông tin người dùng nhập vào — kể cả tài khoản và mật khẩu — đều có thể bị đọc trộm trên đường truyền. HTTPS khắc phục điều này bằng cách mã hóa toàn bộ dữ liệu trao đổi giữa trình duyệt và máy chủ, dựa trên một chứng chỉ số (chứng chỉ SSL/TLS) do một tổ chức cấp chứng chỉ phát hành.
Hiện nay HTTPS là bắt buộc trên thực tế, vì ba lý do:
- Trình duyệt Chrome và Firefox gắn nhãn "Không bảo mật" cho mọi Website còn dùng HTTP.
- Google xác nhận HTTPS là một yếu tố xếp hạng trong kết quả tìm kiếm.
- Nhiều tính năng của trình duyệt như định vị, thông báo đẩy, máy ảnh chỉ hoạt động trên HTTPS.
Chi phí không còn là trở ngại: tổ chức Let's Encrypt cấp chứng chỉ miễn phí và tự động gia hạn; hầu hết nhà cung cấp Web host đều tích hợp sẵn chứng chỉ này trong bảng điều khiển, bạn chỉ cần bật lên. Các nền tảng hiện đại như GitHub Pages, Netlify, Vercel cấp HTTPS tự động ngay khi Website được đưa lên.
Sau khi cài chứng chỉ, cần chuyển hướng toàn bộ truy cập HTTP sang HTTPS. Với máy chủ Apache, thêm đoạn sau vào tệp .htaccess ở thư mục gốc (đây là cấu hình máy chủ nên không chạy thử trong trình duyệt):
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]Ba dòng này đọc như sau: bật bộ viết lại URL; nếu yêu cầu không dùng HTTPS; thì chuyển hướng vĩnh viễn (mã 301) tới đúng địa chỉ đó nhưng với https://. Ta mô phỏng logic này bằng JavaScript:
function chuyenHuongHttps(url) {
const u = new URL(url);
if (u.protocol === "https:") return { trangThai: 200, den: url };
return { trangThai: 301, den: "https://" + u.host + u.pathname + u.search };
}
for (const url of ["http://cuahangminh.vn/", "http://cuahangminh.vn/san-pham?id=7", "https://cuahangminh.vn/gioi-thieu"]) {
const kq = chuyenHuongHttps(url);
console.log(kq.trangThai, url, kq.trangThai === 301 ? "-> " + kq.den : "(giữ nguyên)");
}Cảnh báo: Nếu trang HTTPS lại tải ảnh, CSS hay JavaScript bằng địa chỉ
http://, trình duyệt sẽ chặn hoặc cảnh báo nội dung hỗn hợp (mixed content). Hãy dùng địa chỉ tương đối hoặchttps://cho mọi tài nguyên.
Vừa học xong Web host, FTP và HTTPS, hãy làm các bài sau về chuyển hướng HTTPS, loại nội dung (MIME) máy chủ trả về và chuỗi chuyển hướng:
3. Kiểm thử, tối ưu hóa và bảo trì Website
Giáo trình: Chương 8 — mục "Kiểm thử, tối ưu hóa và bảo trì Website" (Kiểm thử Website sau khi tải lên Web host; Khai báo Website với các công cụ tìm kiếm; Kiểm soát việc thu thập dữ liệu và lập chỉ mục; Sơ đồ Website (sitemap.xml); Tối ưu tốc độ tải trang; Bảo trì Website).
- Mở tên miền, nội dung hiển thị đúng ý
- Ảnh, CSS, JS tải đầy đủ và nhanh
DevTools › Network - Mọi liên kết trên trang hoạt động
- Thử nhiều trình duyệt khác nhau
- Thử trên điện thoại
Responsive Design Mode - HTTPS hợp lệ, HTTP chuyển hướng sang HTTPS
SSL · .htaccess
- Khai báo Website với Google, Bing…
Search Console - Xác minh bằng tệp đặt ở thư mục gốc
- Kiểm soát bot thu thập dữ liệu
robots.txt · meta robots - Lập sơ đồ Website và khai báo
sitemap.xml
- Tối ưu ảnh: đúng định dạng, nén, hoãn tải
loading="lazy" - Bật nén Gzip hoặc Brotli trên máy chủ
- Bật bộ nhớ đệm (cache) cho ảnh, phông, thư viện
- Gộp và rút gọn (minify) CSS, JavaScript
- Dùng CDN khi người dùng ở nhiều quốc gia
CDN
- Theo dõi lượng truy cập
Google Analytics - Kiểm tra tốc độ, SEO, di động
PageSpeed Insights · Nibbler · Woorank - Rà soát liên kết hỏng, lỗi nội dung
Siteimprove - Theo dõi hiện diện mạng xã hội
Grader - Phân tích điểm cần cải thiện
Bing Webmaster Tools
Triển khai chưa phải điểm kết thúc: Website cần được kiểm tra, khai báo, tăng tốc và theo dõi liên tục.
Sơ đồ tổng hợp ba nhóm việc sau khi triển khai: kiểm thử (có chạy đúng không), tối ưu (có nhanh và dễ tìm thấy không) và bảo trì (có giữ được chất lượng theo thời gian không). Phần này đi lần lượt qua từng việc.
3.1. Kiểm thử Website sau khi tải lên Web host
Sau khi thực hiện (1) trỏ tên miền tới Web host và (2) chuyển mã nguồn từ máy cá nhân tới Web host, bạn kiểm tra Website đã hoạt động đúng hay chưa theo các bước sau:
- Bước 1: Mở trình duyệt Web, nhập tên miền và truy cập Website cần kiểm thử.
- Bước 2: Xem lại nội dung trang, đảm bảo giao diện hiển thị đúng như mong muốn của người phát triển.
- Bước 3: Kiểm tra tất cả các liên kết trên trang để chắc chắn chúng hoạt động chính xác.
- Bước 4: Mở trang trên nhiều trình duyệt khác nhau để đảm bảo hiển thị chính xác ở mọi trình duyệt.
Ngoài ra, bạn có thể kiểm tra tốc độ tải trang và việc tải các tài nguyên (ảnh, CSS, JavaScript...) có đầy đủ, chính xác, đủ nhanh hay không: trên Chrome, bấm chuột phải vào trang, chọn "Inspect", chọn thẻ "Network", rồi bấm biểu tượng tải lại trang (Hình 8‑3, 8‑4 của giáo trình). Bạn đã làm quen với DevTools từ buổi 2; thẻ Network cho thấy từng tệp được tải, mã trạng thái, dung lượng và thời gian.
Để kiểm tra Website trên thiết bị di động, dùng chế độ mô phỏng thiết bị của trình duyệt: trên Firefox chọn Menu Tools > Browser Tools > Responsive Design Mode; trên Chrome, mở "Inspect" rồi bấm biểu tượng "Toggle device toolbar" (Hình 8‑5, 8‑6 minh họa trang hiển thị trên iPhone 12/13 Pro Max).
Bước 3 (kiểm tra liên kết) có thể tự động hóa. Đoạn mã dưới đây đọc một trang HTML, gom mọi liên kết nội bộ rồi đối chiếu với danh sách các trang thực sự có trên máy chủ để báo liên kết hỏng (sẽ trả về lỗi 404):
const trangChu = `
<nav>
<a href="index.html">Trang chủ</a>
<a href="gioi-thieu.html">Giới thiệu</a>
<a href="san-pham.html">Sản phẩm</a>
<a href="lien-he.htm">Liên hệ</a>
<a href="https://www.pavietnam.vn">Nhà cung cấp</a>
<a href="#top">Lên đầu trang</a>
</nav>`;
const trangCoThat = new Set(["index.html", "gioi-thieu.html", "lien-he.html"]);
const doc = new DOMParser().parseFromString(trangChu, "text/html");
const noiBo = [...doc.querySelectorAll("a[href]")]
.map((a) => a.getAttribute("href"))
.filter((h) => !h.startsWith("http") && !h.startsWith("#"));
console.log("Liên kết nội bộ:", noiBo.length);
for (const h of noiBo) console.log(trangCoThat.has(h) ? "OK " : "404 ", h);Hãy xem một đoạn HTML nhỏ chạy ngay trong trình duyệt để thấy việc kiểm thử thủ công diễn ra thế nào. Danh sách kiểm tra sau triển khai dưới dạng ô chọn; bảng đếm cho biết còn bao nhiêu việc chưa làm:
<style>
body { font-family: sans-serif; padding: 12px; }
li { list-style: none; margin: 6px 0; }
#tiendo { font-weight: bold; color: #0a7a3d; }
</style>
<h3>Kiểm thử sau khi triển khai</h3>
<ul id="ds">
<li><label><input type="checkbox"> Mở được Website bằng tên miền</label></li>
<li><label><input type="checkbox"> Giao diện hiển thị đúng</label></li>
<li><label><input type="checkbox"> Mọi liên kết hoạt động</label></li>
<li><label><input type="checkbox"> Chạy tốt trên nhiều trình duyệt</label></li>
<li><label><input type="checkbox"> Hiển thị tốt trên thiết bị di động</label></li>
<li><label><input type="checkbox"> Địa chỉ dùng HTTPS</label></li>
</ul>
<p id="tiendo"></p>
<script>
const o = [...document.querySelectorAll("#ds input")];
const cap = () => {
const xong = o.filter((x) => x.checked).length;
document.getElementById("tiendo").textContent = `Đã kiểm: ${xong}/${o.length}`;
console.log("Đã kiểm", xong, "trên", o.length);
};
o.forEach((x) => x.addEventListener("change", cap));
o[0].checked = true; o[5].checked = true; // giả lập thao tác của bạn
cap();
</script>Mẹo: Hãy kiểm thử cả bằng chế độ ẩn danh và điện thoại thật. Trình duyệt thường lưu bộ nhớ đệm khiến bạn tưởng trang đã cập nhật trong khi người dùng vẫn thấy bản cũ (hoặc ngược lại).
3.2. Khai báo Website với các công cụ tìm kiếm
Sau khi đưa Website lên Internet, hãy khai báo với các công cụ tìm kiếm chính (Google, Bing...) để chúng biết Website tồn tại và dẫn người dùng tới. Bạn truy cập trang quản trị của từng công cụ theo bảng sau (Bảng 8‑1 của giáo trình):
| Tên | Đường dẫn tới công cụ tìm kiếm |
|---|---|
https://search.google.com/search-console |
|
| Bing | https://www.bing.com/webmasters |
| Yandex | https://webmaster.yandex.com |
| Baidu | https://ziyuan.baidu.com |
| Yahoo | https://siteexplorer.search.yahoo.com |
Quy trình với Google (Hình 8‑7 đến 8‑10 của giáo trình) gồm các bước:
- Tại trang khai báo, nhập địa chỉ Website mà bạn muốn các bot của công cụ tìm kiếm thu thập dữ liệu.
- Tải tệp xác minh của công cụ tìm kiếm về máy tính cá nhân.
- Chuyển tệp xác minh lên thư mục gốc của Website (có thể dùng FTP Client).
- Quay lại biểu mẫu, bấm nút "XÁC MINH". Khi thành công, bấm "Chuyển đến sản phẩm" để vào Google Search Console với đầy đủ công cụ thiết lập và theo dõi quá trình vận hành Website.
Nếu Website được liên kết đúng cách, các bot của công cụ tìm kiếm sẽ chủ động thu thập dữ liệu các trang còn lại bằng cách đi theo các liên kết trong trang. Bên cạnh việc thu thập, bot còn chấm điểm trang Web: điểm số xác định trang xuất hiện thế nào trong kết quả tìm kiếm, thứ hạng càng cao càng có nhiều cơ hội tiếp cận người dùng.
Vấn đề là mỗi công cụ tìm kiếm dùng thuật toán khác nhau và thường thay đổi thuật toán không báo trước. Một số coi trọng việc có nhiều Website uy tín trỏ liên kết tới; số khác coi trọng mức độ phù hợp giữa nội dung và truy vấn, tốc độ tải trang, khả năng hiển thị tốt trên thiết bị di động. Vì vậy, người quản trị nên tham khảo gợi ý tối ưu trên trang chính thức của các công cụ tìm kiếm và các kỹ thuật SEO (Search Engine Optimization).
Sau khi đã khai báo, mỗi lần cải tiến Website không cần khai báo lại, vì bot định kỳ thu thập và lập chỉ mục (indexing) lại toàn bộ trang; đôi khi công cụ tìm kiếm sẽ chấm lại điểm các trang.
Để biết người dùng đến từ đâu, hầu hết Web host có sẵn công cụ thống kê truy cập. Bạn cũng có thể dùng giải pháp bên thứ ba như Google Analytics miễn phí, hiện là phiên bản Google Analytics 4 – GA4 (https://analytics.google.com/analytics/web/). Dữ liệu này cho biết trang nào đang hoạt động tốt, trang nào chưa hiệu quả, từ đó bạn biết cần thay đổi điểm nào.
Lưu ý: Một lỗi SEO thường gặp là nhồi nhét từ khóa. Theo câu hỏi ôn tập 8.7 của giáo trình, sử dụng từ khóa quá nhiều trên một trang có thể làm giảm hiệu quả SEO. Hãy viết nội dung cho người đọc trước, rồi mới tối ưu cho bot.
Một số yếu tố SEO cơ bản (tiêu đề, mô tả, thẻ h1) có thể chấm tự động. Ví dụ dưới đây chấm điểm ba trang theo ba tiêu chí đơn giản:
const cacTrang = [
{ url: "/", title: "Cửa hàng Minh - Giày thể thao chính hãng", desc: "Giày thể thao nam nữ, giao hàng toàn quốc", h1: 1 },
{ url: "/gioi-thieu.html", title: "Giới thiệu", desc: "", h1: 1 },
{ url: "/lien-he.html", title: "", desc: "Liên hệ cửa hàng", h1: 0 },
];
for (const t of cacTrang) {
const loi = [];
if (!t.title) loi.push("thiếu title");
else if (t.title.length < 10) loi.push("title quá ngắn");
if (!t.desc) loi.push("thiếu description");
if (t.h1 !== 1) loi.push(`số thẻ h1 là ${t.h1} (nên đúng 1)`);
const diem = 100 - loi.length * 25;
console.log(t.url.padEnd(18), String(diem).padStart(3), "điểm", loi.length ? "| " + loi.join(", ") : "| tốt");
}3.3. Kiểm soát việc thu thập dữ liệu và lập chỉ mục
Với nhiều Website, mọi trang và thậm chí toàn bộ thư mục đều có thể bị bot tự động thu thập dữ liệu và lập chỉ mục. Để kiểm soát, bạn tạo một tệp robots.txt đặt ở thư mục gốc của Website. Giáo trình đưa ba ví dụ khai báo:
# 1: không thu thập các trang trong thư mục cart
User-agent: *
Disallow: /cart/
# 2: không thu thập các trang trong hai thư mục cart và private
User-agent: *
Disallow: /cart/
Disallow: /private/
# 3: không thu thập thư mục cart và một tệp cụ thể (private.html) trong thư mục backlist
User-agent: *
Disallow: /cart/
Disallow: /backlist/private.htmlTrong đó User-agent: * nghĩa là áp dụng cho mọi bot, còn mỗi dòng Disallow: là một đường dẫn (tiền tố) mà bot không được thu thập. Đoạn mã dưới đây đọc ví dụ số 3 và quyết định một đường dẫn có được phép thu thập hay không:
const robots = `User-agent: *
Disallow: /cart/
Disallow: /backlist/private.html`;
const luat = robots.split("\n")
.map((d) => d.trim())
.filter((d) => d.toLowerCase().startsWith("disallow:"))
.map((d) => d.slice(9).trim())
.filter(Boolean);
const duocPhep = (duong) => !luat.some((tienTo) => duong.startsWith(tienTo));
for (const d of ["/", "/san-pham.html", "/cart/", "/cart/thanh-toan.html", "/backlist/private.html", "/backlist/public.html"]) {
console.log(duocPhep(d) ? "CHO PHÉP" : "CẤM ", d);
}Cảnh báo:
robots.txtchỉ là lời đề nghị với bot tử tế, không phải cơ chế bảo mật. Ai cũng đọc được tệp này và bot xấu có thể phớt lờ. Đừng dùng nó để giấu dữ liệu nhạy cảm; hãy bảo vệ bằng đăng nhập và phân quyền.
Một giải pháp khác là khai báo thẻ meta robots với nội dung noindex, nofollow: bot không lập chỉ mục trang và cũng không đi theo bất kỳ liên kết nào trên trang. Thẻ này nằm trong phần <head>, nên ta đưa nó vào một trang nhỏ và dùng JavaScript đọc lại giống như một bot làm:
<html>
<head>
<meta charset="UTF-8">
<title>Trang quản trị nội bộ</title>
<meta name="robots" content="noindex, nofollow">
</head>
<body>
<h3>Trang quản trị nội bộ</h3>
<p id="kq"></p>
<script>
const noiDung = document.querySelector('meta[name="robots"]').content;
const chiThi = noiDung.split(",").map((s) => s.trim());
const kq = `Bot ${chiThi.includes("noindex") ? "KHÔNG" : "sẽ"} lập chỉ mục; ${chiThi.includes("nofollow") ? "KHÔNG" : "sẽ"} đi theo liên kết.`;
document.getElementById("kq").textContent = kq;
console.log(kq);
</script>
</body>
</html>Xóa một trang đã được lập chỉ mục
Điều gì xảy ra nếu bạn xóa một trang đã được lập chỉ mục? Trang đó vẫn xuất hiện trong kết quả tìm kiếm cho đến khi Website được lập lại chỉ mục. Trong thời gian chờ, người dùng nhấp vào liên kết sẽ gặp lỗi 404 — để lại ấn tượng kém, thiếu tin cậy. Giải pháp của giáo trình: xóa nội dung khỏi trang nhưng giữ lại chính trang đó, rồi thêm thẻ meta chuyển hướng người dùng sang trang khác:
<meta http-equiv="refresh" content="0; url=../home.html">Giá trị đầu tiên của content phải bằng 0 để chuyển hướng diễn ra ngay lập tức (không trễ); phần url= chỉ trang đích. Thẻ này sẽ điều hướng trang nên ví dụ chỉ để đọc, không có nút chạy thử.
Mở rộng: Với máy chủ Apache, cách "chuẩn" hơn để chuyển hướng trang cũ sang trang mới là khai báo chuyển hướng 301 phía máy chủ (như trong
.htaccessở phần HTTPS). Nó nhanh hơn thẻ meta và thân thiện với công cụ tìm kiếm hơn.
3.4. Sơ đồ Website (sitemap.xml)
Bên cạnh robots.txt, một Website nên có thêm tệp sitemap.xml đặt ở thư mục gốc. Tệp này liệt kê toàn bộ địa chỉ mà người quản trị muốn công cụ tìm kiếm thu thập, kèm thời điểm cập nhật gần nhất, giúp bot phát hiện nhanh các trang mới hoặc các trang không có liên kết nào trỏ tới. Ví dụ của giáo trình:
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://minh-blogs.web.app/</loc>
<lastmod>2026-01-15</lastmod>
</url>
<url>
<loc>https://minh-blogs.web.app/gioi-thieu.html</loc>
</url>
</urlset>Mỗi trang là một phần tử <url> trong <urlset>, trong đó <loc> là địa chỉ đầy đủ và <lastmod> (tùy chọn) là ngày sửa đổi gần nhất. Sau khi tạo xong, khai báo địa chỉ tệp trong mục Sitemaps của Google Search Console. Ngoài ra nên chỉ rõ đường dẫn tới sitemap ngay trong robots.txt bằng dòng:
Sitemap: https://tenmien/sitemap.xmlVới Website nhỏ, bạn không cần viết tay: chỉ cần một đoạn mã sinh XML từ danh sách trang rồi kiểm tra bằng DOMParser:
const goc = "https://minh-blogs.web.app";
const cacTrang = [
{ duong: "/", capNhat: "2026-01-15" },
{ duong: "/gioi-thieu.html" },
{ duong: "/bai-viet/html-co-ban.html", capNhat: "2026-01-20" },
];
const muc = cacTrang.map((t) =>
`<url><loc>${goc}${t.duong}</loc>${t.capNhat ? `<lastmod>${t.capNhat}</lastmod>` : ""}</url>`).join("");
const xml = `<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">${muc}</urlset>`;
const doc = new DOMParser().parseFromString(xml, "application/xml");
console.log("Số URL trong sitemap:", doc.getElementsByTagName("url").length);
for (const loc of doc.getElementsByTagName("loc")) console.log(" -", loc.textContent);
console.log("robots.txt nên có dòng:", "Sitemap: " + goc + "/sitemap.xml");Vừa học xong robots.txt và sitemap.xml, hãy làm các bài sau để tự áp dụng luật robots và chuẩn hóa địa chỉ:
3.5. Tối ưu tốc độ tải trang
Tốc độ tải ảnh hưởng trực tiếp tới trải nghiệm người dùng và thứ hạng tìm kiếm. Giáo trình nêu các biện pháp cơ bản:
| Biện pháp | Làm gì |
|---|---|
| Tối ưu ảnh | Chọn đúng định dạng, nén ảnh trước khi đưa lên, dùng thuộc tính loading="lazy" để hoãn tải ảnh nằm ngoài màn hình |
| Nén Gzip hoặc Brotli | Bật trên máy chủ để giảm dung lượng tệp HTML, CSS, JavaScript |
| Bộ nhớ đệm trình duyệt (cache) | Bật cho các tệp ít thay đổi như ảnh, phông chữ, thư viện |
| Gộp và rút gọn (minify) | Gộp và rút gọn CSS, JavaScript để giảm số lượt yêu cầu và dung lượng |
| CDN | Mạng phân phối nội dung (Content Delivery Network) cho Website có người dùng ở nhiều quốc gia |
CDN sao chép các tệp tĩnh của Website ra nhiều máy chủ đặt rải rác trên thế giới; người dùng được phục vụ từ máy chủ gần mình nhất, nhờ đó giảm đáng kể thời gian chờ. Một số dịch vụ CDN có gói miễn phí: Cloudflare, jsDelivr, Amazon CloudFront. Câu hỏi ôn tập 8.10 hỏi đúng ý này.
Với ảnh, thuộc tính loading="lazy" là cách nhanh nhất để cải thiện: ảnh ở cuối trang chỉ tải khi người dùng cuộn gần tới. Ví dụ dưới đây dùng ảnh SVG nhúng sẵn (không cần mạng) và dùng JavaScript đếm số ảnh được hoãn tải:
<style>
body { font-family: sans-serif; }
img { width: 90px; height: 60px; margin: 4px; border: 1px solid #999; }
</style>
<p>Ảnh đầu trang tải ngay, ảnh phía dưới hoãn tải:</p>
<img alt="Ảnh 1" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='90' height='60'%3E%3Crect width='90' height='60' fill='%23f4a261'/%3E%3C/svg%3E">
<img alt="Ảnh 2" loading="lazy" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='90' height='60'%3E%3Crect width='90' height='60' fill='%232a9d8f'/%3E%3C/svg%3E">
<img alt="Ảnh 3" loading="lazy" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='90' height='60'%3E%3Crect width='90' height='60' fill='%23264653'/%3E%3C/svg%3E">
<script>
const tatCa = document.querySelectorAll("img");
const lazy = document.querySelectorAll('img[loading="lazy"]');
console.log(`Có ${tatCa.length} ảnh, trong đó ${lazy.length} ảnh dùng loading="lazy".`);
</script>Nén và cache có thể "tính" được. Ví dụ rút gọn (minify) CSS bằng cách bỏ chú thích và khoảng trắng thừa, rồi so dung lượng trước/sau:
const css = `
/* Kiểu cho nút */
.nut {
color: white;
background: #0066cc; /* xanh dương */
padding: 8px 16px;
}
.nut:hover {
background: #004c99;
}
`;
const gon = css
.replace(/\/\*[\s\S]*?\*\//g, "")
.replace(/\s+/g, " ")
.replace(/\s*([{}:;,])\s*/g, "$1")
.trim();
console.log("Trước:", css.length, "ký tự");
console.log("Sau :", gon.length, "ký tự");
console.log("Tiết kiệm:", Math.round((1 - gon.length / css.length) * 100) + "%");
console.log(gon);Bộ nhớ đệm trình duyệt được điều khiển qua tiêu đề phản hồi Cache-Control do máy chủ gửi. Ví dụ max-age=31536000, public cho phép trình duyệt giữ tệp một năm:
function phanTichCache(header) {
const kq = {};
for (const phan of header.split(",")) {
const [ten, giaTri] = phan.trim().toLowerCase().split("=");
kq[ten] = giaTri === undefined ? true : /^\d+$/.test(giaTri) ? Number(giaTri) : giaTri;
}
return kq;
}
for (const h of ["max-age=31536000, public", "no-store", "public, max-age=3600"]) {
const c = phanTichCache(h);
const g = c["max-age"];
const thoiGian = !g ? "không có max-age" : g >= 86400 ? `giữ ${g / 86400} ngày` : `giữ ${g / 3600} giờ`;
console.log(h.padEnd(28), "=>", c["no-store"] ? "không lưu cache" : thoiGian);
}Mẹo: Với tệp CSS/JS có cache dài, hãy đổi tên tệp khi nội dung thay đổi (ví dụ
style.v2.csshoặcapp.3f9a1c.js) để người dùng nhận bản mới ngay mà vẫn tận dụng cache cho các tệp không đổi.
Công cụ minh họa của tác giả giáo trình: Thác nước tải trang cho thấy các tệp được tải theo thứ tự nào và tệp nào làm chậm trang.
3.6. Bảo trì Website
Sau khi Website đã triển khai và phục vụ người dùng, người quản trị vẫn cần thường xuyên rà soát và cải thiện hiệu quả hoạt động. Một số công cụ giúp phân tích tổng thể và chỉ ra khía cạnh cần cải thiện (Bảng 8‑2 của giáo trình):
| Công cụ | Địa chỉ URL |
|---|---|
| Google Analytics | https://analytics.google.com/analytics/web/ |
| Bing Webmaster Tools | https://www.bing.com/webmasters |
| Siteimprove | https://www.siteimprove.com |
| Grader | https://website.grader.com |
| Google PageSpeed Insights | https://pagespeed.web.dev |
| Nibbler | https://nibbler.insites.com |
| Woorank | https://www.woorank.com |
- Google Analytics là công cụ phổ biến nhất để phân tích một Website. Đây là dịch vụ phân tích Web của Google, theo dõi và phân tích lượng truy cập: số lượt truy cập, nguồn truy cập (từ Website khác, công cụ tìm kiếm hay mạng xã hội), thời gian ở lại trang, hành vi người dùng (trang được xem, sự kiện tương tác như bấm liên kết, điền biểu mẫu) và nhiều thông tin khác.
- Siteimprove là ứng dụng tính phí dành cho Website lớn: thu thập dữ liệu chuyên sâu, báo cáo liên kết hỏng, lỗi chính tả, vấn đề SEO và khả năng tiếp cận. Chi phí khá cao nhưng xứng đáng với tổ chức phụ thuộc nhiều vào phân tích trực tuyến.
- Grader đặc biệt hữu ích để kiểm tra hiệu quả tiếp thị trên mạng xã hội: giám sát sự hiện diện trên mạng xã hội, hoạt động tin tức, chiến dịch email và khả năng hiển thị đáp ứng trên di động.
- Google PageSpeed Insights, Nibbler, Woorank cung cấp các kiểm tra cơ bản về khả năng tiếp cận, SEO, trải nghiệm người dùng, hiển thị đáp ứng trên di động... Cả ba đều miễn phí và gợi ý những việc nên/không nên làm.
Ví dụ thực tế: Sau hai tuần ra mắt, bạn mở Google Analytics và thấy trang "Giới thiệu" có thời gian ở lại chỉ 5 giây trong khi trang "Sản phẩm" là 2 phút. PageSpeed Insights lại cảnh báo ảnh banner nặng 3 MB. Bạn nén ảnh, thêm
loading="lazy"và viết lại phần đầu trang "Giới thiệu" cho rõ hơn, sau đó theo dõi chỉ số trong tuần kế tiếp. Đó chính là vòng lặp bảo trì: đo → cải thiện → đo lại.
Việc bảo trì còn gồm: sao lưu định kỳ (như đã nói ở phần FTP), gia hạn tên miền và hosting đúng hạn, kiểm tra liên kết hỏng, cập nhật nội dung và thư viện, và theo dõi báo cáo trong Google Search Console.
Vừa học xong tối ưu tốc độ và bảo trì, hãy làm các bài sau để quyết định bật nén, đọc tiêu đề Cache-Control và chấm điểm SEO:
Thực hành theo giáo trình
Giáo trình: Chương 8 — mục "Thực hành" (Bài 8.1. Mua tên miền; Bài 8.2. Mua Web host; Bài 8.3. Chuyển mã nguồn trang Web lên Web host).
Ba bài thực hành của giáo trình mô tả thao tác trên Website của các nhà cung cấp thật (có thanh toán). Vì vậy trong lớp bạn đọc và nắm quy trình, còn việc mua thật chỉ làm khi có nhu cầu; phần triển khai thực tế bạn sẽ làm ở bài tự thực hành 8.4 bằng nền tảng miễn phí.
Bài 8.1. Mua tên miền
Mục tiêu: đăng ký một tên miền và trỏ nó tới nơi lưu trữ Website.
- Bước 1: Truy cập Website của một nhà đăng ký tên miền, nhập tên miền dự định đăng ký và kiểm tra xem còn trống hay không. Nếu còn trống, bấm nút "Chọn" (Hình 8‑16).
- Bước 2: Thanh toán chi phí mua tên miền: bấm "Tiếp tục thanh toán" và tiến hành thanh toán để hoàn tất.
- Bước 3: Nhận thư xác nhận đã đăng ký tên miền thành công.
- Bước 4: Trỏ tên miền tới nơi lưu trữ Website trên Web host, bằng cách khai báo các bản ghi DNS (Hình 8‑17).
Bước 4 chính là ứng dụng của mục 1.2. Đoạn mã dưới đây sinh ra "tờ khai báo" các bản ghi cần nhập vào trang quản lý DNS khi bạn có tên miền và địa chỉ IP của host:
function taoBanGhi(tenMien, ip, mailHost) {
return [
{ ten: "@", loai: "A", giaTri: ip },
{ ten: "www", loai: "CNAME", giaTri: tenMien },
{ ten: "@", loai: "MX", giaTri: `10 ${mailHost}` },
{ ten: "@", loai: "TXT", giaTri: "v=spf1 mx ~all" },
];
}
const ds = taoBanGhi("cuahangminh.vn", "203.0.113.10", "mail.cuahangminh.vn");
console.log("Tên".padEnd(5), "Loại".padEnd(6), "Giá trị");
for (const b of ds) console.log(b.ten.padEnd(5), b.loai.padEnd(6), b.giaTri);Ký hiệu @ đại diện cho chính tên miền gốc. Sau khi lưu, hãy kiên nhẫn chờ bản ghi lan truyền (mục 1.2).
Bài 8.2. Mua Web host
Mục tiêu: chọn và đăng ký một gói Web host gắn với tên miền.
- Bước 1: Lựa chọn gói Web host (gói và thời gian sử dụng) muốn mua, dựa trên bảng giá các gói (Hình 8‑18).
- Bước 2: Bấm "Đặt mua", nhập tên miền muốn liên kết với Web host này, rồi bấm "Đăng ký hosting" (Hình 8‑19).
- Bước 3: Thanh toán chi phí: bấm "Tiếp tục thanh toán" và hoàn tất thanh toán.
- Bước 4: Nhận thư xác nhận đã mua Web host thành công.
Thư xác nhận thường chứa địa chỉ IP/máy chủ FTP, tài khoản và mật khẩu — thông tin bạn dùng ở bài 8.3 và để khai báo bản ghi A ở bài 8.1.
Bài 8.3. Chuyển mã nguồn trang Web lên Web host
Sau khi tải về và cài đặt ứng dụng FTP Client (ví dụ FileZilla), bạn chuyển toàn bộ mã nguồn từ máy cá nhân tới Web host:
- Bước 1: Nhập thông tin Web host (địa chỉ, tài khoản, mật khẩu) rồi bấm "Connect" để kết nối máy cá nhân với Web host (Hình 8‑20).
- Bước 2: Bấm chuột phải vào Thư mục (Folder) hoặc Tệp tin (File) trên máy cá nhân muốn chuyển và chọn "Upload" (Hình 8‑21).
- Lưu ý (sao lưu): để sao lưu, tải mã nguồn mới nhất từ Web host về máy: chuột phải vào thư mục/tệp trên Web host rồi chọn "Download" (Hình 8‑22).
Lưu ý: Hãy dùng SFTP/FTPS nếu Web host hỗ trợ (mục 2.3). Chỉ upload nội dung cần xuất bản (thư mục gốc của Website), đừng upload tệp chứa mật khẩu, khóa API hay thư mục
.git.
Chuẩn bị trang đầu tiên trước khi upload: hãy thử soạn nhanh trong trình soạn trực tiếp dưới đây (HTML, CSS, JS với bản xem trước), rồi chép thành index.html để triển khai.
(Chương trình không in gì.)
Chạy trong khung cách ly ngay trên trình duyệt của bạn; không có mạng.
Câu hỏi ôn tập
Giáo trình: Chương 8 — mục "Câu hỏi ôn tập lý thuyết" (câu 8.1 đến 8.10; đáp án đối chiếu Phụ lục).
Câu 8.1. Tên miền Top-Level Domain (TLD) là gì? A. Phần trước dấu chấm của tên miền, thường là tên tổ chức/doanh nghiệp sở hữu; B. Thành phần cuối cùng của tên miền, đứng sau dấu chấm cuối cùng, chỉ định loại tên miền; C. Tên miền phổ biến như .com, .net, .org, .edu...; D. Cả B và C đều đúng.
Đáp án: D. TLD là thành phần cuối cùng của tên miền (B) và các ví dụ phổ biến là .com, .net, .org, .edu (C). Phương án A là mô tả của nhãn tên tổ chức, không phải TLD.
Câu 8.2. Tên miền phụ (subdomain) là gì? A. Tên miền chứa ký tự đặc biệt như *, &, #; B. Tên miền dùng để chia sẻ một Website trên nhiều máy chủ; C. Tên miền được tạo ra bên trong tên miền chính để chỉ định một khu vực cụ thể của Website; D. Tất cả đều sai.
Đáp án: C. Ví dụ fit trong fit.neu.edu.vn. Tên miền không được chứa ký tự đặc biệt (A sai).
Câu 8.3. Để chọn một dịch vụ Web host phù hợp, cần lưu ý yếu tố nào? A. Giá cả, tốc độ, bảo mật; B. Tên miền, giao diện, nội dung; C. Màu sắc chủ đạo và phông chữ của Website; D. Số lượng ảnh có trong Website.
Đáp án: A. Giá cả, tốc độ, bảo mật (cùng môi trường vận hành, dung lượng, chi phí duy trì).
Câu 8.4. Dịch vụ Web host thương mại phổ biến hiện nay chạy trên những hệ điều hành nào? A. Windows; B. Linux; C. macOS; D. Cả A và B.
Đáp án: D. Windows hosting và Linux hosting.
Câu 8.5. Loại Web host nào có chi phí thấp nhất, phù hợp với Website nhỏ và người mới bắt đầu? A. Shared hosting; B. VPS hosting; C. Dedicated hosting; D. Tất cả đều đúng.
Đáp án: A. Shared hosting, vì nhiều Website chia sẻ chi phí thuê và vận hành máy chủ.
Câu 8.6. Trong phát triển Web, SEO là viết tắt của cụm từ nào? A. Search Engine Optimization; B. Site Engine Optimization; C. Social Engine Optimization; D. Search Engine Operation.
Đáp án: A. Search Engine Optimization (tối ưu hóa công cụ tìm kiếm).
Câu 8.7. Sử dụng từ khóa quá nhiều trên một trang Web ảnh hưởng gì tới SEO? A. Tốt cho SEO; B. Không ảnh hưởng; C. Có thể làm giảm hiệu quả SEO; D. Chỉ ảnh hưởng tốc độ tải trang.
Đáp án: C. Nhồi nhét từ khóa có thể làm giảm hiệu quả SEO.
Câu 8.8. Tại sao phải bảo trì Website? A. Để tăng cường tính năng và hiệu suất của Website; B. Để tạo giao diện mới; C. Để tăng doanh số bán hàng; D. Để tạo nhiều trang Web mới.
Đáp án: A. Bảo trì giúp Website vận hành tốt, an toàn và hiệu quả theo thời gian.
Câu 8.9. Trong triển khai Website, phương thức nào thường dùng để tải tệp mã nguồn từ máy cá nhân lên Web host? A. FTP; B. SMTP; C. HTTP; D. HTTPS.
Đáp án: A. FTP (nên dùng SFTP/FTPS cho an toàn). SMTP dùng để gửi thư điện tử.
Câu 8.10. Để giảm thời gian tải Website, dùng công nghệ nào để phân phối nội dung trên các máy chủ khác nhau? A. Load balancing; B. Server-side rendering; C. Caching; D. Content Delivery Network (CDN).
Đáp án: D. CDN sao chép tệp tĩnh ra nhiều máy chủ trên thế giới để phục vụ người dùng từ nơi gần nhất.
Bạn có thể tự kiểm tra bằng đoạn mã sau — nó chứa đáp án chuẩn của chương 8 trong Phụ lục và chấm bài làm của bạn (hãy sửa mảng baiLam để thử):
const dapAn = { "8.1": "D", "8.2": "C", "8.3": "A", "8.4": "D", "8.5": "A", "8.6": "A", "8.7": "C", "8.8": "A", "8.9": "A", "8.10": "D" };
const baiLam = { "8.1": "D", "8.2": "C", "8.3": "B", "8.4": "D", "8.5": "A", "8.6": "A", "8.7": "C", "8.8": "A", "8.9": "A", "8.10": "C" };
let dung = 0;
for (const cau of Object.keys(dapAn)) {
const ok = baiLam[cau] === dapAn[cau];
if (ok) dung++; else console.log(`Câu ${cau}: bạn chọn ${baiLam[cau]}, đáp án ${dapAn[cau]}`);
}
console.log(`Đúng ${dung}/10 câu, tương đương ${dung.toFixed(1)} điểm (mỗi câu 1 điểm)`);Bài tập tự thực hành theo giáo trình
Giáo trình: Chương 8 — mục "Bài tập tự thực hành" (Bài 8.4. Triển khai Website lên Vercel).
Bài 8.4. Triển khai Website lên Vercel
Đề bài: tạo một dự án Website đơn giản (hoặc dùng dự án có sẵn của bạn), rồi thực hiện:
- Triển khai lên Vercel (hoặc GitHub Pages, Netlify) và kiểm tra Website đã chạy trên giao thức HTTPS chưa.
- Bổ sung tệp
robots.txtvàsitemap.xmlvào thư mục gốc của Website. - Khai báo Website với Google Search Console và khai báo tệp
sitemap.xml. - Dùng Google PageSpeed Insights chấm điểm Website, ghi lại ba khuyến nghị quan trọng nhất và thực hiện ít nhất một trong ba khuyến nghị đó.
Gợi ý các bước (với Vercel):
- Đưa thư mục dự án lên một kho GitHub (bạn đã học
git add,commit,pushở buổi 14). - Đăng nhập Vercel bằng tài khoản GitHub, chọn Add New → Project, nhập kho vừa tạo; với Website tĩnh, để nguyên cấu hình mặc định rồi bấm Deploy.
- Nhận địa chỉ dạng
ten-du-an.vercel.app, đã có HTTPS tự động. Mở thử và nhìn biểu tượng ổ khóa trên thanh địa chỉ. - Tạo
robots.txtvàsitemap.xmlở thư mục gốc, commit và push; Vercel tự triển khai lại. - Vào Google Search Console, thêm Website (xác minh quyền sở hữu), mục Sitemaps nhập
sitemap.xml. - Chạy PageSpeed Insights cho cả bản điện thoại và máy tính, ghi ba khuyến nghị đầu tiên (thường là nén ảnh,
loading="lazy", rút gọn CSS/JS) và sửa.
Đoạn mã dưới đây là bộ "kiểm tra nhanh" mà bạn có thể sao chép làm kiểu cho dự án của mình: nó nhận danh sách tệp ở thư mục gốc, nội dung robots.txt và sitemap.xml rồi báo lỗi thường gặp:
const goc = ["index.html", "css/style.css", "robots.txt", "sitemap.xml"];
const robots = "User-agent: *\nDisallow: /private/\nSitemap: https://ten-du-an.vercel.app/sitemap.xml";
const sitemap = `<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"><url><loc>https://ten-du-an.vercel.app/</loc></url><url><loc>http://ten-du-an.vercel.app/lien-he.html</loc></url></urlset>`;
const kiemTra = [];
for (const t of ["index.html", "robots.txt", "sitemap.xml"]) if (!goc.includes(t)) kiemTra.push(`thiếu ${t} ở thư mục gốc`);
if (!/^Sitemap:\s*https:\/\//im.test(robots)) kiemTra.push("robots.txt chưa khai báo Sitemap bằng https");
if (/^Disallow:\s*\/\s*$/im.test(robots)) kiemTra.push("Disallow: / sẽ chặn toàn bộ Website!");
const doc = new DOMParser().parseFromString(sitemap, "application/xml");
for (const loc of doc.getElementsByTagName("loc")) {
if (!loc.textContent.startsWith("https://")) kiemTra.push("sitemap có URL không dùng HTTPS: " + loc.textContent);
}
console.log(kiemTra.length ? kiemTra.join("\n") : "Mọi thứ ổn");Hãy sửa dữ liệu mẫu để kết quả "Mọi thứ ổn" — đó cũng là danh sách việc bạn cần có trong bài nộp.
Tổng kết khóa học
Mở rộng: Phần này không nằm trong chương 8 mà do khóa học bổ sung để khép lại 15 buổi: ôn lại toàn bộ chương trình, đặt ra dự án cuối kỳ và gợi ý hướng học tiếp. Mọi nội dung đều dựa trên 8 chương của giáo trình.
Bản đồ 15 buổi của khóa
Khóa học đi từ "web là gì" tới "web chạy trên Internet", theo đúng quy trình phát triển Web mà bạn đã gặp ở buổi 1:
- Mục đích trang Web, đối tượng sử dụng
- Tính năng chính, giao diện và công nghệ mong muốn
- Ngân sách, cơ chế thanh toán/tạm ứng
- Kế hoạch: nguồn lực, tiến độ, chi phí
- Sơ đồ Website (sitemap)
- Phác thảo giao diện (wireframe)
- UI: nút bấm, biểu tượng, ô nhập
- UX: cách người dùng tương tác
- Bố cục, màu sắc, logo; nhận phản hồi rồi chỉnh sửa lặp lại
- "Content is king": nội dung là vua
- Viết tiêu đề, văn bản hấp dẫn
- Tối ưu SEO, đa phương tiện, liên kết nội bộ
- Frontend: HTML, CSS, JavaScript
- Backend: xử lý, cơ sở dữ liệu, cung cấp dữ liệu
- Làm trang chủ trước, rồi các trang phụ
- Liên kết, biểu mẫu, tập lệnh, chính tả
- Trình xác thực mã theo chuẩn Web
- Chức năng, giao diện, hiệu suất, bảo mật
- Cài đặt, cấu hình trên máy chủ (production)
- Giám sát, cập nhật nội dung và bảo mật
- Khắc phục lỗi để duy trì trải nghiệm tốt
- Bước 1–2 Lập kế hoạch thay đổi
- Bước 3–4 Thiết kế thay đổi
- Bước 5–6 Lập trình, kiểm thử, chạy thay đổi
Bước 7 không phải điểm dừng: mỗi thay đổi sau khi vận hành lại đi qua các bước 1 đến 6; kiểm thử diễn ra thường xuyên suốt quá trình.
Sơ đồ nhắc lại bảy bước phát triển Web của chương 1: thu thập thông tin, lập kế hoạch, thiết kế giao diện và trải nghiệm người dùng, sáng tạo nội dung, lập trình, kiểm thử – đánh giá, triển khai và bảo trì. Buổi hôm nay chính là bước 6 và bước 7 ở cuối quy trình.
| Buổi | Nội dung | Giáo trình | Sản phẩm bạn làm được |
|---|---|---|---|
| 1 | Tổng quan về thiết kế Website | Chương 1 | Hiểu mô hình khách – chủ, URL, quy trình 7 bước |
| 2 | HTML, CSS, JavaScript và công cụ | Chương 1 | Chọn công cụ, dùng DevTools, ba cách nhúng mã |
| 3 | HTML (1): tài liệu, phần tử, thuộc tính, head | Chương 2 | Khung tài liệu HTML đúng chuẩn |
| 4 | HTML (2): ngữ nghĩa, văn bản, bảng, danh sách, liên kết | Chương 2 | Trang nội dung có cấu trúc |
| 5 | HTML (3): biểu mẫu, đa phương tiện | Chương 2 | Form và nhúng ảnh/âm thanh/video |
| 6 | CSS (1): cú pháp, cách nhúng, bộ chọn | Chương 3 | Chọn đúng phần tử để định dạng |
| 7 | CSS (2): màu sắc và định dạng | Chương 3 | Trang có màu, nền, chữ, biến CSS |
| 8 | Bố cục (1): mô hình hộp, kích thước, vị trí | Chương 4 | Làm chủ box model, display, position |
| 9 | Bố cục (2): Flexbox, Grid, đáp ứng | Chương 4 | Bố cục linh hoạt, responsive |
| 10 | JavaScript căn bản (1) | Chương 5 | Biến, kiểu dữ liệu, toán tử, hàm |
| 11 | JavaScript căn bản (2) | Chương 5 | Mảng, điều kiện, vòng lặp, lỗi, đối tượng |
| 12 | JavaScript cho Website (1) | Chương 6 | window, document, sự kiện, DOM |
| 13 | JavaScript cho Website (2) | Chương 6 | Xác thực form, canvas, JSON, fetch |
| 14 | Công cụ hỗ trợ | Chương 7 | Emmet, Git/GitHub, SASS, Bootstrap, jQuery |
| 15 | Triển khai Website và tổng kết | Chương 8 | Website có tên miền, HTTPS, đã khai báo tìm kiếm |
Nhìn bản đồ này, bạn thấy ba lớp kiến thức xếp chồng: HTML là cấu trúc, CSS là trình bày, JavaScript là hành vi — và lớp ngoài cùng là công cụ và triển khai để biến mã nguồn thành sản phẩm.
Dự án cuối kỳ
Dự án cuối kỳ gom mọi thứ bạn đã học vào một Website hoàn chỉnh. Yêu cầu gợi ý:
- Chủ đề tự chọn: cửa hàng nhỏ, blog cá nhân, câu lạc bộ, hồ sơ năng lực (portfolio), trang giới thiệu một địa điểm...
- Tối thiểu 5 trang: trang chủ, danh sách, trang chi tiết, giới thiệu, liên hệ.
- HTML ngữ nghĩa (
header,nav,main,section,article,footer), có ít nhất một bảng hoặc danh sách và một biểu mẫu liên hệ. - CSS đáp ứng dùng Flexbox hoặc Grid, hiển thị tốt trên điện thoại, máy tính bảng, máy tính.
- JavaScript: xác thực biểu mẫu, ít nhất một tương tác DOM (lọc, tìm kiếm, mở/đóng...) và một phần dữ liệu đọc từ tệp JSON bằng
fetch. - Công cụ: quản lý mã bằng Git/GitHub, có thể dùng Emmet, SASS hoặc Bootstrap.
- Triển khai: đưa lên Vercel/GitHub Pages/Netlify với HTTPS, có
robots.txt,sitemap.xml, khai báo Google Search Console và tối ưu theo PageSpeed Insights.
Bảng tiêu chí đánh giá gợi ý (tổng 100 điểm). Hãy chạy đoạn mã để tự chấm dự án của mình — sửa mảng diem theo thực tế:
const tieuChi = [
{ ten: "HTML ngữ nghĩa và khả năng tiếp cận", trongSo: 15 },
{ ten: "CSS và bố cục đáp ứng", trongSo: 20 },
{ ten: "JavaScript tương tác (DOM, form, JSON)", trongSo: 20 },
{ ten: "Công cụ (Git/GitHub, Emmet, SASS...)", trongSo: 10 },
{ ten: "Triển khai (HTTPS, robots, sitemap)", trongSo: 15 },
{ ten: "Hiệu năng và SEO (PageSpeed)", trongSo: 10 },
{ ten: "Báo cáo và thuyết trình", trongSo: 10 },
];
const diem = [0.9, 0.8, 0.75, 1, 0.9, 0.7, 0.8]; // mức đạt từ 0 đến 1 cho từng tiêu chí
let tong = 0;
tieuChi.forEach((t, i) => {
const d = t.trongSo * diem[i];
tong += d;
console.log(t.ten.padEnd(40), `${d.toFixed(1)}/${t.trongSo}`);
});
console.log("Tổng điểm:", tong.toFixed(1), "/ 100");
console.log("Quy đổi hệ 10:", (tong / 10).toFixed(1));Mẹo: Làm dự án theo vòng đời thay vì dồn vào cuối: tuần đầu phân tích và phác thảo giao diện; tiếp đó dựng HTML; rồi CSS; rồi JavaScript; triển khai sớm một bản đơn giản lên Vercel để biết quy trình, sau đó mỗi lần cải tiến chỉ cần
git push.
Hướng ôn tập
Hãy ôn theo từng lớp kiến thức, mỗi chương gắn với một cách tự kiểm tra:
| Chương | Trọng tâm ôn | Tự kiểm tra bằng cách |
|---|---|---|
| 1 | Mô hình khách – chủ, URL, quy trình phát triển, tính khả dụng, SEO, đáp ứng | Giải thích từng thành phần của một URL và 7 bước quy trình |
| 2 | Khung tài liệu, phần tử/thuộc tính, ngữ nghĩa, bảng, danh sách, liên kết, biểu mẫu, đa phương tiện | Viết từ đầu một trang blog có form liên hệ |
| 3 | Cú pháp CSS, bộ chọn, độ đặc hiệu, màu, nền, văn bản, biến CSS | Dự đoán kiểu nào thắng khi hai quy tắc xung đột |
| 4 | Mô hình hộp, display, position, Flexbox, Grid, media query | Dựng bố cục 3 cột chuyển thành 1 cột trên điện thoại |
| 5 | Biến, kiểu dữ liệu, toán tử, hàm, mảng, vòng lặp, try/catch, đối tượng |
Làm các nhóm bài JavaScript trên Codelab |
| 6 | window, DOM, sự kiện, xác thực form, JSON, fetch |
Viết trang có danh sách lọc theo ô tìm kiếm |
| 7 | Emmet, Git/GitHub, SASS, Bootstrap, jQuery | Tạo kho, commit, push; dựng trang Bootstrap |
| 8 | Tên miền, DNS, Web host, FTP, HTTPS, robots.txt, sitemap.xml, tối ưu, bảo trì | Làm lại 10 câu ôn tập 8.1–8.10 và bài 8.4 |
Ba mẹo ôn tập: (1) tự gõ lại các ví dụ chạy thử thay vì chỉ đọc; (2) làm lại các bài tập Codelab mà bạn từng sai; (3) mở DevTools trên Website bất kỳ và tự hỏi "phần này viết bằng HTML/CSS/JS nào?".
Lộ trình học tiếp
Mở rộng: Các hướng dưới đây là gợi ý ngoài giáo trình để bạn tiếp tục sau khi kết thúc khóa.
| Hướng | Học gì | Dựa trên nền tảng nào của khóa |
|---|---|---|
| Front-end nâng cao | TypeScript, framework (React, Vue), công cụ đóng gói (Vite) | JavaScript buổi 10–13, DOM, Git |
| Back-end | Node.js/Express, cơ sở dữ liệu, REST API, xác thực người dùng | fetch, JSON, HTTP, triển khai |
| Thiết kế giao diện và trải nghiệm | Figma, nguyên tắc UX/UI, hệ thống thiết kế | Buổi 1–2, CSS, thiết kế đáp ứng |
| Chất lượng và vận hành | Kiểm thử tự động, CI/CD (GitHub Actions), Docker, giám sát | Git/GitHub, triển khai, bảo trì |
| Bảo mật và khả năng tiếp cận | OWASP Top 10 (XSS, CSRF), WCAG, HTTPS nâng cao | Xác thực form, HTTPS, HTML ngữ nghĩa |
Điểm chung của mọi hướng đều là nền tảng bạn vừa học: HTML cấu trúc tốt, CSS bố cục chắc, JavaScript tư duy rõ ràng và thói quen đưa sản phẩm lên mạng, đo lường rồi cải thiện.
Sai lầm thường gặp
| Sai lầm | Hậu quả | Cách đúng |
|---|---|---|
| Để Website chạy trên HTTP | Trình duyệt gắn nhãn "Không bảo mật", dữ liệu có thể bị đọc trộm, xếp hạng tìm kiếm kém | Bật chứng chỉ SSL/TLS (Let's Encrypt), chuyển hướng 301 từ HTTP sang HTTPS |
| Upload bằng FTP thường qua mạng công cộng | Mật khẩu truyền dạng văn bản thuần, dễ bị lộ | Dùng SFTP hoặc FTPS |
| Quên upload tệp (CSS, JS, ảnh) hoặc sai đường dẫn | Trang mất định dạng, ảnh vỡ, liên kết lỗi 404 | Upload đủ thư mục, kiểm tra thẻ Network và kiểm tra liên kết sau khi triển khai |
| Thấy tên miền chưa vào được ngay rồi sửa bản ghi liên tục | Làm kéo dài thời gian lan truyền, gây rối cấu hình | Chờ theo TTL (có thể đến 24–48 giờ), kiểm tra lại rồi mới chỉnh |
Đặt robots.txt sai chỗ hoặc viết Disallow: / nhầm |
Bot không thu thập hoặc chặn cả Website khỏi tìm kiếm | Đặt ở thư mục gốc, kiểm tra từng dòng Disallow |
Dùng robots.txt để giấu thông tin nhạy cảm |
Ai cũng đọc được tệp và biết đường dẫn bạn muốn giấu | Bảo vệ bằng đăng nhập, phân quyền; dùng noindex khi chỉ cần không hiện trên tìm kiếm |
| Xóa hẳn trang đã lập chỉ mục | Người dùng nhấp từ kết quả tìm kiếm gặp lỗi 404, mất tin cậy | Giữ lại trang, xóa nội dung và chuyển hướng bằng meta refresh (hoặc 301 phía máy chủ) |
| Nhồi từ khóa vào trang | Làm giảm hiệu quả SEO | Viết nội dung tự nhiên cho người đọc, tiêu đề và mô tả rõ ràng |
Ảnh quá lớn, không nén, không loading="lazy" |
Trang tải chậm, người dùng bỏ đi | Nén ảnh, chọn đúng định dạng, hoãn tải ảnh ngoài màn hình, dùng CDN |
| Quên gia hạn tên miền hoặc hosting | Tên miền bị thu hồi, Website biến mất | Đặt nhắc lịch, bật tự động gia hạn, theo dõi ngày hết hạn |
| Không sao lưu | Mất mã nguồn khi host lỗi hoặc bị tấn công | Download định kỳ qua FTP và luôn giữ bản trên Git/GitHub |
Tóm tắt
- Tên miền (domain) là địa chỉ dạng chữ thay cho địa chỉ IP; gồm các nhãn cách nhau bằng dấu chấm, chữ cái/số/dấu
-, nhãn ≤ 63 ký tự, tổng ≤ 253 ký tự. Kết thúc bằng TLD (do ICANN/IANA quản lý;.vndo VNNIC). - DNS dịch tên miền thành IP; các bản ghi A, AAAA, CNAME, MX, TXT, NS; thay đổi bản ghi cần thời gian lan truyền (TTL, thường tới 24–48 giờ).
- Web host: Shared, VPS, Cloud, Dedicated, Windows/Linux, Static hosting... Chọn theo môi trường vận hành, dung lượng, chi phí, thời gian dùng; Website tĩnh dùng GitHub Pages/Netlify/Vercel là phù hợp nhất.
- Chuyển mã nguồn bằng FTP Client (ưu tiên SFTP/FTPS); bật HTTPS bằng chứng chỉ SSL/TLS (Let's Encrypt) và chuyển hướng 301 HTTP → HTTPS.
- Kiểm thử sau khi tải lên: mở bằng tên miền, kiểm tra giao diện, liên kết, nhiều trình duyệt, thiết bị di động, thẻ Network.
- Khai báo với công cụ tìm kiếm (Search Console + tệp xác minh); kiểm soát bot bằng
robots.txt, meta robots,sitemap.xml; xử lý trang bị xóa bằng chuyển hướng. - Tối ưu tốc độ: ảnh,
loading="lazy", Gzip/Brotli, cache, minify, CDN. Bảo trì bằng Google Analytics, PageSpeed Insights, Nibbler, Woorank, Siteimprove, Grader. - Khóa học khép lại bằng bản đồ 15 buổi, dự án cuối kỳ và các hướng học tiếp.