Ở Phần 1, chúng ta đã xây dựng một Chrome Extension Scroll To Top.
Sang Phần 2, chúng ta sẽ đi sâu vào một khái niệm cốt lõi nhất của Chrome Extension:
Làm thế nào để chạy JavaScript trên mọi trang web?
Câu trả lời chính là: Content Script.
Mục tiêu của Phần 2
Sau bài viết này, bạn sẽ:
- Hiểu content script là gì
- Biết cách chạy script trên mọi website
- Biết thời điểm script được inject
- Tránh các lỗi phổ biến khi làm việc với DOM
- Có một extension hoàn chỉnh dùng được ngay
Content Script là gì?
Content Script là JavaScript được Chrome inject trực tiếp vào trang web đang mở trên Google Chrome.
Content Script có thể:
- Đọc & thay đổi DOM
- Gắn event
- Inject UI
- Đọc nội dung trang
👉 Content Script là cách DUY NHẤT để chạy code trên web page.
Khai báo Content Script trong manifest.json
Chúng ta bắt đầu với một extension tối thiểu có cấu trúc thư mục như sau:
run-script-all-pages/
├── manifest.json
└── content.js
Cấu hình content_scripts
{
"manifest_version": 3,
"name": "Run Script On All Pages",
"version": "1.0",
"description": "Demo chạy content script trên mọi trang web",
// Cấu hình content scripts
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"]
}
]
}
Giải thích:
matches: xác định trang nào sẽ chạy script
all_urls: tất cả website (http, https)
Các kiểu matches phổ biến
"matches": [
"https://example.com/*",
"https://*.google.com/*"
]
Bạn cũng có thể giới hạn phạm vi chạy để tối ưu hiệu năng.
Loại trừ trang không cần chạy
"exclude_matches": [
"https://mail.google.com/*"
]
Thời điểm Content Script được inject
Chrome cho phép bạn chọn thời điểm chạy script bằng run_at.
Các giá trị run_at
| Giá trị | Ý nghĩa |
|---|---|
document_start | Trước khi DOM render |
document_end | DOM cơ bản đã sẵn sàng |
document_idle | Trang load xong |
Áp dụng vào manifest
{
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"],
"run_at": "document_idle"
}
]
}
📌 Trong đa số trường hợp, document_idle là an toàn nhất.
Quyền truy cập của Content Script
Content Script:
- ✅ Truy cập DOM
- ✅ Dùng
window,document - ❌ Không dùng
chrome.tabs - ❌ Không dùng
chrome.storagetrực tiếp
👉 Nếu cần quyền cao hơn → phải message sang background (Phần 3).
Làm việc với DOM trong Content Script
Đọc thông tin trang
console.log('URL:', window.location.href);
console.log('Title:', document.title);
Chỉnh sửa DOM
document.body.style.border = '4px solid #2563eb';
📌 Mọi thay đổi DOM đều chỉ ảnh hưởng trang hiện tại.
Chạy trên các trang SPA (React, Vue, Angular)
Các trang SPA như:
- React
- Vue
- Angular
👉 Thường không reload page, nên content script:
- Chỉ chạy 1 lần
- DOM thay đổi liên tục
Giải pháp: MutationObserver
const observer = new MutationObserver(() => {
console.log('DOM thay đổi');
});
observer.observe(document.body, {
childList: true,
subtree: true
});
Chống inject trùng (Best Practice)
Rất quan trọng ❗
if (document.getElementById('my-extension-root')) return;
const root = document.createElement('div');
root.id = 'my-extension-root';
document.body.appendChild(root);
👉 Luôn:
- Gắn
id - Check trước khi inject
Giao tiếp với Extension (Overview)
Content Script không lưu state tốt → cần giao tiếp:
- Popup
- Background Service Worker
📌 Chúng ta sẽ đi sâu ở Phần 3.
Hiệu năng & bảo mật
Hiệu năng
- Không query DOM liên tục
- Tránh
setInterval - Giới hạn
matches
Bảo mật
- Không inject HTML không kiểm soát
- Không đọc dữ liệu nhạy cảm
- Không phá logic trang
Debug Content Script
Xem log:
- Mở DevTools → tab Console của trang web
- Không phải console của extension
Reload extension:
chrome://extensions- Click Reload
Các lỗi thường gặp
| Lỗi | Nguyên nhân |
|---|---|
| Script không chạy | Sai matches |
| DOM null | Sai run_at |
| Inject nhiều lần | Không check id |
| Không thấy log | Mở sai DevTools |
Tóm tắt kiến thức cốt lõi
- Content Script là trung tâm
matches+run_atquyết định hành vi- Luôn kiểm soát phạm vi & inject
- SPA cần xử lý DOM động
