Why Rollup Beats Webpack for Building a Simple JS Library

This article compares Webpack and Rollup, explains why Rollup’s tree‑shaking and ES6 module support make it better for a lightweight JavaScript utility library, and provides a step‑by‑step guide to set up the project with TypeScript, ESLint, Prettier, Husky, Commitlint and Jest testing.

37 Mobile Game Tech Team
37 Mobile Game Tech Team
37 Mobile Game Tech Team
Why Rollup Beats Webpack for Building a Simple JS Library

Preface

Recently I was writing a frontend utility library. I started with Webpack, but then discovered Rollup, which better fits my needs. This article introduces building a simple JavaScript utility library with Rollup.

Requirements

Code level 1. Write code using ES6 syntax (including async) with specific parameter requirements. 2. Follow coding standards when committing. 3. Unit testing. 4. Generate documentation comments. Function level 1. Support mainstream browsers (e.g., Chrome, Firefox). 2. Provide common JS methods. 3. May depend on other libraries.

Webpack VS Rollup

Entry files Both Webpack and Rollup require a configuration file to specify entry, output, plugins, etc.

Relative path support: Webpack does not support it (requires path.resolve); Rollup supports it.

This is just one simple difference; there are several more.

Tree‑shaking (dead code elimination)

Tree‑shaking reduces the bundle size by removing unused code, which shortens page load time. It works by statically analyzing ES6 modules.

tree shaking illustration
tree shaking illustration

Comparing the same code bundled by Webpack and Rollup:

Execution time: Webpack 71 ms, Rollup 17 ms.

File size: Webpack 389 KB, Rollup 262 KB.

The main reason is that Rollup uses tree‑shaking, leveraging ES6 module features for static analysis and removing dead code during the uglify phase.

ES6 Module Rules

Only top‑level statements (import/export) are allowed.

Import module specifiers must be string literals.

Imported modules cannot be reassigned.

// Case 1
let str = '只能作为模块顶层的语句出现';
import { sum } from 'util';

// Case 2
import { 's' + 'um' } from 'util';

// Case 3
import { sum } from 'util'
sum = 1; // Syntax Error: 'sum' is read‑only

Real‑time Reloading

Webpack uses webpack-dev-server. Rollup uses rollup-plugin-serve + rollup-plugin-livereload. Webpack offers more customizable middleware options.

Summary

Webpack - Rich ecosystem, complete documentation, many plugins. - Code splitting and on‑demand loading with tree‑shaking (Webpack 2+). - Generates additional code, larger bundles, slower execution, lower readability. - Suitable for projects involving CSS/HTML, complex code splitting, or full applications.

Rollup - Smaller plugin ecosystem. - Bundles everything together, uses tree‑shaking to reduce size. - Usually produces no extra code, faster execution, better readability. - Ideal for building libraries.

Project Setup

Initialize project 1. Create folder rollup-demo. 2. Run npm init -y. 3. Install Rollup and a plugin to clear the dist directory: npm i rollup rollup-plugin-clear -D. 4. Create entry file src/main.js.

function fun1(){
  function fun2(){
    return 'no'
  }
  return 'yes'
}
fun1()
console.log(fun1())
function Useless(){
  console.log(1111)
}

Create rollup.config.js in the project root:

'use strict';
import clear from 'rollup-plugin-clear';
export default {
  input: 'src/main.ts',
  output: {
    file: 'dist/bundle.js',
    format: 'umd' // bundle format
  },
  plugins: [
    clear({ targets: ['dist'] }) // clean dist folder
  ]
};

Add a build script to package.json:

"build": "rollup -c rollup.config.js"

Run npm run build to complete a simple Rollup build.

Using TypeScript

TypeScript provides static typing, better IDE support, and compile‑time checks, making code easier to read and refactor. Install the necessary packages:

npm i rollup-plugin-typescript2 typescript -D

Update rollup.config.js to use the TypeScript plugin:

import ts from "rollup-plugin-typescript2";
export default {
  input: "./src/main.ts",
  plugins: [
    ts({ useTsconfigDeclarationDir: true })
  ]
};

Example tsconfig.json:

{
  "compilerOptions": {
    "target": "es5",
    "module": "es2015",
    "lib": ["es2015", "es2016", "es2017"],
    "strict": true,
    "sourceMap": true,
    "strictNullChecks": true,
    "declaration": true,
    "declarationDir": "dist/types",
    "noUnusedLocals": true,
    "outDir": "./dist",
    "typeRoots": ["node_modules/@types"]
  }
}

ESLint & Prettier

ESLint enforces code quality rules; Prettier formats code. Install the following:

npm i eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin prettier eslint-config-prettier eslint-plugin-prettier -D

Create .eslintrc.js:

module.exports = {
  root: true,
  parser: '@typescript-eslint/parser',
  parserOptions: { ecmaVersion: 2019, sourceType: 'module' },
  extends: [
    'plugin:@typescript-eslint/recommended',
    'prettier/@typescript-eslint',
    'plugin:prettier/recommended'
  ],
  env: { es6: true, node: true },
  rules: {
    'no-undef': 'error',
    'eqeqeq': 'error',
    'no-console': 'error'
  }
};

Create .prettierrc.js:

module.exports = {
  arrowParens: 'avoid',
  bracketSpacing: false,
  endOfLine: 'lf',
  jsxBracketSameLine: false,
  jsxSingleQuote: false,
  printWidth: 100,
  proseWrap: 'preserve',
  semi: true,
  singleQuote: true,
  useTabs: false,
  trailingComma: 'es5'
};

Commit Code Standards (Husky, lint‑staged, Commitlint)

Install:

npm i husky lint-staged -D
npm i @commitlint/cli @commitlint/config-conventional -D

Create huskyrc.js:

module.exports = {
  hooks: {
    'commit-msg': 'commitlint -e $HUSKY_GIT_PARAMS',
    'pre-commit': 'lint-staged'
  }
};

Create lint-staged.config.js:

module.exports = {
  '{src,test}/**/*.ts': ['npm run lint', 'git add']
};

Create commitlint.config.js:

module.exports = {
  extends: ["@commitlint/config-conventional"],
  rules: {
    'subject-case': [2, 'always', ['upper-case']]
  }
};

Jest Testing

Jest provides fast parallel test execution, powerful mocking, built‑in coverage, DOM testing via JSDOM, and works with TypeScript via ts-jest. Install:

npm i jest @types/jest ts-jest -D

Create jest.config.js:

module.exports = {
  roots: ['<rootDir>/test'],
  transform: { '.(ts|tsx)': 'ts-jest' },
  testEnvironment: 'node',
  testRegex: '(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$',
  collectCoverage: true,
  coveragePathIgnorePatterns: ['/node_modules/', '/test/'],
  coverageThreshold: {
    global: { branches: 90, functions: 95, lines: 95, statements: 95 }
  }
};

Create a sample test test/main.test.ts:

import Sum from '../src/main';

test('sum is right', () => {
  expect(Sum(1, 2)).toBe(10);
});

Add a test script to package.json:

"test": "jest"

Conclusion

This article explained the differences between Webpack and Rollup, demonstrated how to build a simple JavaScript library with Rollup, and incorporated TypeScript, ESLint, Prettier, Husky, Commitlint, and Jest to ensure code quality. The complete project is available on GitHub: https://github.com/turning1998/baselib .

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

TypeScriptJavaScriptJestRollupESLintPrettier
37 Mobile Game Tech Team
Written by

37 Mobile Game Tech Team

37 Mobile Game Tech Team

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.