Buat ekstensi Chrome menggunakan Angular
Tutorial ini didasarkan pada manifes ekstensi chrome versi 3 (MV3) dan juga, Angular versi 2+ (2, 3, dan …). Jika Anda belum menggunakan manifes versi 3, Anda dapat mengikuti tutorial ini untuk bermigrasi dari manifes V2 ke V3.
Di akhir artikel ini, Anda akan dapat mendemonstrasikan aplikasi Angular Anda di dalam popup ekstensi chrome atau dialog (dengan menggunakan iframe yang diluncurkan oleh file skrip konten ekstensi chrome).
Konfigurasi aplikasi sudut
Pertama, buat dan kembangkan aplikasi Angular yang Anda inginkan sesuai keinginan. Artinya, saat Anda mengembangkan aplikasi Angular, jangan memikirkan konfigurasi apa pun yang terkait dengan ekstensi chrome dan kembangkan aplikasi Anda seperti biasa.
Setelah menyelesaikan pengembangan aplikasi Angular Anda, Anda hanya memerlukan 2 perubahan untuk menyiapkan aplikasi Angular Anda untuk diterapkan di dalam ekstensi chrome.
- Ubah "base href" aplikasi di dalam aplikasi Angular index.html.
<base href="/app/index.html">
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Application Title</title>
<!-- <base href="/" /> --> // Remove this
<base href="/app/index.html"> // Use this instead of the above line
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="favicon.ico" />
</head>
<body>
<app-root></app-root>
</body>
</html>
useHash: true
RouterModule.forRoot(routes, { useHash: true })
ng build --prod
Langkah selanjutnya akan menunjukkan kepada kita bagaimana menggunakan aplikasi Angular di dalam ekstensi chrome.
Konfigurasi ekstensi Chrome
Pertama-tama, Perlu dicatat bahwa tutorial ini didasarkan pada manifes ekstensi chrome versi 3 (MV3).
Di mana kami ingin mendemonstrasikan aplikasi Angular kami di ekstensi chrome kami? Munculan ekstensi Chrome atau dialog (menggunakan iframe)?
Untuk pemahaman yang lebih baik, lihat gambar di bawah yang pertama terkait dengan aplikasi Angular di dalam popup ekstensi chrome dan yang kedua terkait dengan aplikasi Angular di dalam iframe ekstensi chrome.
Sekarang, mari kita jelaskan masing-masing langkah demi langkah.
Gunakan popup ekstensi chrome untuk menampilkan aplikasi Angular
- Buat folder di bawah direktori root proyek ekstensi chrome dan beri nama app , lalu, salin dan tempel file build aplikasi Angular Anda dari folder dist di dalamnya. Perhatikan bahwa untuk menempelkan hanya konten folder dist aplikasi Angular .
Lihat struktur direktori proyek di bawah ini.
Sample Extension Project Directory
-- app
- index.html
.
.
.
-- assets
- cancel.png
- icon.png
-- popup
- popup.js
- popup.html
- popup.css
-- background.js
-- content_script.js
-- manifest.json
"manifest_version": 3,
"name": "Angular App",
"version": "1.0.1",
.
.
.
"action": {
"default_icon": "assets/icon.png",
"default_title": "Angular App",
"default_popup": "app/index.html" // Please, look at the path carefully!
},
.
.
.
"web_accessible_resources": [
{
"resources": [
"app/index.html"
.
.
.
]
}
]
Dalam pendekatan ini, kita akan membuat iframe di dalam file skrip konten ekstensi chrome dan kemudian menambahkan aplikasi Angular kita ke iframe ini untuk melihat aplikasi kita di dalam dialog(modal) di layar.
Untuk mengimplementasikan ini, saya lebih suka membuat fungsi untuk membuka dan menutup dialog(modal) dengan id unik. Jadi, dengan fungsi ini, Anda dapat membuat dan menampilkan dialog sebanyak yang Anda inginkan satu sama lain dan masing-masing memiliki id unik.
- Buat fungsi openDialog() di dalam file content_script.js . Fungsi ini akan mendapatkan 3 argumen:
- id : ID unik dari dialog.
- options : Opsi khusus yang ingin Anda atur pada dialog.
- contentPath : Jalur rute aplikasi Angular awal yang ingin ditampilkan segera setelah membuka dialog. Perhatikan bahwa untuk menulis rute aplikasi Angular awal setelah jalur direktori aplikasi Angular di dalam proyek ekstensi chrome. Misalnya, jika file build aplikasi Angular (isi folder dist) berada di bawah folder app di dalam direktori root ekstensi chrome, maka contentPath akan terlihat seperti ini: “app/index.html#/” . Atau, jika Anda ingin membuka rute tertentu dari aplikasi Angular (misalnya /store), maka contentPath dari "/store" ( jalur rute Angular akan ditampilkan di dalam dialog) akan terlihat seperti ini: "app/index. html#/toko” .
- id : ID unik dari dialog yang akan ditutup.
const preModalContainerId = '_container-';
function openDialog(id, options, contentPath) {
// First load dialog html file
getHtmlContent(contentPath).then(modalHtmlContent => {
// Create dialog overlay (a black layer behind the dialog body)
const overlayElem = document.createElement("div");
overlayElem.classList.add('myext-modal-overlay');
overlayElem.setAttribute("id", id);
// Create an iframe for showing dialog body (in Chrome extension the dialog should be used with iframe)
const iframeElement = document.createElement("iframe");
// Check if options has iframe class name for styling
if (options?.iframe?.className) {
iframeElement.classList.add(options.iframe.className);
} else {
iframeElement.setAttribute("style", "width: 100%; height: 100%;");
}
// Assign src for iframe to show Angular app
iframeElement.src = chrome.runtime.getURL(contentPath);
// If overlay has cancel button then prepare to clear iframe from screen by click on cancel icon
if (options?.overlay?.hasCancelBtn) {
const cancelButton = document.createElement("span");
// if options has cancel button class name for styling
if (options?.overlay?.cancelBtnImage) {
cancelButton.style.backgroundImage = 'url(' + getAssetImgPath(options.overlay.cancelBtnImage) + ')';
} else {
cancelButton.innerText = '+';
}
// if options has cancel button class name for styling
if (options?.overlay?.cancelBtnClassName) {
cancelButton.classList.add(options.overlay.cancelBtnClassName);
} else {
cancelButton.classList.add('myext-modal-overlay-cancel-btn');
}
overlayElem.appendChild(cancelButton);
jq(cancelButton).click(() => {
closeDialog(id);
});
}
// Set iframe as dialog overlay child
overlayElem.appendChild(iframeElement);
// Dialog body container
const modalBodyContainerId = preModalContainerId + id;
const modalBodyContainer = document.createElement("div");
modalBodyContainer.classList.add('myext-modal-container');
modalBodyContainer.setAttribute("id", modalBodyContainerId);
// Add dialog html file content to dialog body container
modalBodyContainer.innerHTML = modalHtmlContent;
document.body.appendChild(overlayElem);
document.body.appendChild(modalBodyContainer);
});
}
function getAssetImgPath(assetPath) {
return chrome.runtime.getURL(assetPath);
}
async function getHtmlContent(htmlFileUrl) {
let fileUrl;
// Check if html file url is decoded or not
if (htmlFileUrl.includes('chrome-extension://')) {
fileUrl = htmlFileUrl;
} else {
fileUrl = chrome.runtime.getURL(htmlFileUrl);
}
return await (await fetch(fileUrl)).text();
}
function closeDialog(id) {
const overlayElem = document.getElementById(id);
const modalBodyContainerId = preModalContainerId + id;
const modalBodyContainer = document.getElementById(modalBodyContainerId);
if (overlayElem) overlayElem.remove();
if (modalBodyContainer) modalBodyContainer.remove();
}
.myext-modal-overlay {
display: inline-block;
position: fixed;
width: 100%;
height: 100%;
left: 0;
top: 0;
background: rgba(51, 51, 51, 0.7);
z-index: 1000000;
}
.myext-modal-overlay-cancel-btn {
position: absolute;
width: 50px;
height: 50px;
left: 50px;
top: 50px;
font-size: 2.5em;
color: white;
background-color: #c57070;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
transform: rotate(45deg);
cursor: pointer;
z-index: 1001;
transition: all 0.25s ease-in-out;
}
.myext-modal-overlay-cancel-btn:hover {
background-color: #b06565;
box-shadow: 0 2px 10px #666;
}
.myext-modal-container {
display: block;
position: fixed;
border-radius: 18px;
overflow: hidden;
box-shadow: 0 2px 50px #444;
background: #1d222f;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 2001;
}
.myext-iframe {
position: fixed;
border-radius: 35px;
overflow: hidden;
box-shadow: 0 2px 50px #444;
top: 50px;
right: 50px;
height: 630px;
width: 390px;
}
.myext-modal-overlay-custom-cancel-btn {
position: absolute;
width: 50px;
height: 50px;
top: 35px;
right: 35px;
border-radius: 50%;
background-repeat: no-repeat;
object-fit: cover;
background-size: cover;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
z-index: 1001;
transition: all 0.25s ease-in-out;
}
.myext-modal-overlay-custom-cancel-btn:hover {
box-shadow: 0 2px 10px #666;
}
"manifest_version": 3,
"name": "Angular App",
"version": "1.0.1",
.
.
.
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": [
"content_script.js",
],
"css": [
"style.css"
],
"run_at": "document_end",
"all_frames": false
}
],
"action": {
"default_icon": "assets/icon.png",
"default_title": "Angular App",
"default_popup": "app/index.html" // Please, look at the path carefully!
},
.
.
.
"web_accessible_resources": [
{
"resources": [
"app/index.html"
"style.css",
.
.
.
],
"matches": [
"<all_urls>"
]
}
]
const dialogOptions = {
iframe: {
className: 'myext-iframe'
},
overlay: {
hasCancelBtn: true,
cancelBtnClassName: 'myext-modal-overlay-custom-cancel-btn',
cancelBtnImage: 'assets/images/cancel-btn.png'
}
}
openDialog('example-id', dialogOptions, 'app/index.html#/');
closeDialog('example-id');
Terima kasih banyak telah membaca artikel ini.

![Apa itu Linked List? [Bagian 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































