JSPM

  • Created
  • Published
  • Downloads 1507
  • Score
    100M100P100Q113041F
  • License MIT

Build Chrome Extensions with this Rollup plugin.

Package Exports

  • rollup-plugin-chrome-extension

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (rollup-plugin-chrome-extension) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

rollup-plugin-chrome-extension logo

rollup-plugin-chrome-extension

npm (scoped) GitHub last commit CircleCI Codecov TypeScript Declarations Included

Chrome Extension Tutorials on YouTube ko-fi


A feature-rich solution for bundled Chrome extensions! 💯

Build Chrome extensions using Rollup, with minimal configuration.

Use manifest.json as the input. Every file in the manifest will be bundled or copied to the output folder.

Table of Contents

Getting started

Chrome Extension Boilerplates

We have TypeScript and JavaScript boilerplates available.

Get started fast with the JavaScript React boilerplate:

git clone https://github.com/extend-chrome/js-react-boilerplate.git

Or use the TypeScript React boilerplate if you're feeling fancy:

git clone https://github.com/extend-chrome/ts-react-boilerplate.git

Special thanks to @kyrelldixon for this Svelte and Tailwind CSS boilerplate with optional TypeScript support:

git clone https://github.com/kyrelldixon/svelte-tailwind-extension-boilerplate.git

I want to do it myself

npm i rollup rollup-plugin-chrome-extension@latest -D

Install the plugins Node Resolve and CommonJS if you plan to use npm modules.

npm i @rollup/plugin-node-resolve @rollup/plugin-commonjs -D

Usage

Create a rollup.config.js file in your project root.

// rollup.config.js

import resolve from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'

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

export default {
  input: 'src/manifest.json',
  output: {
    dir: 'dist',
    format: 'esm',
  },
  plugins: [
    // always put chromeExtension() before other plugins
    chromeExtension(),
    simpleReloader(),
    // the plugins below are optional
    resolve(),
    commonjs(),
  ],
}

Add these scripts to your package.json file.

// package.json

{
  "scripts": {
    "build": "rollup -c",
    "start": "rollup -c -w"
  }
}

Put your Chrome extension source code in a folder named src in the root of your project and build with the following command:

npm run build

Your extension build will be in the dist folder. It has everything it needs: manifest, scripts, and assets (images, css, etc...).

Load it in Chrome chrome://extensions/ to test drive your extension! 🚗

Features

⭐️ It's all in the Manifest

Why does the `rollup.config.js` only need the manifest as an entry point?
`rollup-plugin-chrome-extension` parses your manifest and bundles the scripts in your background page, content scripts, option page and popup page
Does that include the scripts in the Options page and Popup page?
`rollup-plugin-chrome-extension` uses the JS or even TS files in your HTML files as entry points. Shared code is split out into chunks automatically, so libraries like React and Lodash aren't bundled into your extension multiple times.
What happens with the assets? Like images, icons or css files?
All assets declared in the manifest (including files in `web_accessible_resources`, any image, icon, font, and even CSS files) are automatically copied into the output folder. Even the images in your HTML files get copied over. NOTE: This only includes assets in the html itself. If you import images or CSS in a JavaScript file, you will need an additional plugin.
Is the Manifest validated?
`rollup-plugin-chrome-extension` validates your output manifest, so you discover mistakes when you build, not in a cryptic Chrome alert later.
Does it detect permissions automatically?
`rollup-plugin-chrome-extension` statically analyzes your bundled code, detects any required permissions and adds them to the manifest in the `dist` folder. Any permissions in the source manifest are always included.
Do I have to copy/paste the package.json fields to the Manifest?
You can omit `manifest_version`, `version`, `name`, and `description` from your source `manifest.json`. We'll fill them out automatically from your `package.json`, if you use an npm script to run Rollup. Just manage your version number in `package.json` and it will reflect in your extension build.

Don't worry, any value in your source manifest will take over! 😉

⭐️ Reload Your Extension Automatically

Does this mean I don't have to manually reload my extension during development?
Improve your development experience with our reloader! You won't have to reload your Chrome extension every time you make a change to your code. We know what a pain it can be to forget and wonder, "Why isn't this change working? 😟".
Does it also reload the pages I am injecting content scripts?
Ever got the error `"Extension context invalidated"` in your content script? That happens when the extension reloads but the content script doesn't. Our reloader makes sure that doesn't happen by reloading your content scripts when it reloads your extension automatically.
How do I enable the reloader?
If you include the helper plugin `simpleReloader` in your config, when Rollup is in watch mode your background page will include an auto-reloader script. This will reload your extension every time Rollup produces a new build.

⭐️ Write Chrome Extensions In TypeScript

Includes Chrome extension API types

If you use the @rollup/plugin-typescript, you can write your Chrome extension in TypeScript. That's right, it bundles the scripts in your manifest and in your HTML script tags.

TypeScript definitions are included, so no need to install an additional @types library!


⭐️ Use ES2015 Modules In Your Scripts

Chrome extensions don't support modules in background and content scripts. We've developed a module loader specifically for Chrome extension scripts, so you can take advantage of Rollup's great code splitting features.

⭐️ How does the dynamic import wrapper work?

TLDR; RPCE parses the manifest and replaces any script path with an IIFE wrapper that loads the script using a dynamic import statement.

See Why do we need to use dynamic import in scripts? for the reasons we need dynamic imports. Content scripts are pretty straight forward, and the wrapper they use is just an IIFE that loads the script and logs any import errors. Background pages need a special wrapper because wake events (onInstalled, onMessage, etc...) fire before the import completes. We make sure we don’t miss any events by capturing all events that occur before the import promise resolves and then re-dispatch them after the import completes.


⭐️ What About FireFox Support?

Until v89, Firefox did not support dynamic imports in web extensions, so any scripts needed to be in another format, like IIFE. The suggested solution was to run Parcel on the Rollup output, but this won’t be necessary once Firefox v89 is released.


⭐️ Use Promises like it's 2021

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

chromeExtension({ browserPolyfill: true })

This option adds browser to the global scope, so you don't need to import anything.

Install this type package to get Intellisense. It's automatically updated on a regular basis.


⭐️ Plugins Take It To The Next Level

Take advantage of other great Rollup plugins to do awesome things with your Chrome extensions!

Some of our favorites are:

Two of our own plugins:

⭐️ Outputs a Chrome Web Store friendly bundle

Every time you publish your Chrome extension to the Web Store, your extension will be reviewed by a robot and then a human to make sure it meets their guidelines. Even if you pass when you first publish, your extension may be flagged at any time. rollup-plugin-chrome-extension helps you put your best foot forward.

Wrong permissions are the number one reason that Chrome extensions are rejected from the Chrome Web Store. rollup-plugin-chrome-extension can detect most of the commonly used permissions in your code automatically, so you only need to add a permission manually if you absolutely know that you need it.

Imagine the person who reviews the code you submit. Common bundling options like webpack and Parcel produce code that is really hard to read. Rollup produces code that is easy to read! When you submit your extension for review, you want to avoid misunderstandings.

Rollup produces a nice clean bundle using code splitting, ES modules, and tree-shaking. If you don't use some piece of code, Rollup removes it. If you use a module in more than once place, Rollup splits it out into a chunk, so that it's only in your extension once.

All of this means a smaller Chrome extension. We've seen Chrome extensions go from over 8Mb to less than 1Mb just by switching from create-react-app to Rollup. A smaller bundle means less code to review, and less room for error during the review process.