Koru pattern, a big R and a big U

Rollup Plugins for Absolute Beginners

26 July 2021

I've recently been getting into the new generation of development tools like wmr, Vite, esbuild and Snowpack. These are causing quite a bit of hype in the community.

So I thought I'd start to get closer to the metal with these tools and how to configure them. Something interesting I found out is that both Vite and wmr have opted to support rollup plugins!

The rollup plugin API is a hell of a lot simpler than writing webpack loaders so this is good news. This also means that understanding rollup plugins and how to write them will continue to be an important skill in the JavaScript world, so let's get into it:

Default Export Function #

A rollup plugin should be a JavaScript module exporting a single function by default. It's also an important convention to start the name with "rollup-plugin-"

At the moment node.js still isn't using esmodules by default, so let's use the ".mjs" extension. Something like this:

// rollup-plugin-mydopeplugin.mjs

export default function myDopePlugin(){}

This function should return an object with some specific keys which rollup is going to look for when running through your code. In the rollup docs these are referred to as "hooks" because they are places you can hook into the build - makes sense!

Name Property #

The most basic and important property to add is the name of your plugin. This will be used by rollup for any error messages or warnings. So let's name our plugin!

// rollup-plugin-mydopeplugin.mjs

export default function myDopePlugin(){
    return {
        name:"my-dope-plugin"
    }
}

Hey this really doesn't seem so bad does it? But we probably want our plugin to do something. At the moment it will do absolutely nothing, but hey, it's bug free!

Transform hook #

This hook is going to let us change our code. It's a function that takes two arguments:

The string representation of the code is simple enough. But what do I mean by ID? We're JavaScript developers and probably used to IDs being something we use to grab a user or a post when we're processing data. In this case, the ID refers to the string path that was used to import the module. It's the string in the JavaScript import statement after "from" .

So if our source code looked like:

// index.js

import {uppercaseMyString} from './utilities.js'

Then the ID when rollup plugs the utilities import into a transform hook would be "./utilities.js".

What should our transform hook return? There are a few options:

Let's write our plugin #

Let's write a plugin which will insert a console.log at the start of every JavaScript file that gets imported in our project. We'll start by adding a transform function to our previous code:

// rollup-plugin-mydopeplugin.mjs

export default function myDopePlugin(){
   return {
       name:"my-dope-plugin",
       transform(source,id){

       }
   }
}

Now we'll take a look at the id and make sure we're looking at a JavaScript file. If it doesn't have the ".js" file extension, we'll return null to tell rollup we don't want to do anything with it. So our transform function becomes:

transform(source,id){
    if (id.slice(-3) !== ".js") return null;
}

And finally if it is a JavaScript file, let's concatenate a console.log to the front of our code and return the string.

// rollup-plugin-mydopeplugin.mjs

export default function myDopePlugin(options = {}) {
  return {
    name: "my-dope-plugin",
    transform(source, id) {
      if (id.slice(-3) !== ".js") return null;
      return "console.log('hello from rollup');" + source;
    },
  };
}

And that's our plugin finished!

Now let's use it in a rollup build. Let's npm install rollup and create a "rollup.config.js" file. This file needs a default export which is an object with input and output keys that hold strings to where we want to input and output our source. It also has a key that holds an array of plugins.

We can import our plugin to the rollup config file, then call its function within the plugins array in the rollup config:

// rollup.config.js
import myDopePlugin from './rollup-plugin-mydopeplugin.mjs';

export default {
  input: 'index.js',
  output: {
    file: 'bundle.js',
  },
  plugins: [ myDopePlugin() ]
};

Then when we run our rollup build we just need to tell it to use our config file by adding a --config argument in the command line. If you do a default npm install it'd look something like this:

./node_modules/.bin/rollup --config

And that's it! Hopefully this has made getting your hands dirty in the build step slightly less scary by keeping things super simple.

As mentioned before, you could potentially use this plugin in the build step of a Vite project or a wmr project - not that this particular plugin has any use at all. But this is super empowering that we have some reusability in build systems now.

There's quite a few more rollup hooks to look into if you want to get some more power building these plugins. I'd also recommend checking out This talk about build plugins with Jake Archibald and Jason Miller.

I might try add another blogpost sometime soon getting deeper into rollup plugins as they're so dang useful.

Back to blog