No results

    Search failed

    npm GitHub

    Poops vs webpack, Rollup & Parcel

    The webpack config that nobody on the team can read is a genre. It starts as twenty lines, acquires a loader for Sass, a loader for the loader, a plugin to extract the CSS the loaders just inlined, a resolve.alias block, and a comment saying do not touch this, it took a day. Two years later the project is a landing page with a contact form, and the toolchain has more dependencies than the site has pages.

    Poops is the reaction to that: in, out, options โ€” and no place for that config to grow into.

    Where the three stand

    All read from npm in August 2026:

    Latest Notes
    webpack 5.109.x actively maintained; the 2026 roadmap targets native CSS support, built-in TypeScript and a path to webpack 6
    Rollup 4.62.x frequent releases; still the reference for library bundling, and the plugin API Rolldown kept
    Parcel 2.16.x zero-config by design; last release six months before this page was written
    Rspack 2.x not compared here โ€” a Rust, webpack-compatible bundler, and the thing to look at if the reason you are reading this page is webpack is slow

    Feature by feature

    Poops webpack Rollup Parcel
    Config one JSON file webpack.config.js, loaders + plugins rollup.config.js, plugins none for the common case
    Learning surface the keys in the config reference loaders, rules, plugins, resolve, optimization plugin lifecycle hooks its conventions, when you need to leave them
    Escape hatch esbuild options pass through a loader or plugin a plugin a .parcelrc transformer
    Sass built in sass-loader + css-loader + MiniCssExtractPlugin a plugin built in
    PostCSS / Tailwind own config key postcss-loader a plugin built in
    HTML pages, layouts, front matter built in, Nunjucks or Liquid html-webpack-plugin, one page at a time no entry HTML, no templating
    Collections, taxonomies, RSS, sitemap, search index built in no no no
    Content hashing + HTML rewriting no yes via plugins yes
    Code splitting esbuild's splitting โ€” hashed chunks, but no manifest and no HTML rewriting yes, SplitChunksPlugin yes, and precise yes
    Module federation no yes โ€” its own territory no no
    Tree-shaken library output esbuild's, three entries for IIFE/ESM/CJS yes the best of the four for this yes
    Dev experience rebuild + reload; CSS swapped in place dev server with HMR plugin-provided watch dev server with HMR
    Dependencies you install 18 direct, 41 packages webpack + cli + loaders + plugins rollup + plugins parcel

    The same job, spelled out

    Bundle a TypeScript entry, compile SCSS beside it, minify both, keep sourcemaps on the unminified twin. In webpack that is ts-loader (or babel-loader plus a preset), sass-loader โ†’ css-loader โ†’ MiniCssExtractPlugin.loader, a rules array to wire them to extensions, the plugin in plugins, and optimization.minimizer for the CSS half. In Poops it is the file itself:

    {
      "scripts": [{
        "in": "src/js/main.ts",
        "out": "dist/js/main.js",
        "options": { "minify": true, "sourcemap": true, "format": "iife", "target": "es2019" }
      }],
      "styles": [{
        "in": "src/scss/index.scss",
        "out": "dist/css/styles.css",
        "options": { "minify": true, "sourcemap": true }
      }]
    }

    Both emit main.js + main.min.js and styles.css + styles.min.css. The difference is that the second one has no loader order to get wrong, and the $schema reference at the top of the file makes the editor complete every key โ€” a typo is caught as you type it rather than at build time.

    Add "markup" and the same file also builds the pages, which is the part webpack, Rollup and Parcel were never trying to do.

    The part Poops refuses

    There is no plugin API and there will not be one. A feature that fits in a few lines of config does not get an extension point, and one that does not fit gets argued about in an issue instead. That refusal is the whole design: it is why the dependency list is boring, why the config is JSON, and why there is no version of this project where you write a poops.config.js that imports four packages.

    The cost is real and it is exactly webpack's strength: when Poops does not do something, you cannot bolt it on. A custom transform for a file type nobody has heard of is a loader in webpack and a fork in Poops โ€” or a markup engine, which is the one interface left open, because a template language is a whole job rather than a hook.

    Use webpack, Rollup or Parcel when

    If Use Why
    You need module federation or a micro-frontend split webpack Nothing else here does it
    You publish a library and want the smallest, cleanest ESM output with precise external control Rollup It has been the reference for a decade, and Poops' esbuild output is fine but blunter
    You want zero config for an app with many asset types Parcel Its conventions cover more file types than Poops does
    The existing config works and nobody is fighting it leave it A migration you do not need is a bug you introduce
    webpack is only slow Rspack, or Vite Both are drop-in-ish and Rust-fast; Poops is a different tool, not a faster webpack

    Use Poops when

    • The project is a site with a front end: pages, SCSS and TypeScript in one config, one command, plain files out.
    • The build should be readable by whoever picks the project up next year โ€” including you. JSON, no imports, with $schema completing the keys in the editor.
    • You want the toolchain to be one dependency instead of a bundler plus five loaders plus three plugins that have to agree on versions.
    • Nobody on the team wants to own a webpack.config.js again.

    The size of the JavaScript is not the deciding factor โ€” esbuild handles large bundles fine. What decides it is whether you need managed chunks, a manifest and federation, or whether you need the config to stay small enough to read.