Building a web extension with Vue at speed of light
10 min read
November 6, 2019
In this 10 min read tutorial you'll learn how to build a production ready web extension made with Vue that works cross-browser.
Getting started with the creation of a web extension using VueJs.
What is a web extension?
At Chrome's official document you can see more info on what they are and what you can do with them.
Generating our Web Extension
We are going to use the great tool vue-web-extension by @HugoAlliaume. We only need to have the Vue CLI installed. If you have always used Vue through the CDN distribution, then you need to install it by running:
Please check Vue CLI installation guide for more info.
Once you have successfully installed Vue CLI, please execute:
The previous command will drive you through the creation of our web extension. In the process, you
will be asked a few questions such as project name, libraries we want to use, license, etc. They are there to make your life easier and reduce the boilerplate in the initial version of your web extension. So don't worry about it!
::: tip Keep it simply If you are not 100% sure about adding a dependency or not, I recommend keeping it simple. You can always opt to add it manually later. :::
For simplicity, and in the context of this tutorial I set the following values:
Now that we have the web extension skeleton, it's time to build the extension. Simply run:
At this point, you should have compiled the extension successfully (in the terminal should be many indicators of that, such as
no errors displayed or
Built at: MM/DD/YYYY message). If that's the case, you should be able to see a new folder
dist in the root path. It contains the compiled version of
my-extension. Yay! :confetti_ball:
Let's run our extension locally
First of all, we need to enable the
developer mode. In order to do that, open Chrome browser and type
chrome://extensions in the search bar. Right after that, you will be able to see several cards for each extension you have installed before. What you need to do now is just to turn the switch
Developer mode on. Look at the top-right corner as shown in the following image to find it.
Now, we need to add our extension
my-extension to Chrome. Remember we have our distribution under the recently created
dist folder, so what you need to do is look for the button
Load unpacked at the top-left and select the
dist folder found in the root's path of your extension. After that, you should be able to see it listed within the rest of your extensions.
::: tip Hot Reloading
Once you have loaded the extension pack,
vue-web-extension allows you to keep watching for new changes and hot reload the extension. To make use of this, you simply need to run
npm run watch:dev.
Voilá 🎩 ... Our extension is there :tada:
Go ahead, click on the extension's icon next to the search bar and see what happens...
Understanding the extension structure
Let's start by taking a look at our extension's tree:
What do we have?
The manifest.json file contains important information about your extension such as its name, permissions, icons, etc.
A content script is no more than a "Js file that runs in the context of web pages." Basically, the content script will give you the possibility of interacting with web pages that you visit while using the browser. Yes, it has access to all pages you have open in the browser :scream:. Not bad 😏
To inject the content script, we need to tell the
manifest.json which is the file and when to add it.
With the option
matches you can explicitly tell the browser in which pages that you visit the
content.js should be injected. For more matching patterns visit: match_patterns.
::: tip Customizing the extension Suppose we want to display something in the current page once the user interacts with the popup. We need to communicate the popup with the actual web page. :::
In our content script we'd like to listen for events from the pop-up so let's add:
::: warning Telling webpack to add the content.js & Re-build the extension!
In order to make our web-extension use the
content.js file, we need to tell webpack to add it to the build. You need to add
content: "./content.js", to the entry key under the config in your
webpack.config.js. After doing that, you need to ensure that the build contains it. Stop any process for building your extension and make sure you start it again. For example re-run:
npm run watch:dev.
Check the new output on console and make sure you have the
content.js in there. That's it!
icons & browser actions
As you may have seen, by default,
my-extension has a puzzle piece (thanks to the amazing library we used). If you want to change it you must modify the
manifest.json. There you will see two settings for
icon_128.png respectively, simply replace those images by your custom images. That icon doesn't come alone, they are also what we call
browser actions. Through it, you can display a tooltip, a badge or a popup. 🤔
For example, in our default setting we are defining the icons, but also the title (try it yourself by posing the mouse over the extension's icon for a few secs) as well as the popup page (click the icon to open it). Our manifest looks something like this:
Still confused? 🙄 I invite you to take a look at the official Chrome's browser action documentation.
The background script, compared to the
content script, it has full access to the browser API but can't access the current page as the content script can. So it will happen that you depend on both scripts if you want to do really useful things with your web extension. Also you will need to communicate them in order to pass the information around. We will see that in a minute.
A practical example of a background script would be listening to clicks, for example when there is a new tab opened.
The same way you did with the content script, you'll need to explicitly tell the browser who is your background file by doing:
We are not going to do anything with
background.js in this example, but if you are curious about it, please check a web extension we have built in the past: whosnext vue web extension.
As we said before, content script and background script have some limitations when it comes to communicating or getting data. They run in different contexts and they have access to different information. This forces us to communicate and pass information through messages. The same happens between the
popup and the
Let's check how a web extension communicates the different parts of it:
One more time, I suggest you consider the official messaging documentation if you want to understand it in more details.
In the context of this web extension, we need to send messages to our content script each time the user interacts with the popup. Why? Because we want to make changes to the current page. So we will catch those messages coming from the popup and do some crazy stuff on our page.
Let's add the following code to the
At this point your web extension should look like this:
If you want to check how the whole project looks like, please visit web extension example on Github. You can also check a more complete web extension we made in vue at whosnext repo.
::: warning WebExtension polyfill In this post I used only Chrome's documentation as reference because it's really comfortable reading through it and for making the tutorial simpler, however, be aware that the extension is built using webextension-polyfill which means your extension is supported in Chrome, Firefox & Opera. :::