DEV Community

Marcin Wosinek
Marcin Wosinek

Posted on • Edited on

Rollup 2 in a simple html+js use case

In this series, I'll take a look on a simple usecase of js+html application, build with various js bundlers. In earlier articles, we've seen how far we can get without any bundler and how it goes wepback & esbuild. Here we will take look on rollup.js.

Rollup 2

Rollup seems to be in an interesting point - on many metrics just after webpack - second most popular, second oldest:

npm trends for bundlers

source

but in the same time, seems it's not generating as much excitement as some newer tools - like discussed previously esbuild. But it's still worth taking a look - just because of it's popularity, you can come across it in some project.

The app

application screenshot

same as other articles of this series, simple app with 1 component with template & data in separate files.

Code

The main html file is simple:

<!-- index.html -->
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <title>Contact App</title>
    <link rel="shortcut icon" href="#" />

    <script type="module" src="./dist/index.js"></script>
    <link rel="stylesheet" href="style.css" />
  </head>
  <body></body>
</html>
Enter fullscreen mode Exit fullscreen mode

the source file, ./dist/index.js has to be match to what we set as output in rollup.config.js.

Main js file:

// src/index.js
import "./contact-list/contact-list";
Enter fullscreen mode Exit fullscreen mode

no surprise here, rollup behaves in the same way we are already accustomed by other bundlers.

The component

The component is broken down into 3 files. By default, rollup supports JS files only. For JSON & HTML, we will need to install a plugin & set up configuration.

// src/contact-list/contact-list.js
import template from "./contact-list.html";
import contacts from "./data.json";

const contactList = document.createElement("div");

contactList.className = "contact-list";

contacts.forEach((entry) => {
  const element = document.createElement("div");
  element.className = "contact";

  element.innerHTML = template;

  element.querySelector(".name").innerHTML = entry.name;
  element.querySelector(".phone").innerHTML = entry.phone;

  contactList.appendChild(element);
});

document.body.appendChild(contactList);
Enter fullscreen mode Exit fullscreen mode

So far, each bundler works with the same application code - that's very good for migrations if we ever decide going from building with one tool to some other.

Even for JSON files, rollup needs an aditional library - a json plugin. The installation & configuration will be covered below.

src/contact-list/data.json, the data file:

[
  {
    "name": "Christopher L Sanders",
    "phone": "769-232-1807"
  },
  {
    "name": "Frances J Nolte",
    "phone": "901-287-0419"
  }
]
Enter fullscreen mode Exit fullscreen mode

HTML files, where the source of the biggest confusion for me. Looks that I'm very used to webpack's html-loader, and it's way of thinking. The rollup's core html plugin seems to do slightly different thing. In the end I got my template as a string into js by a combination of @rollup/plugin-babel & babel's plugin babel-plugin-transform-html-import-to-string. This solution felt pretty over engineered to me - I'm either very off with how I approached the problem, or I was trying to force rollup to behave in a way it would rather not. I guess, in cases when you use reacts' jsx or tsx, it feels much smoother, because you don't move template out of js.

<!-- src/contact-list/contact-list.html -->
<h2 class="name">name</h2>

<p class="phone">phone</p>
Enter fullscreen mode Exit fullscreen mode

Build dependencies & configuration

For a successful build of the above code, we need quite a few things. To install them all:

$  npm install --save-dev @babel/preset-env @rollup/plugin-babel @rollup/plugin-json rollup babel-plugin-transform-html-import-to-string
Enter fullscreen mode Exit fullscreen mode

The configuration:

// rollup.config.js
import { babel } from "@rollup/plugin-babel";
import json from "@rollup/plugin-json";

const config = {
  input: "src/index.js",
  output: {
    format: "esm",
    file: "dist/index.js",
  },
  plugins: [
    babel({
      exclude: "node_modules/**",
      presets: ["@babel/preset-env"],
      plugins: ["babel-plugin-transform-html-import-to-string"],
      extensions: [".js", ".html"],
    }),
    json(),
  ],
};

export default config;
Enter fullscreen mode Exit fullscreen mode

That is a bit disappoiting - especially if you heard horror storries about wepback confiuration, here even simple usecase requires a lot of configuration.

For easy access to build script, you can add following line to package.json:

  "scripts": {
    // other scripts
    "build": "rollup -c rollup.config.js"
  }
Enter fullscreen mode Exit fullscreen mode

succesful build:

$ npm run build

> rollup@1.0.0 build
> rollup -c rollup.config.js


src/index.js → dist/index.js...
babelHelpers: 'bundled' option was used by default. It is recommended to configure this option explicitly, read more here: https://github.com/rollup/plugins/tree/master/packages/babel#babelhelpers
created dist/index.js in 301ms
Enter fullscreen mode Exit fullscreen mode

Complete code & application example

If you want to see the application in action in the browser you can see it here:
https://marcin-wosinek.github.io/js-html-comparison-rollup-2/

and for the working code example you can go here:
https://github.com/marcin-wosinek/js-html-comparison-rollup-2

Top comments (0)