Quản lý dependency an toàn: chọn, cập nhật và kiểm soát thư viện bên ngoài

  • author-image

    Nguyễn Đình Cường

  • blog-tag
  • blog-comment 0 comment
  • created-date 09 Nov, 2026
blog-thumbnail

Dự án hiện đại hiếm khi tự viết mọi thứ, chúng dựa vào hàng chục hay hàng trăm thư viện bên ngoài. Điều này giúp tiết kiệm thời gian nhưng cũng kéo theo rủi ro: lỗi bảo mật, thư viện bị bỏ rơi, cập nhật làm hỏng ứng dụng. Bài này đưa ra thói quen để dùng dependency một cách an toàn và bền vững.

Trước khi thêm một thư viện: đặt câu hỏi

Mỗi dependency là một khoản nợ: bạn phải theo dõi, cập nhật và tin tưởng nó. Trước khi cài, hãy hỏi:

  1. Có thật sự cần không? Nếu chỉ dùng một hàm nhỏ và ngôn ngữ có sẵn cách làm tương tự, đừng thêm cả thư viện.
  2. Còn được duy trì không? Xem lần phát hành gần nhất, hoạt động của kho mã, số issue tồn đọng và có người duy trì phản hồi không.
  3. Mức độ phổ biến và độ tin cậy? Lượng người dùng đông, tài liệu tốt, có cộng đồng là dấu hiệu tích cực (nhưng không tuyệt đối).
  4. Giấy phép là gì? Đảm bảo tương thích với cách bạn dùng (thương mại, mã nguồn đóng...).
  5. Kích thước và phụ thuộc kéo theo? Một thư viện nhỏ có thể kéo hàng chục thư viện con.
  6. Tên có đúng không? Kẻ xấu hay đăng gói giả có tên gần giống gói nổi tiếng (typosquatting). Kiểm tra kỹ chính tả và nguồn gốc trước khi cài.

Dùng lockfile và commit nó

File khóa phụ thuộc ghi lại phiên bản chính xác của mọi gói đã cài, kể cả gói gián tiếp: package-lock.json (npm), yarn.lock, pnpm-lock.yaml, composer.lock (PHP), poetry.lock hoặc requirements.txt được ghim phiên bản (Python), Cargo.lock (Rust), go.sum (Go).

  • Commit lockfile vào Git với ứng dụng để mọi người và môi trường build đều dùng đúng một bộ phiên bản.
  • Trên CI và khi deploy, dùng lệnh cài theo lockfile nghiêm ngặt như npm ci thay vì npm install.
  • Với thư viện chia sẻ cho người khác, thường chỉ khai báo khoảng phiên bản tương thích, còn lockfile phục vụ phát triển và kiểm thử.

Hiểu phiên bản ngữ nghĩa (SemVer)

Nhiều thư viện đánh số dạng MAJOR.MINOR.PATCH, ví dụ 2.4.1:

  • PATCH (2.4.1): sửa lỗi, không đổi API.
  • MINOR (2.4.1): thêm tính năng, vẫn tương thích ngược.
  • MAJOR (2.4.1): có thay đổi phá vỡ tương thích.

Ký hiệu như ^2.4.1 cho phép nâng MINOR và PATCH, ~2.4.1 chỉ nâng PATCH. Đây là quy ước, không phải bảo đảm tuyệt đối, nên vẫn phải đọc ghi chú phát hành và chạy test khi cập nhật.

Cập nhật đều đặn, từng bước nhỏ

Bỏ mặc dependency nhiều năm rồi nâng cấp một lượt thường gây ác mộng, vì phải vượt qua nhiều thay đổi phá vỡ cùng lúc. Thói quen tốt hơn:

  1. Kiểm tra định kỳ (hàng tuần hoặc hàng tháng): npm outdated, composer outdated, pip list --outdated.
  2. Cập nhật bản vá và bản nhỏ thường xuyên, mỗi lần một nhóm nhỏ.
  3. Với bản lớn (major), đọc hướng dẫn nâng cấp, làm trên nhánh riêng và chạy đầy đủ test.
  4. Dùng công cụ tự động như Dependabot hoặc Renovate để mở pull request cập nhật, bạn chỉ cần xem và merge khi test qua.
  5. Có bộ test tốt thì cập nhật rẻ và an tâm hơn nhiều.

Theo dõi lỗ hổng bảo mật

  • Chạy các lệnh kiểm tra như npm audit, composer audit, pip-audit để phát hiện gói có lỗ hổng đã biết.
  • Bật cảnh báo bảo mật của nền tảng lưu mã (GitHub, GitLab).
  • Đánh giá mức độ ảnh hưởng thực tế: lỗ hổng trong công cụ chỉ dùng lúc phát triển thường ít nghiêm trọng hơn trong mã chạy trên production.
  • Ưu tiên cập nhật nhanh các lỗ hổng nghiêm trọng ở phần tiếp xúc với dữ liệu người dùng.

Giảm rủi ro chuỗi cung ứng

  1. Chỉ cài từ registry chính thức, cẩn trọng với gói có ít người dùng hoặc mới đăng.
  2. Hạn chế chạy các script tự động khi cài đặt từ nguồn không rõ.
  3. Khóa phiên bản và xem lại thay đổi lockfile trong pull request.
  4. Không đưa khóa bí mật vào môi trường chạy bước cài đặt nếu không cần thiết.
  5. Cân nhắc kho gói nội bộ (mirror) cho tổ chức lớn.

Bọc thư viện bằng lớp của riêng bạn

Với thư viện quan trọng (gửi email, thanh toán, lưu trữ), đừng gọi trực tiếp rải rác khắp mã. Hãy bọc nó sau một giao diện nhỏ của dự án:

// mailer.js: toàn bộ ứng dụng chỉ biết hàm nàyimport someMailLib from 'some-mail-lib';export async function sendMail({ to, subject, html }) {return someMailLib.send({ to, subject, body: html });}

Khi cần thay thư viện, bạn chỉ sửa một file. Việc này cũng giúp viết test dễ hơn bằng cách giả lập hàm bọc.

Dọn dẹp định kỳ

  • Gỡ gói không còn dùng (npm uninstall, composer remove); công cụ như depcheck giúp phát hiện.
  • Phân biệt phụ thuộc chạy thật và phụ thuộc chỉ để phát triển (dependencies và devDependencies).
  • Xem lại các gói trùng chức năng và gộp về một lựa chọn.

Kết luận

Dùng thư viện bên ngoài là điều bình thường, quan trọng là có kỷ luật: chọn kỹ, khóa phiên bản, cập nhật đều, theo dõi bảo mật và bọc những phần quan trọng. Những thói quen này giữ cho dự án khỏe mạnh theo thời gian.

Để học cách xây dựng và vận hành dự án với hệ sinh thái thư viện hiện đại, bạn có thể tham khảo các khóa học tại codebem.com.

author_photo
Nguyễn Đình Cường

0 comment