Rollup is the bundler behind Vite, and its plugin API is the de facto standard. If you've written a Vite plugin, you've used Rollup's API.
The Rollup Plugin Interface
// rollup.config.js
export default {
input: "src/index.js",
output: [
{ file: "dist/bundle.cjs.js", format: "cjs" },
{ file: "dist/bundle.esm.js", format: "es" },
{ file: "dist/bundle.umd.js", format: "umd", name: "MyLib" },
],
plugins: [myPlugin()],
};
Writing a Plugin: Full Lifecycle
function jsonPlugin() {
return {
name: "json",
// Resolve custom module IDs
resolveId(source) {
if (source === "virtual:config") return source;
return null; // Defer to other plugins
},
// Load content for resolved IDs
load(id) {
if (id === "virtual:config") {
return `export default ${JSON.stringify({ version: "1.0" })}`;
}
return null;
},
// Transform file contents
transform(code, id) {
if (!id.endsWith(".json")) return null;
const parsed = JSON.parse(code);
return {
code: `export default ${JSON.stringify(parsed)};`,
map: null,
};
},
// Modify the final bundle
generateBundle(options, bundle) {
for (const [fileName, chunk] of Object.entries(bundle)) {
if (chunk.type === "chunk") {
console.log(`${fileName}: ${chunk.code.length} bytes`);
}
}
},
};
}
Code Splitting
export default {
input: {
main: "src/index.js",
admin: "src/admin.js",
worker: "src/worker.js",
},
output: {
dir: "dist",
format: "es",
chunkFileNames: "chunks/[name]-[hash].js",
manualChunks(id) {
if (id.includes("node_modules")) {
if (id.includes("react")) return "vendor-react";
if (id.includes("lodash")) return "vendor-lodash";
return "vendor";
}
},
},
};
Watch Mode API
import { watch } from "rollup";
const watcher = watch({
input: "src/index.js",
output: { file: "dist/bundle.js", format: "es" },
plugins: [/* ... */],
});
watcher.on("event", (event) => {
switch (event.code) {
case "START": console.log("Build starting..."); break;
case "BUNDLE_END":
console.log(`Built in ${event.duration}ms`);
event.result.close();
break;
case "ERROR": console.error(event.error); break;
}
});
Programmatic API
import { rollup } from "rollup";
async function build() {
const bundle = await rollup({
input: "src/index.js",
plugins: [nodeResolve(), commonjs(), terser()],
});
// Generate multiple outputs
await bundle.write({ file: "dist/index.cjs", format: "cjs" });
await bundle.write({ file: "dist/index.mjs", format: "es" });
await bundle.write({ file: "dist/index.umd.js", format: "umd", name: "MyLib" });
await bundle.close();
}
Tree Shaking: The OG
Rollup invented tree shaking for JavaScript:
// utils.js
export function used() { return "I stay"; }
export function unused() { return "I get removed"; }
// index.js
import { used } from "./utils";
console.log(used());
// unused() is completely removed from bundle
Building reusable libraries? My Apify tools show how to build and distribute production packages.
Custom tooling? Email spinov001@gmail.com
Top comments (0)