webextension-polyfill

repository·master·Indexed 25 days ago

https://github.com/mozilla/webextension-polyfill

A lightweight polyfill library (v0.12.0) that provides the Promise-based `browser` API to Google Chrome. It allows developers to write extensions that run on both Firefox and Chrome with minimal changes by wrapping Chrome's callback-based APIs into Promises. The library supports installation via npm, direct download, and integration with module bundlers like Webpack.

Tokens
2.7K
Snippets
7
Records
20
Agent score
35%

What's inside webextension-polyfill

  1. Understanding Promise-based APIs

    master

    The browser namespace provides Promise-based APIs that differ from Chrome's callback-based chrome namespace in several ways:

    • Return Values: Every async function returns a Promise instead of accepting a callback.
    • Error Handling: Instead of checking chrome.runtime.lastError, use Promise rejection handlers (.catch()) or try/catch blocks.
    • Message Responses: In onMessage listeners, return a Promise to send a response instead of using a sendResponse callback.
    • Chaining: Use Promise chaining or async/await to handle sequential operations instead of nested callbacks.
  2. Basic Setup for HTML Documents (Popups/Tabs)

    master

    For HTML documents like browserAction popups or tab pages, include the polyfill script in the <head> before your application scripts.

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <script type="application/javascript" src="browser-polyfill.js"></script>
        <script type="application/javascript" src="popup.js"></script>
      </head>
      <!-- ... -->
    </html>
  3. MSEdge support and compatibility

    master

    Microsoft Edge (MSEdge) support depends on the version:

    • MSEdge >= 79.0.309: Unofficially supported as a Chrome-compatible target.
    • MSEdge < 79.0.309: Unsupported. To support older versions, use the MSEdge --ms-preload manifest key and the Microsoft Edge Extension Toolkit's Chrome API bridge to load the polyfill without MSEdge-specific changes.
  4. Basic Setup for Background and Content Scripts

    master

    To use the polyfill, it must be loaded into any context where browser APIs are accessed. In your manifest.json, ensure browser-polyfill.js is listed before any other scripts that depend on it.

    {
      // ...
    
      "background": {
        "scripts": [
          "browser-polyfill.js",
          "background.js"
        ]
      },
    
      "content_scripts": [{
        // ...
        "js": [
          "browser-polyfill.js",
          "content.js"
        ]
      }]
    }
  5. Use TypeScript with webextension-polyfill

    master

    To add TypeScript support to your web extension project, use the following packages:

    • @types/webextension-polyfill: Recommended. Types and JS-Doc are automatically generated from the mozilla schema files and are kept up-to-date with the latest APIs.
    • @types/chrome: Manually maintained types. Note that this package only contains types for Chrome extensions.
  6. Basic Setup with Module Bundlers (Webpack/Browserify)

    master
    The library is a UMD module. You can use require to import it. Using require("webextension-polyfill") will use the non-minified version, which you should then minify as part of your build process. To explicitly use the minified version, require the path to the minified file.
  7. Basic Setup with ES6 Module Loader

    master

    You can use the native ES6 module loader. Note that the polyfill module does not export the browser object; instead, it defines browser in the global namespace (window).

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <script type="module" src="browser-polyfill.js"></script>
        <script type="module" src="background.js"></script>
      </head>
      <!-- ... -->
    </html>
    // In background.js (loaded after browser-polyfill.js)
    // The `browser` API object is already defined globally.
    browser.runtime.onMessage.addListener(...);
  8. Usage with webpack without bundling

    master

    If you prefer not to bundle the polyfill into every script, you can use copy-webpack-plugin to copy the library into your output folder and then load it via manifest.json as described in the Basic Setup guide.

    1. Install the plugin:
    npm install --save-dev copy-webpack-plugin
    1. Configure webpack.config.js:
    const CopyWebpackPlugin = require('copy-webpack-plugin');
    
    module.exports = {
      plugins: [
        new CopyWebpackPlugin({
          patterns: [{
            from: 'node_modules/webextension-polyfill/dist/browser-polyfill.js',
          }],
        })
      ]
    }
  9. Injecting the Polyfill via executeScript

    master

    For dynamically-injected content scripts loaded via tabs.executeScript, you must inject the polyfill separately before injecting your content script, unless the polyfill was already declared in manifest.json.

    browser.tabs.executeScript({file: "browser-polyfill.js"});
    browser.tabs.executeScript({file: "content.js"}).then(result => {
      // ...
    });
  10. Download webextension-polyfill directly

    master

    If you do not use a package.json or prefer to manage files manually, you can download the library directly from unpkg.com or via GitHub releases.

    Available files in the dist/ directory:

    • browser-polyfill.js (non-minified)
    • browser-polyfill.min.js (minified)
  11. Limitations of Promise-based APIs on Chrome

    master
    The Promise-based APIs provided by this library do not support passing a callback parameter when running on Chrome. While some native Firefox asynchronous methods might support both a promise and a callback, this polyfill's Promise-based implementation does not.