Building Chrome Extensions with React and Webpack

Silicon Valley Code Camp 2017

Guy Vider

Site: TravelingTechGuy.com

Github: github.com/TravelingTechGuy

LinkedIn: linkedin.com/in/gvider

Twitter: @TravelTechGuy

Slides: https://travelingtechguy.github.io/svcc-chrome-extension/

Code: https://github.com/TravelingTechGuy/svcc-chrome-extension

In this session we'll cover:

  1. What are Chrome extensions and why should you care? (3 minutes)
  2. How to create a basic Chrome extension (10 minutes)
  3. How to add React to the view parts, and how to use Webpack to package the extension (20 minutes)
  4. Tie it all togather into a functional extension (10 minutes)
  5. Q&A (time permitting)

To build and use the extensions in this repo, you'll need:

  1. A console application of your choosing
  2. git - clone this repo:
    git clone https://github.com/TravelingTechGuy/svcc-chrome-extension
    Or you could just download the full zip at
    https://github.com/TravelingTechGuy/svcc-chrome-extension/archive/master.zip
  3. NodeJS and NPM - install from the NodeJS site
  4. Install Webpack globally using NPM:
    npm i -g webpack

What are extensions?

Extensions are small software programs that can modify and enhance the functionality of the Chrome browser. You write them using web technologies such as HTML, JavaScript, and CSS. ... You can distribute your extension through the Chrome Web Store.

Google

Simply put, extesnions are apps for your browser

Some examples:

And many more at the Chrome web store... all free!

Setup

  1. In Chrome, go to Menu > More Tools > Extensions
    Alternatively, type chrome://extensions in the address bar
  2. Check the Developer mode box
  3. You can now load unpacked extensions
Chrome browser extensions settings page

Basic extension

Folder structure

        
          manifest.json*
          background.html
          background.js
          options.html
          popup.html
          --|_locales*
            --|messages.json
          --|icons
            --|icon16.png
            --|icon19.png
            --|icon48.png
            --|icon128.png
        
      

Files marked with * are mandatory.

Extension parts:

  1. Manifest - tells Chrome all the essentials about the extension, assigns the various components and icons, and sets permissions and security.
  2. Messages - contains the extension's name and description. Provide I18N support.
  3. Icons - holds all icons and images the extension needs.
  4. Popup page - will be shown when the extension icon is clicked [Not mandatory].
  5. Options page - allows settings management for the extension [Not mandatory].
  6. Background page - an HTML/Javascript file that runs constantly in the background [Not mandatory].
    Useful for carrying out async tasks, network operations and monitoring, and provide access to Chrome API.

The manifest.json file

        {
          "name": "Basic",
          "version": "1.0.0",
          "manifest_version": 2,
          "description": "Basic extension",
          "homepage_url": "http://www.TravelingTechGuy.com",
          "icons": {
            "16": "icons/icon16.png",
            "19": "icons/icon19.png",
            "48": "icons/icon48.png",
            "128": "icons/icon128.png"
          },
          "default_locale": "en",
          "background": {
            "page": "background.html",
            "persistent": true
          },
          "options_page": "options.html",
          "browser_action": {
            "default_icon": "icons/icon19.png",
            "default_title": "Basic Extension",
            "default_popup": "popup.html"
          },
          "permissions": [
          ],
          "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"
        }
      

Once the extension loaded:

extension loaded

Why use React in a Chrome extension?

Reactive extension setup

Our new folder structure:

        
          package.json        //NPM modules, and build scripts
          webpack.config.js   //Webpack configuration files
          +build          //folder containing he built extension (created)
          +dist           //folder containing the packed extension (created)
          +src            //source root folder for Webpack to process
          --|manifest.json*
          --|background.html  //only needed if we want access to clipboard
          --|options.html
          --|popup.html
          --|scripts          //All logic goes here
            --|background.js  //background logic
            --|popup.js       //React DOM render - can be embedded in HTML
            --|options.js     //React DOM render - can be embedded in HTML
            --|components     //React components folder
              --|popup.js     //component logic
              --|popup.css    //component stylesheet
              --|options.js
              --|options.css
              --|...
          --|_locales*
            --|messages.json
          --|icons
            --|icon16.png
            --|icon19.png
            --|icon48.png
            --|icon128.png 
        
      

Extension logic

Utilizing local storage in an extension

  1. Don't forget to add "storage" to the manifest's permissions!

  2. window.localStorage

    Pros:
    • Synchronous, and thus easier to work with
    • Has support in Dev Tools (Resources > Local Storage to view and modify)
    Cons:
    • Only stores strings, therefore you need to serialize data yourself (JSON.stringify)
    • Is not accessible from content scripts, so you need to rely on Messaging to pass values
  3. chrome.storage.local

    Pros:
    • Can store non-strings with no additional boilerplate
    • Available within Content Scripts
    • Supports events that notify about changes (chrome.storage.onChanged)
    • Has a built-in mechanism for default values
    • Specifying "unlimitedStorage" permission in your manifest allows storing more than the HTML5 localStorage 5MB limit
    Cons:
    • Asynchronous, therefore a bit harder to work with
    • Not accessible from Dev Tools
  4. chrome.storage.sync

    Same as chrome.storage.local, but synced between signed-in Chrome instances.

Lets put all we know together into StockQuote

Let's look at the code...

A bonus extension: changes the content of an HTML page ☺

Questions?

Github: github.com/TravelingTechGuy

LinkedIn: linkedin.com/in/gvider

Twitter: @TravelTechGuy

/