Skip to content

Latest commit

 

History

History
339 lines (260 loc) · 8.42 KB

File metadata and controls

339 lines (260 loc) · 8.42 KB

API Documentation

rollup-plugin-chrome-extension works out of the box, but sometimes you need more.

Table of Contents

Exports

chromeExtension

Type Arguments
function (options?: object) => ChromeExtensionPlugin

Call this function to initialize rollup-plugin-chrome-extension. Always put it first in the plugins array, since it converts the manifest json file to an array of input files. See Options API for config details.

// rollup.config.js

import { chromeExtension } from 'rollup-plugin-chrome-extension'

export default {
  input: 'src/manifest.json',
  output: {
    dir: 'dist',
    format: 'esm',
  },
  plugins: [chromeExtension()],
}

simpleReloader

Type Call Signature
function `() => SimpleReloaderPlugin

This reloader simply uses setInterval to fetch a local timestamp file every few seconds. When Rollup completes a new build, it changes the timestamp and the Chrome extension reloads itself.

If Rollup is not in watch mode, simpleReloader disables itself`.

Make sure to do your final build outside of watch mode so that it doesn't include the reloader.

Usage for simpleReloader

import {
  chromeExtension,
  simpleReloader,
} from 'rollup-plugin-chrome-extension'

export default {
  input: 'src/manifest.json',
  output: {
    dir: 'dist',
    format: 'esm',
  },
  plugins: [
    chromeExtension(),
    // Reloader goes after the main plugin
    simpleReloader(),
  ],
}

Start Rollup in watch mode. Enjoy auto-reloading whenever Rollup makes a new build.

Manifest API

[permissions]

If a wrong permission has been detected

Sometimes a third-party module will reference a Chrome API to detect its environment, but you don't need the permission in your manifest.

// wrong permissions in output manifest.json
{
  "permissions": [
    "alarms", // This should not be here
    "storage"
  ]
}

Solution: Prefix unwanted permissions in the manifest with "!", for example, "!alarms".

// source manifest.json
{
  "permissions": [
    "!alarms", // This permission will be excluded
    "storage"
  ]
}
// correct permissions in output manifest.json
{
  "permissions": ["storage"]
}

[web_accessible_resources]

If you have files that are not imported to a script, or referenced directly in the manifest or an HTML file, add them to web_accessible_resources.

They will be written to output.dir with the same folder structure as the source folder (the folder with the manifest file). Relative paths may not lead outside of the source folder.

{
  "web_accessible_resources": [
    "fonts/some_font.oft",
    // HTML files are parsed like any other HTML file.
    "options2.html",
    // Globs are supported too!
    "**/*.png"
  ]
}

Options API

You can use an options object with any of the following properties. Everything is optional.

[browserPolyfill]

Type
boolean

Add the excellent promisified Browser API by Mozilla to your Chrome extension with one easy option:

chromeExtension({
  browserPolyfill: true,
})

Don't forget to install types if you want Intellisense to work!

[dynamicImportWrapper]

Type
object or false

We use dynamic imports to support ES2015 modules and code splitting for JS files.

Use modules in Chrome extension scripts. Only disable if you know what you're doing, because code splitting won't work if dynamicImportWrapper === false.

Why do we need to use dynamic import in scripts?

Two things are going on here: This Rollup plugin leverages two Rollup features to parse the manifest into inputs:

  • It adds multiple parsed files to options.input
  • It uses options.output.dir to support multiple output files. This means that Rollup will use code-splitting. This is great because it makes a smaller bundle with no overlapping code, but we need a way to load those chunks into our content and background scripts. After some experimentation, I found that ES modules are the best format for web extensions, but they don’t support ES modules in background or content scripts out of the box.

The solution is to use dynamic imports in extension scripts. All Chromium browsers and Firefox 89+ (coming May 2021) support this.

[dynamicImportWrapper.wakeEvents]

Type
string[]

Events that wake (reactivate) an extension may be lost if that extension uses dynamic imports to load modules or asynchronously adds event listeners.

List events that will wake your background page (for example, 'chrome.tabs.onUpdated', or 'chrome.runtime.onInstalled'). The script module loader will defer them until after all the background script modules have fully loaded.

It may be possible to statically analyze the background page code to detect which events the extension uses. Like this issue if this is something that interests you!

// Example usage
chromeExtension({
  dynamicImportWrapper: {
    wakeEvents: ['chrome.contextMenus.onClicked'],
  },
})

// Default value
chromeExtension({
  dynamicImportWrapper: {
    wakeEvents: [
      'chrome.runtime.onInstalled',
      'chrome.runtime.onMessage',
    ],
  },
})

[dynamicImportWrapper.eventDelay]

Type
number or boolean

Delay Event page wake events by n milliseconds after the all background page modules have finished loading. This may be useful for event listeners that are added asynchronously.

chromeExtension({
  dynamicImportWrapper: {
    eventDelay: 50,
  },
})

[verbose]

Type
boolean

Set to false to suppress "Detected permissions" message.

// Example usage
chromeExtension({
  verbose: false,
})

// Default value
chromeExtension({
  verbose: true,
})

[pkg]

Type
object

Only use this field if you will not run Rollup using npm scripts (for example, $ npm run build), since npm provides scripts with the package info as an environment variable.

The fields name, description, and version are used.

These values are used to derive certain values from the package.json for the extension manifest. A value set in the source manifest.json will override a value from package.json.

// Example usage
const packageJson = require('./package.json')

chromeExtension({
  // Not needed if you use npm to run Rollup
  pkg: packageJson,
})

// Default value
chromeExtension({
  // Can be omitted if run using an npm script
})

[publicKey]

Type
string

If truthy, manifest.key will be set to this value. Use this feature to stabilize the extension id during development.

Note that this value is not the actual id. An extension id is derived from this value.

const p = process.env.NODE_ENV === 'production'

// Example usage
chromeExtension({
  publicKey: !p && 'mypublickey',
})

// Default value
chromeExtension({
  publicKey: undefined,
})