After following a tutorial on creating a Chrome extension with Vue.js, I successfully implemented a Vue.js based extension. Now, my goal is to pass the URL of an active tab from a background script to the popup page.
I added console.log statements in the onMessage and onClicked events in background.js, but these listeners seem not to be receiving any data. Strangely, the onInstalled listener is working perfectly.
Given that I'm relatively new to both Vue.js and browser extensions, I'm feeling a bit lost here. Could you assist me in identifying what might be missing or incorrect in my code?
manifest.json
{
"manifest_version": 3,
"name": "Random Quote",
"version": "1.0.0",
"description": "Browser extension that fetches a random quote from zenquotes.io",
"host_permissions": ["https://zenquotes.io/"],
"permissions": ["activeTab", "scripting"],
"action": {
"default_popup": "popup.html",
"default_icon": {
"16": "images/icon-16x16.png",
"48": "images/icon-48x48.png",
"192": "images/icon-128x128.png"
}
},
"background": {
"service_worker": "js/background.js"
}
}
background.js
chrome.runtime.onMessage.addListener(function () {
console.log("onMessage.addListener");
});
chrome.action.onClicked.addListener(function (tab) {
console.log("onClicked.addListener");
});
chrome.runtime.onInstalled.addListener(() => {
console.log('Hello, World!');
});
popup.html
<!DOCTYPE html>
<html lang="en_US">
<head>
<title>Random Quote</title>
<link rel="stylesheet" type="text/css" href="css/popup.css" />
<meta charset="UTF-8">
</head>
<body>
<div id="app"></div>
<script src="js/popup.js"></script>
</body>
</html>
popup.vue
<template>
<div class="container">
<h1 class="title text-center">Random Quote</h1>
<blockquote class="quote-card">
<p>
{{ state.quote }}
</p>
<cite> {{ state.author }} </cite>
</blockquote>
<blockquote class="quote-card">
here show URL of the current Tab
</blockquote>
</div>
</template>
<script>
export default {
data() {
return {
state: {
quote: "",
author: "",
},
};
},
async created() {
try {
const response = await fetch("https://zenquotes.io/api/random");
const data = await response.json();
if (Array.isArray(data) && data.length > 0) {
this.state.quote = data[0].q; // Extract the quote from the response
this.state.author = data[0].a;
} else {
this.state.quote = "Failed to fetch quote.";
}
} catch (error) {
console.error(error);
this.state.quote = "Error occurred while fetching quote.";
}
},
};
</script>
popup.js
import { createApp } from "vue";
import Popup from "./Popup.vue";
console.log("popup.js - 1");
createApp(Popup).mount("#app");
console.log("popup.js - 2");
webpack.mix.js
let mix = require("laravel-mix");
mix
.setPublicPath("./")
.sass("src/sass/popup.scss", "dist/css")
.js("src/js/popup.js","dist/js")
.js("src/js/background.js","dist/js")
.vue()
.copy("src/images/", "dist/images")
.options({
processCssUrls: false,
});
mix-manifest.json
{
"/dist/js/popup.js": "/dist/js/popup.js",
"/dist/js/background.js": "/dist/js/background.js",
"/dist/css/popup.css": "/dist/css/popup.css",
"/dist/images/icon-128x128.png": "/dist/images/icon-128x128.png",
"/dist/images/icon-16x16.png": "/dist/images/icon-16x16.png",
"/dist/images/icon-48x48-off.png": "/dist/images/icon-48x48-off.png",
"/dist/images/icon-48x48.png": "/dist/images/icon-48x48.png"
}
package.json
{
"name": "randomquote",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --env=production --config=node_modules/laravel-mix/setup/webpack.config.js",
"prod": "npm run production"
},
"author": "",
"license": "ISC",
"dependencies": {
"cross-env": "^7.0.3",
"laravel-mix": "^6.0.49",
"postcss": "^8.4.33",
"sass": "^1.70.0",
"sass-loader": "^14.0.0",
"vue": "^3.4.15",
"vue-loader": "^17.4.2",
"vue-template-compiler": "^2.7.16"
}
}