Building a simple Google Chrome extension with Vue

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

This is great, was looking for this, thank you!

πŸ‘οΈŽ︎ 6 πŸ‘€οΈŽ︎ u/santolaz πŸ“…οΈŽ︎ Feb 07 2021 πŸ—«︎ replies

Dude. I can't tell you how long I've been wondering how on earth to do this.

Already following you on twitter - and have checked out a few of your other projects (off the top of my head, the static site generator) - just want to say, you're doing a great job, and I love the content you are pushing out.

πŸ‘οΈŽ︎ 6 πŸ‘€οΈŽ︎ u/hallindavid πŸ“…οΈŽ︎ Feb 07 2021 πŸ—«︎ replies

This video was great, for the most part everything was easy to follow and clear/concise.

I am wondering how you might be able to take full[er] advantage of VueJS, including using some of its extension libraries (like Vuex), and or visual/component libraries (Vuetify, etc).

Are there aspects of deeper VueJS that make it untenable for a Chrome extension?

πŸ‘οΈŽ︎ 3 πŸ‘€οΈŽ︎ u/pfs3w πŸ“…οΈŽ︎ Feb 07 2021 πŸ—«︎ replies

This was simply FANTASTIC! New sub for you, good sir

πŸ‘οΈŽ︎ 2 πŸ‘€οΈŽ︎ u/ThatChocolateGuy πŸ“…οΈŽ︎ Feb 08 2021 πŸ—«︎ replies

I haven’t watched yet but totally saved this for later. It’s right up my alley! Thanks for sharing!

πŸ‘οΈŽ︎ 1 πŸ‘€οΈŽ︎ u/Electrohead614 πŸ“…οΈŽ︎ Feb 07 2021 πŸ—«︎ replies

Nice video, will you be doing any pure VueJS tutes in the future?

πŸ‘οΈŽ︎ 1 πŸ‘€οΈŽ︎ u/F14D πŸ“…οΈŽ︎ Feb 08 2021 πŸ—«︎ replies

This is great. Saved it! I've been wanting to make an extension using Vue :) Thanks

πŸ‘οΈŽ︎ 1 πŸ‘€οΈŽ︎ u/TimV55 πŸ“…οΈŽ︎ Feb 08 2021 πŸ—«︎ replies
Captions
hey everyone andrew here this video will be relatively quick and simple i'll be showing off how to build a google chrome extension from scratch using vue to provide interactivity with chrome's extension api the extension in question will be used to block a list of websites whenever a toggle has been turned on let's dive right in first things first what do we need to create an extension well at an absolute bare minimum we need a file called manifest.json i have one right here in a local directory so let's open it up this file provides all of the metadata for our extension as well as the permissions and scripts that it requires to install and run on a browser adding in a name property we can title our extension this will show up in both the extensions window and the chrome web store a version property containing the current version of your extension a description describing what your extension does and finally manifest underscore version set to 2 the current requirement for new chrome extensions let's save this and head back to our browser on the extensions page check the developer mode option at the top right if it isn't already active this will display an additional header with a few new options the one that we're going to use is load unpacked this expects a folder so let's navigate to the root directory where our new manifest.json file resides after hitting select you'll see your extension with the name version and description provided earlier appear in the list we can pin it to our toolbar up top but it doesn't really do anything we can click it but it just shows a context menu with a few generic options what we want is some kind of window to display where we can add in sites to block and toggle the active state of the extension heading back into manifest.json let's append some lines to this config file browser action and that's an object containing default popup with a value of popup.html let's create that file and open it up some pretty basic sample text should work for our testing purposes a title and a little body content okay that looks good after each change we make in order to pull this into the extension installed in our browser we just hit this refresh button so now if we click the extension next to the url bar we can see the pop-up with the html that we saved earlier the size of this pop-up window is dependent on the wrapper element that contains it so if we go back into the popup.html file and pull all of this into a div and specify the width to say 480 pixels when we go back refresh and open the popup again we can see that it's set to 480 pixels wide okay so now that we know about the basics of displaying html in a pop-up let's expand on this a little bit i'm going to scaffold out a basic layout for our site blocking extension the title isn't really necessary here but i'll add it in anyway and we'll be styling this pop-up with a style sheet called popup.css under the css directory we have our wrapper div add in a title some buttons an area to hold the site's block list and finally a button to save the list of sites saving this and refreshing our extension we can see what that looks like now and it's not bad but it's unstyled so let's fix that let's create a directory called assets sas and inside of it will be a single file popup.scss i'm going to take a shortcut here and just paste in a bunch of styles that work well with the markup that we've added earlier now this being a sas file we need to compile this into plain css i'm going to be using laravel mix for this so we'll need a package.json file at our project root in order to get started with that it's a private project and for our scripts used i'm just pulling in from the main larval mix example using the terminal i'm going to install and save laravel mix sas and some other supporting packages as well okay that finished up nicely so the next thing we need to do is create our webpack config file webpack.mix.js let mix equals require larvalmix set the public path to our current directory and compile our pop-up sas file to a disk css directory we'll also add in this process css urls option as false this helps prevent font or image files from being added automatically i don't think we have any with this project but i like adding this in whenever i use mix with sas so now we just have to run npm run dev in the terminal all right once that's done we have to go back and update the stylesheet path in our popup.html file since we ended up exporting our css to a disk directory i'll show you why i chose to do this if we go back and refresh our extension again we are met with an error clicking it we are alerted to the fact that our extension contains a key file found in the node modules directory added when we ran npm install and if we go back and look at the details of our extension the size has ballooned to over a hundred megabytes this is because we are including that entire node modules directory in our extension when we don't need to at all we just need to include the compiled assets manifest json file and pop-up html so let's uninstall this extension go back to our project in the ide move our popup.html file and manifest.json file into the disk directory and adjust the source of the style sheet removing the disk directory this will be the point of entry for our extension instead of the entire project root going back into chrome and clicking load unpack let's choose our disk directory now we don't see the errors anymore our plugin size has been reduced to under a megabyte and our styled pop-up html is looking perfect okay so now that we have a style pop-up displaying we need to actually add some functionality to it if we open back up our manifest.json file under the description we'll add a new attribute called background this can contain a few different attributes nested in it but we're going to focus solely on scripts and include a single one called background.js what this does is pretty self-explanatory telling the extension what javascript should be ran in the background whenever the extension is active and installed on the browser we also need a few permissions to use this extension properly storage web requests web request blocking and wild cards of every insecure and secure site that the user visits after that's added let's create that background.js file in assets.js there's a few things that we need to do in here mostly with chrome's built-in events that we can hook event listeners into whenever the extension is installed for the first time we should set some default values like the active state and the list of sites that are blocked chrome runtime on installed add listener and for the invoked function we're going to use chrome storage sync set passing in an object consisting of the two properties that we're going to use throughout our extension toggle sites active a boolean by default will be set to false and toggle sites list a string by default set to just example.com set is an asynchronous function meaning that it expects a callback as the second parameter which contains either an error or the storage items that were set i'm not really keen on doing anything with either of those so for this example we're just going to return back an empty function as a note we're also using chrome storage sync here which means that any values that we set are available across all browsers signed into the same user account for that extension the alternative to this is chrome storage local which sets those values only on a single browser after that's set up we'll have to do something a little hacky in order to pull in the values that we want to our extension without any hiccups i'll explain why as i go first we're setting some variables here with the same name and values as the ones that we set in our uninstalled listener next we're using the chrome storage sync get method to pull in an array of values from the storage api again we're using the same names as the ones we've been referencing toggle sites active and toggle sites list just like the set method uninstalled this is an asynchronous function and the second parameter is a callback with the result set from the browser storage after this resolves we're replacing the global scoped variables with the results from the browser storage result dot toggle sites active and result.toggle sites list so the reason that we did this is because of the fact that storage sync get is an asynchronous function it doesn't block the script processing and instead waits in the background for resolve but our extension needs some values to start with otherwise we'd be met with errors on our extension screen or in our extensions console log even though the lag here is less than a second this is a workaround to prevent any undefined variables from making their way through so now that we have both our active state and a list of sites we need to write the functionality to block those sites if our extension is active for that we're going to use a listener on chrome web request on before request which will expect a callback with a details object containing information about the request first we're going to check if our extension is active through the toggle site's active bullion if it's not we're going to return early an object with a single property cancel set to false this tells chrome to continue with the request just like normal moving on the extension is deemed active at this point so we'll have to go through the list of sites we've set and block the request if the url being requested is in that list for that we just need a few vanilla javascript methods chained together let cancel equal toggle sites list split by a new line into an array and then sum some expects a callback function with the only parameter being a single item in that array for each item we're going to generate a new url object from the details web request object's url property and then return a boolean value if that url's hostname contains the single item from our sum filter of the toggle sites list sum is an array method in javascript that either returns true or false returning true if any of the items in the array pass the filter provided by the callback function so in this case if any of our toggle sites list websites added in through our extension match up with the url of the incoming request that cancel variable is going to be true and so now all we need to do is return back the same object we used earlier cancel and then true or false depending on the value of that sum method after that the on before request listener expects two more parameters a filter object to determine what urls will be listened to in our case we're setting that to all urls and then lastly an array containing event type information which for our extension will just use the string blocking okay that's the whole functionality to block a site depending on our extension's active state and list of websites the last thing we need to add to our background script is a listener for the chrome storage unchanged event anytime that either of our storage items are updated we need to update those global scope variables that determine whether or not a site is blocked this listener expects a callback function containing changes and namespace parameters we are only going to continue if the namespace is sync since that's the method we're using if the changes object contains a toggle site's active item then that toggle site's active variable is now equal to changes toggle sites active new value which is the change that was made to trigger this event and we're doing the exact same thing for toggle sites list okay that's it let's add this script to our webpack flow compiling it to a dist js folder and running npm rundev to start that compilation now if we go back to our extension screen in chrome and refresh we can see that well nothing is displaying or happening in our extension that's expected though we don't have any front-end functionality tied to our pop-up html yet but if we click this background page link in the extension description a chrome dev tools window opens up that lets us monitor and work on background pages or scripts so if we run chrome storage sync get here and output the results to our console we can see that our toggle site's active item is set to false and toggle site's list is set to just example.com our defaults let's see if our work so far paid off we can run chrome storage sync set and set the toggle site's active value to true and we can verify that by running the same get method that we just did so this should mean that if we visit example.com perfect it's blocked by an extension that means that everything we've programmed into our background.js file is working as expected and if we run storage sync get passing in toggle sites active as false refreshing this site it pulls up as expected so now we have to get our pop-up tied to these values and let it update them using view opening up our popup.html file let's cut out this whole wrapper element and put in a div with an app id in its place after that a script element pointing to js popup.js let's create that script under assets js and open it up this is where our view app initialization is going to happen so let's get started with import view from view but wait we haven't installed that yet let's open up a terminal window and do npm install save dev view okay that's good and we'll need to import a single root component for our front end i'm thinking pop-up from the current assets js directory components popup.view let's create that component now and paste in all the markup that we used to have in popup.html back to popup.js const app equals new view el is our app element in popup.html and we'll use render passing in our pop-up component to the create element method we'll need to add this file to our webpack flow so a new js call to popup.js and output to dist js we'll also need to tack on this view method here i'm not 100 sure why it might be something new with laravel mix outside of laravel projects but it errors out without it so now let's head back to our popup.view component and start adding some functionality to it first let's create a data object that will hold our active state and our url list both of these will have the same defaults that we used in the background.js script but we'll quickly overwrite these in the created method of our component we're going to call chrome storage sync get just like we did to generate the global variables earlier we want toggle sites active and toggle sites list and in the callback we're going to replace our data elements with the values from those two storage items just a quick note even though we are in view we can use the chrome api extension in full since this script is running inside of an extension window we'll also create two methods one for setting the state of our extension and one for saving our list of urls for the state we'll call it set active and expect a boolean passed in we'll set our active data state to the boolean and then call chrome storage sync set setting the toggle site's active value as the boolean passed in for the next method we'll call it save lists this is going to call chrome storage sync set as well updating the toggle sites list item to the value of the list data object both of these are going to ignore the callback functions returning void to tie in these methods let's update our markup a little bit we'll need to add click handlers to the active state buttons passing in set active false for the off one and set active true for the on one for the text area that holds our urls it's going to use v model and be attached to our list data object and the save button will have a click handler as well firing off the save list method for the buttons in order to tell what state the extension is in we'll use this is active class i've created to highlight it for the off button we'll set the is active class on if the active state is false and for the on button if the active state is true okay this looks great so let's compile our assets with npm rundev and check it out going back to chrome and refreshing our extension let's open it up we can see immediately that our view component is working the off state is being highlighted and the example.com default url is showing in our site list if we click on here our state changes and the extension should be active so let's test that example.com and it's blocked if we open up our extension and click off refreshing the site it's not perfect everything is working as expected and our view component is tying into the chrome extension api let's open up our extension and try adding in some more sites to make sure this is working hitting save and turning the extension on if we navigate to one of the sites we block the requests to them are being stopped and if we remove a site it's showing up just as it should before we go let's add in a visual element to our extension which will help the user know immediately if it's active or not first we have to create an icon set in the manifest.json file we can use this icons object which expects a few different sizes 16 48 and 128 pixels wide i've added in these sample icons that i made to an images folder in our assets directory there's also an off state for the 48 pixel image and i'll show you how to use that shortly let's add these paths to our icons object in the manifest.json file and add copying the images from the assets to the disk directory in our webpack flow after running npm run dev if we go back to chrome and refresh our extension we can see that it now has an icon both on the extension page and in the toolbar up top but that icon doesn't update whenever this state is active or inactive which is what i'd like to do in order to quickly show a user whether or not the extension is active if we head into our view component this is an easy addition at the bottom of our set active method we can call chrome browser action set icon this expects an object consisting of a path to the icon that we want to use in our case that's going to be that 48 by 48 off image that i referenced a little earlier but this path needs to be dynamic and update depending on the active state so instead let's create a new data object called icons active will point to the plain 48x48 icon and inactive to the off icon now in the set icon method we can update the path to the icon's object and determine the property value based on if the active flag is set to true or false running npm rundev to compile our changes and we're good to go before we test this out let's head back to our manifest.json file real quick by default we've set the active state of the extension to false and so we should display the off icon instead of the normal one under the browser action object we can set a new property called default icon and pass in that off 48 by 48 icon path all right let's go back to chrome refresh our extension and test it out we can see immediately that our icon is in the off position by default and if we open up the extension and click the on button our icon updates to reflect that change with everything else working just as intended alright that's about it for this video you've learned how to create a basic google chrome extension from scratch use view to provide interactivity to a pop-up element attached to that extension and call chrome api methods from a view component huge thanks to my github sponsors youtube elite members and everyone else who continues to support these videos as always if you have any questions about this or any other web development topics please feel free to reach out to me in the comments or on my twitter linked below thanks for watching
Info
Channel: Andrew Schmelyun
Views: 26,718
Rating: undefined out of 5
Keywords: vue, vue.js, vue tutorials, web development, web development tutorials, web dev, web dev tutorial, javascript, chrome extensions, google chrome extensions, chrome extension tutorial, javascript tutorial
Id: kYl271X2LNA
Channel Id: undefined
Length: 24min 27sec (1467 seconds)
Published: Sun Feb 07 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.