Tự tạo Chrome Extension cho riêng mình
Công việc nào cũng vậy, sau một thời gian chúng ta sẽ tự nhận thấy có những thứ cứ lặp đi lặp lại hàng ngày. Mình cũng vậy, công việc của mình được thực hiện rất nhiều trên Google Chrome và sẽ thật hữu ích nếu như chúng ta có riêng cho một extension để tự động những công việc lặp đi lặp lại nhàm chán ấy, cũng là một cách để tiết kiệm thời gian và hơn thế nữa là nhìn có vẻ chuyên nghiệp hơn rất nhiều. Bạn có thể trèn thêm các chức năng khác cho một trang web mà bạn sử dụng nó thường xuyên, lấy dữ liệu, lưu trữ...và nhiều thứ hay ho khác nữa bạn có thể làm với một extension.
Cấu trúc của một Chrome Extension
Về cơ bản, một Chrome Extension chủ yếu sẽ được viết bằng Javascript và HTML. Bạn có thể tổ chức các thư mục tùy ý sao cho phù hợp và tiện lợi nhất trong quá trình code. Với mình thì sẽ như thế này: Dưới đây, chúng ta sẽ đi sâu vào bên trong để tìm hiểu chức năng của từng file
Chức năng của các thành phần
1. manifest.json
Đây là file config cho extension của chúng ta. Nó chứa thông tin cơ bản về extension, các file sẽ được chạy, inject...
{
"name": "Nhaccuatui Extension",
"version": "0.0.1",
"manifest_version": 2,
"description" : "Extension for Nhaccuatui",
"icons": {
"16": "images/icon.png",
"48": "images/icon.png"
},
"browser_action": {
"default_icon": {
"19": "images/icon.png",
"38": "images/icon.png"
},
"default_title": "Nhaccuatui Extension",
"default_popup": "popup.html"
},
"background": {
"page": "background.html",
"persistent": false
},
"content_scripts": [
{
"matches": [
"*://nhaccuatui.com/bai-hat/*",
],
"js": [
"scripts/content.js",
],
"css": [
"styles/font.css",
"styles/main.css"
],
"run_at": "document_idle"
}
],
"permissions": [
"clipboardWrite",
"storage"
]
}
name
: Là thuộc tính xác định tên extension của bạnversion
: Phiên bản hiện tại, Chrome sẽ dựa vào đây để xác định xem extension của bạn có bản cập nhật mới hay khôngmanifest_version
: Xác định phiên bản của chính file manifest.jsondescription
: Miêu tả chi tiết hơn về extensionicons
: Icon của extension sẽ được hiển thị trên store. Trong trường hợp này, mình để chúng trong thư mục imagesbrowser_action
:default_icon
: Icon sẽ được sử dụng để hiển thị trên trình duyệtdefault_title
: Title sẽ được hiển thị khi hover chuột vào icon của extensiondefault_popup
: Đây là file HTML sẽ được hiển thị khi bạn mở extension ra. Chúng ta sẽ nói rõ hơn về file này trong phần sau
background
:page
: Đây sẽ là trang chạy ngầm bên dưới và thường sẽ chỉ chứa một script tag để đưa file javascript vàopersistent
: Là flag có giá trị làtrue
hoặcfalse
. Xác định trang background sẽ được chạy như thế nào
content_scripts
:matches
: Xác định các trang web mà bạn muốn thêm các nội dung của mình vàojs
: Là danh sách các file javascript sẽ được inject vào các trang web đã được khai báo bên trêncss
: Tương tự như thuộc tínhjs
nhưng là danh sách các file cssrun_at
: Thời điểm inject các file content bên trên vào trang web
permissions
: Khai báo các quyền hạn truy cập cho extension
2. Content script
Đây là các thành phần được inject vào các trang web mà bạn khai báo ở thuộc tính matches
trong file manifest.json
. Các thành phần này được chạy cùng môi trường với trang web hiện tại nên bạn có thể sử dụng javascript, css để thao tác lên các thành phần DOM. Nhờ đó bạn có thể thay đổi giao diện trang, thêm các button, thêm các chức năng khác mà bạn muốn.
3. Popup page
Đây là trang sẽ chạy và hiển thị khi bạn mở extension của mình lên. Cấu trúc của nó cũng tương tự như những trang HTML khác. Trong trường hợp của mình thì đó trang popup.html
. Trang này được chạy ở một môi trường khác so với các content script. Có thể hiểu nôm na là chúng được chạy ở một cửa sổ trình duyệt khác so với cửa sổ trình duyệt hiện tại.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="./styles/lib/bootstrap.min.css">
<link rel="stylesheet" href="./styles/page.css">
<title>My Extension</title>
</head>
<body>
<div class="wrapper">
<h1>This is popup page</h1>
</div>
<script src="./scripts/lib/bootstrap.min.js"></script>
<script type="module" src="./scripts/popup.js"></script>
</body>
</html>
Bạn sẽ tạo giao diện chính cho extension của mình tại đây. Trang sẽ được load lại mỗi khi extension được mở.
Bạn có thể sử dụng localStorage
để lưu trữ dữ liệu giống như một database.
4. Background page
Cũng giống như trangpopup.html
, trang background.html
cũng sẽ chạy cùng một môi trường. Tuy nhiên nó không có giao diện mà đơn thuần chỉ chứa một script tag với mục đích đưa vào đó file background.js
.
<html>
<body>
<script type="module" src="./scripts/background.js"></script>
</body>
</html>
Mặc định trang này sẽ được tự động sinh ra và tự động inject file background.js
, nhưng trong trường hợp bạn muốn custom nó thì đây sẽ là nơi để bạn thực hiện điều đó
File background.js
được sử dụng với mục đích tương tự như một server, nó lắng nghe các sự kiện được gọi từ trang popup hay trang content. Xử lý, lưu trữ dữ liệu cũng như là trả về data trong response.
Giao tiếp gữa các thành phần
Vừa rồi chúng ta đã phần nào hiểu được chức năng của các thành phần trong một extension. Như chúng ta đã biết, file content.js
được chạy cùng với trang web hiện tại mà nó được inject vào. Trong khi đó, popup.js
và background.js
được chạy ở cùng một môi trường và chúng tách biệt hoàn toàn so với của sổ hiện tại mà trình duyệt đang hiển thị. Vì thế, để có sự kết nối giữa các file script ở các môi trường khác nhau, Chrome sử dụng các message để thể hiện sự giao tiếp đó.
Chúng ta sẽ cùng nhau làm môt ví dụ để hiểu hơn vấn đề này nhé. Extension của chúng ta sẽ có chức năng là lưu lại các bài hát mà mình thích trên https://www.nhaccuatui.com/ để hàng ngày có thể nghe lại chúng mà không phải mất công tìm kiếm. Tất nhiên là thực tế thì trang nhạc nào cũng có chức năng tạo playlist rồi. Nào hãy cùng bắt đầu thôi.
content.js
Trong phần này, chúng ta sẽ xử lý việc chèn thêm vào trang một button mà khi click vào nó, chúng ta sẽ lấy dữ liệu ở trang hiện tại và gửi lên cho background.js
xử lý:
window.onload = function () {
var button = document.createElement('button');
button.innerHTML = 'Add to Playlist';
document.body.prepend(button);
button.addEventListener('click', function () {
var link = window.location.href;
var name = document.querySelector('.name_title').innerText;
chrome.extension.sendMessage({
type: 'add-song',
data: {link, name}
});
});
}
Để ý rằng, ở thuộc tính matches
trong manifest.json
, chúng ta có một giá trị là "*://nhaccuatui.com/bai-hat/*"
. Như vậy đoạn script trên sẽ chỉ được chạy ở trang mà bài hát đang được phát.
background.js
Vừa rồi ở content.js
chúng ta đã gửi một message đi. Vậy muốn background.js
nhận được thông điệp này thì chúng ta phải đăng ký cho nó lắng nghe những request được gửi đến
chrome.extension.onMessage.addListener(
function (request) {
switch(request.type) {
case 'add-song':
addSong(data);
break;
case 'remove-song':
break;
}
});
function addSong(data) {
var songs = getSongs();
songs.push(data);
localStorage.songs = JSON.stringify(songs)
}
function getSongs() {
if (!localStorage.songs) {
localStorage.songs = JSON.stringify([]);
}
return JSON.parse(localStorage.songs);
}
Khi nhận được message, chúng thực hiện lưu data vào trong localstorage
.
popup.js
Như đã thấy chúng ta sử dụng popup.js
trong trang popup.html
do đó tại đây chúng ta sẽ xử lý ở popup.js
để hiển thị danh sách các bài hát đã được lưu.
$(document).ready(function () {
var songs = JSON.parse(localStorage.songs || '[]');
var songHTML = null;
songs.forEach(song => {
songHTML = $(`<a href="${song.link}" target="_blank">${song.name}</a>`);
$('.wrapper').append(songHTML);
})
});
Như vậy, mỗi lần extension được mở ra, chúng ta sẽ thấy danh sách các bài hát mà mình đã lưu được hiển thị ra ở đây. Bạn có thể thêm các tính năng khác nữa như tự động phát các bài hát trong danh sách, hay download tất cả chúng về máy của mình.
Load extension
- Các bạn vào google chrome, gõ vào địa chỉ
chrome://extensions/
- Click vào nut
Load unpacked
bên góc trái màn hình - Tìm đến folder chứa extension của chúng ta, thế là xong
Conclusion
Vừa rồi chúng ta đã tìm hiểu về các thành phần của một chrome extension cũng như các chức năng và sự giao tiếp giữa chúng. Hi vọng với những chia sẻ đó, các bạn sẽ phần nào hiểu hơn về cấu trúc của một extension để có thể tự tạo riêng cho mình một extension, phục vụ các nhu cầu của bản thân.
All rights reserved