Parcel2 v. Webpack – parcel bundle size is significantly larger

🐛 bug report

I’ve started trying to use Parcel2 in a real-life situation, and I’m noticed that the parcel bundle size (1.1MB) is significantly larger than webpack’s (666 KiB) for the same app. (It’s also significantly slower – see #4566).

Like all real-life situations, it’s complicated, so I tried to create a simplified repro environment in the fluentui-button-babel branch of this repo. It’s a simple react app with a single Button component from the @fluentui/react-northstar library. This library is alpha-quality, and there’s known issues about bundle size that the team is trying to address. However, webpack still does a significantly better job than parcel right now. The main driver seems to be that this optimization that the library authors made is picked up by webpack but not by parcel.

🎛 Configuration (.babelrc, package.json, cli command)

Webpack (full config here):

  • Using babel-loader with this config:
presets: [
   "@babel/preset-env",
   "@babel/preset-react",
   "@babel/preset-typescript",
]

Parcel configuration:

  • No .parcelrc file, which means that the default babel transformer is being used.
  • No custom babel configuration.
  • Ran parcel build src/index.html

src/index.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Sample App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <script src="./index.tsx"></script>
  </body>
</html>

src/index.tsx:

import React from "react";
import ReactDOM from "react-dom";
import App from "./components/App";

ReactDOM.render(<App />, document.getElementById("root"));

src/components/App.ts:

import React from "react";
import { Provider, themes, Button } from "@fluentui/react-northstar";

const App = () => (
  <Provider theme={themes.teams}>
    <Button content="Hello from FluentUI" />
  </Provider>
);

export default App;

🤔 Expected Behavior

Parcel and webpack build size should be roughly the same (or maybe Parcel should be better 😄).

😯 Current Behavior

Here’s the bundle size comparison:

Scenario Bundle Size
Build with parcel (default babel config with scope-hoisting and minification) 1.11 MB
Build with webpack (babel-loader with scope-hoisting and minification) 660 KiB
Build with webpack (ts-loader with module: es6 with scope-hoisting and minification) 660 KiB
Build with webpack (ts-loader with module: commonjs with scope-hoisting and minification) 1.21 MB

💁 Possible Solution

By using source-map-explorer and a custom node script, I generated a visualization of the stuff that is in the parcel bundle, but not the webpack bundle:

image

You can see that the main driver of the increased size are icons from the @fluentui/react-icons-northstar. The fluentui team recently made an optimization to allow webpack to tree-shake these icons, and it seems that it works with webpack, but not with parcel.

I’m not sure why this is happening – most likely something at the scope-hoisting phase that doesn’t like the way this library was written. Even if there’s something the library authors could do to improve this, it seems like a good goal to do our best to make sure that libraries that are optimized for webpack remain optimized with parcel.

🔦 Context

Trying to build a real-world app that uses @fluentui/react-northstar and parcel2.

💻 Code Sample

See the fluentui-button-babel branch of this repo.

🌍 Your Environment

Software Version(s)
Parcel 2.0.0-nightly.248
Node 12.16.3
Yarn 1.22.4
Operating System OSX 10.15.4

1 possible answer(s) on “Parcel2 v. Webpack – parcel bundle size is significantly larger

  1. I have implemented the fix and the bundle size is 632kb compared to Webpack’s 635kb, will open a PR after more testing.

    (But 600kb is still massive for a single Button)