Development
Phase2
July 23, 2014
...but you don't know where to start? Fear not! In this post I will guide you through the steps of putting together a Chrome extension from scratch, packaging it, and uploading it to the Webstore.
is a "scaffolding tool for modern web apps" which means it'll set you up with a nice little framework and some helpers for whatever you're building. Lucky for us, there's even a Yeoman generator for Chrome extensions so we can go ahead and install that. First things first, make sure you have NodeJS and npm installed. If you don't, you'll have to install them. Then you can install Yeoman like so:
$ npm install -g yo
Then you can install the Chrome extension generator for it:
$ npm install -g generator-chrome-extension
All set! Let's create a new project.
Firstly, create an empty directory for your project and open it up in a terminal. For the purposes of this tutorial, we'll say we're creating an extension named "Pupperator" which, I don't know, randomly adds puppies to the page or something. Sure.
$ mkdir ~/Code/pupperator
$ cd ~/Code/pupperator
Using Yeoman, you can now generate some boilerplate for your Chrome extension:
$ yo chrome-extension
Or, if you want to use Compass (and Sass), you can include the --compass flag:
$ yo chrome-extension --compass
This will prompt a series of questions:
After that, you'll see a bunch of "create" statements fly by which means that it's generating files for you, and then you'll see some things getting installed, and then the process should complete, meaning you're ready to develop.
Now that you have some code, you can go ahead and enable it in Chrome.
Before we buckle down and start coding, let's look at what Yeoman gave us. Your exact codebase will likely be slightly different based on what options you chose when generating it, but you should get the idea.
For most extensions, you can get by by only touching app/manifest.json as well as the CSS/JS/HTML files that exist in /app, but it's nice to have an understanding of the other files in case you want to configure things a bit.
Firstly, you'll want to fire up "grunt" using:
$ grunt debug
Doing so does a few very nice and very helpful things:
Now you're finally ready to write some code. The code that you right depends heavily on what you're trying to do. If you're doing some fancy stuff behind the scenes that doesn't need to inject as much code into individual pages, you'll probably be looking more at the background.js script (or a renamed version of it). Background scripts get a lot of power which is not available in content scripts, because they are treated more like first class citizens by Chrome's extensions API. Content scripts, for example, can't use the chrome.* API functions (take a moment to skim that link before moving on) that background scripts have access to. If you're mainly targeting a browser or page action button, you'll be dealing with popup.html and popup.js. This is really quite simple, since the popup is nothing more than a regular old .html file which references CSS or JS as needed, and is displayed in a small window. Regular front end development rules apply here, and you're only limited by your imagination, so you can do fancy stuff like AJAX calls or responsive layouts without jumping through any special hoops. Browser actions also give you the ability to add text in front of the button, using the setBadgeText() function, or do something besides show a popup HTML page when clicked. They're pretty flexible little guys. If you're trying to alter the behavior of existing web pages, by adding JS or CSS to them, then you're going to be spending most of your time in content scripts. You'll probably want to rename the default "contentscript.js" file (both the file itself and the reference to it in manifest.json), and/or create some new files so that you can better organize your code. Content scripts are very easy to grasp because they literally just run code inside the web pages that you give them access to. The only difference between them and actual JS files included in the page is that content scripts have a couple limitations (see the next section).
Since content scripts seem to be the most commonly edited files in Chrome extension, I'd like to talk a bit about some special things to keep in mind for them. The main thing that trips people up is that content scripts don't have access to global objects, like the "window" object, or global objects defined by the JS in the page itself. This can be a problem that is tough to work around. The other stumbling point is the fact that content scripts can't trigger events like regular JS. So if you manually change an input's value, but a "change" event handler doesn't run, and you try to manually trigger the change event, you're out of luck. In both cases, there's a (hacky, but useful) workaround which involves manually building a <script> tag and adding it to the page. Here's a function to do that:
/**
* Builds a script tag with the given JS code and injects it into a page.
*
* This allows us to run JS that isn't strictly allowed in Chrome extension,
* such as .trigger()ing things like click and change, or accessing global vars.
*
* @param {string} jsString
*/
var injectJs = function(jsString) {
var s = document.createElement('script');
s.textContent = jsString;
s.onload = function () {
this.parentNode.removeChild(this);
};
document.head.appendChild(s);
};
Just put the JS string you need to inject into a variable and run that function to dump it into the page.
If you find that you need to pull in some commonly used JS or CSS library, then "bower" (which Yeoman includes by default) is your friend. Search for what you need and if bower has a package for it, then you can add it to your extension using:
bower install thingname --save
Then you can just point to the files that you need in the app/bower_components directory. You can also ignore these files with git so that you're not using git to keep track of 3rd party dependencies. Instead, just let git track bower.json (which itself tracks version dependencies), so anyone can clone the repo and run "bower install" at any time to pull everything in.
Once you are happy with your extension and you deem it ready to upload to the Webstore, you need only run one simple command:
$ grunt build
This will do a lot of things, such as minifying your code, hinting your JS, bumping the version in your manifest.json, etc., but the important end result is that you get a .zip file dump into the package/ directory which is ready to upload to the Webstore. Once you have that, mosey on over to the Webstore Developer Dashboard, click the "Add New Item" button, and upload your file. After that, you'll have to enter a bunch of information about it and upload at least one screenshot, but that's all that stands between you and publishing your extension to the world. With that, you should be off to the races. The Chrome extension API docs should pick up where this posts leave off, and they are well written and helpful, so make that your first stop for questions. If you are interested in learning more about using Grunt, learn from the pro, Steven Merrill in his blog post "Combining Tasks with Grunt." Happy extension writing!