parcel icon indicating copy to clipboard operation
parcel copied to clipboard

Slow hot reload builds in Parcel v2

Open elliottkember opened this issue 4 years ago â€ĸ 17 comments

🐛 bug report

Hi all! Loving Parcel. Very excited about Parcel 2.

My Parcel 1 app is hot-reloading very slowly in Parcel 2. The reason I'm upgrading is that Parcel 1 sits at about 100-110% CPU usage even when not compiling my app. Parcel 2 doesn't do this at all (yay) but compilation time for hot module reloads has gone from 200ms to 4.0s (oh no).

We have a fairly big application, lots of files and modules, but nothing that I would consider unreasonably big. Around 777 JS files in our src directory.

I don't actually know how to debug this compilation speed problem. I'm not sure whether this is something with our Babel setup, whether I need to update a module, or whether my targets are set up incorrectly (I'm using the default >0.25%).

(P.S. I've tested the Parcel 1 100% CPU problem with a dummy app containing 1,000 files - and as I add more and more files to the app, the CPU usage goes up. At 1,000 files it's somewhere between 50-60%.)

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

This is my .parcelrc:

{
  "extends": "@parcel/config-default",
  "transformers": {
    "*.svg": ["@parcel/transformer-svg-react", "@parcel/transformer-js"],
    "*.png": ["@parcel/transformer-raw"],
    "*.jpg": ["@parcel/transformer-raw"],
    "*.graphql": ["parcel-transformer-graphql-ast"],
  }
}

This is my babel.config.js:

module.exports = function(api) {
  api.cache(true);

  const presets = ['@babel/preset-react'];

  if (process.env['NODE_ENV'] === 'test') {
    presets.push([
      '@babel/preset-env',
      { modules: 'commonjs', targets: { node: 'current' } },
    ]);
  }

  const plugins = [
    [
      'auto-import',
      {
        declarations: [
          {
            default: 'React',
            path: 'react',
            members: ['useState', 'useEffect', 'useContext', 'useRef'],
          },
          { default: 'PropTypes', path: 'prop-types' },
          { default: 'classnames', path: 'classnames' },
          {
            default: 'withStyles',
            path: '@material-ui/core/styles/withStyles',
          },
        ],
      },
    ],
    [
      'babel-plugin-root-import',
      {
        paths: [
          { rootPathPrefix: '~', rootPathSuffix: 'src' },
          { rootPathPrefix: '#', rootPathSuffix: 'test' },
        ],
      },
    ],
    [
      'transform-inline-environment-variables',
      {
        include: [
          'CONTACT_SALES_FORM_ID',
          'CONTACT_SUCCESS_FORM_ID',
          'SENTRY_FRONTEND_DSN',
        ],
      },
    ],
    '@babel/plugin-syntax-import-meta',
    '@babel/plugin-proposal-class-properties',
    '@babel/plugin-proposal-function-sent',
    '@babel/plugin-proposal-export-namespace-from',
    '@babel/plugin-proposal-numeric-separator',
    '@babel/plugin-proposal-optional-chaining',
    '@babel/plugin-proposal-throw-expressions',
  ];

  return {
    presets,
    plugins,
  };
};

If anybody has any suggestions on where I should be looking, I'd love to get to the bottom of this, in case anybody else sees the same thing.

🤔 Expected Behavior

It should be wicked fast! Parcel 1 was very fast, although it did seem to hog a single CPU core at 100% for our application.

đŸ˜¯ Current Behavior

Hot module reloading builds in Parcel 1 took ~200ms, and the same type of builds in Parcel 2 take anywhere between 2-4 seconds.

A hot reload looks like:

yarn run v1.22.4
$ NODE_ENV=development parcel index.html --no-autoinstall --public-url /dist
ℹī¸ Server running at http://localhost:1234
✨ Built in 4.32s

Parcel 1: ezgif-4-298363069598

Parcel 2: ezgif-4-19704afae25c

🌍 Your Environment

Software Version(s)
Parcel 2.0.0-beta.1
Node v13.14.0
npm/Yarn yarn 1.22.4
Operating System macOS

elliottkember avatar Sep 09 '20 20:09 elliottkember

babel.config.js

That is detrimental at least for production builds. I think every JS file is being reprocessed. Could you try to use a babel.config.json with an env key instead? https://babeljs.io/docs/en/6.26.3/babelrc#env-option

mischnic avatar Sep 09 '20 21:09 mischnic

Also: can you try to adding --no-hmr and seeing if the "Built in ..." time is faster? Trying to isolate the cause....

mischnic avatar Sep 09 '20 21:09 mischnic

I moved to a babel.config.json file without any change in hot reloading times, and adding --no-hmr gives me Built in 3.69s, ranging between 3 and 8 seconds. I don't know quite what reprocessing all the files entails, so that might be happening, but at least it only shows Building index.js.... The little loading spinner in the command line prompt stops turning during that step.

elliottkember avatar Sep 09 '20 23:09 elliottkember

@mischnic I figured out the problem with Parcel 1 - it was that fsevents is an optional dependency for chokidar which is used for the file watcher - after I installed fsevents@1, parcel 1 is lightning fast. I haven't found a way for yarn to install fsevents - it ignores it as an optionalDependency and I don't know why. Probably because it's very old.

elliottkember avatar Sep 09 '20 23:09 elliottkember

You probably can't share your code?

Are you using the most recent nightly?

You can run Parcel with --profile which emits a file that can be loaded into Chrome devtools and shows a flamegraph of all operations.

mischnic avatar Jul 07 '21 07:07 mischnic

@mvpix is that showing a build after editing a single file, or is that a fresh build of your whole app? Any more info you can provide that could help?

devongovett avatar Jul 12 '21 05:07 devongovett

This sounds almost exactly like an issue I'm also having. I'm also using React on Mac with Parcel 2, it can take upwards of 100 seconds to build my app (quite large app, but Parcel 1 did it blazingly fast).

justinfarrelldev avatar Jul 30 '21 05:07 justinfarrelldev

@justinfarrelldev Can you share more details? Is this with/without cache, development/production build? A profile via parcel build --profile would also be interesting

mischnic avatar Aug 01 '21 13:08 mischnic

@mischnic In trying to get you the profiling info, I actually realized my version of Parcel was different and quite old, going up to 1.12.3 fixed my problem. Thank you though!

justinfarrelldev avatar Aug 01 '21 14:08 justinfarrelldev

I have the same problem on my end. HMR is very slow, about 5s to 10s ([email protected])

vcarel avatar Nov 22 '21 14:11 vcarel

There's still nothing we can do here without a reproduction.

mischnic avatar Nov 22 '21 14:11 mischnic

It says "building", "bundling", "packaging", "optimizing". All those step take equal time, except bundling, which is faster.

If I reduce the size of my project to... 1 file, it takes 300 to 500ms to build. But the project is quite big (387 ts and js files, 98 .module.scss files). Maybe it's just that?

For the record, the built files are quite big too:

-rw-rw-r-- 1 vianney vianney  18M nov.  22 18:06 index.8c718e25.js
-rw-rw-r-- 1 vianney vianney  24M nov.  22 18:06 index.8c718e25.js.map
-rw-rw-r-- 1 vianney vianney 602K nov.  22 18:06 index.f8b2c0e1.css
-rw-rw-r-- 1 vianney vianney 258K nov.  22 18:06 index.f8b2c0e1.css.map

vcarel avatar Nov 22 '21 17:11 vcarel

Indeed, a build of

import * as fluent from "@fluentui/react";
import * as spectum from "@adobe/react-spectrum";
import * as antd from "antd";
import * as moment from "moment";
import * as React from "react";
import * as ReactDOM from "react-dom";

console.log(fluent, spectum, antd, moment, React, ReactDOM);
console.log(2) // change to different number

is a 9.4mb bundle and takes 2-3s to build after a trivial change.

Bundling takes 1.1s (we are already working on speeding that part up) Something like https://github.com/parcel-bundler/parcel/issues/4143 would help, because for many basic changes, only the single changed asset is needed in the browser, not the whole new bundle.

mischnic avatar Nov 22 '21 22:11 mischnic

@mischnic I am having the same Issue adding changing one line takes 8s to rebuild on a quite big project.

How can I send you the profile?

mkaraula avatar Nov 23 '21 09:11 mkaraula

I also ran into this when trying to convert an app to parcel - in our case, it typically takes about 10s for parcel to rebuild after changing just a single file. In the case of the trace below it actually took 15s (maybe unlucky, maybe overhead?)

Here's the trace: profile-20220731-134852.trace.zip

dsgkirkby avatar Jul 31 '22 20:07 dsgkirkby

@dsgkirkby This applies to you as well: https://github.com/parcel-bundler/parcel/issues/4143#issuecomment-997528950

"bundling" takes the most time in your case.

If you want to try the new bundler right now, do this: https://github.com/parcel-bundler/parcel/issues/5772#issuecomment-1133377231 (you don't have to necessarily use the nightly version)


How can I send you the profile?

Using parcel index.html --profile.

mischnic avatar Jul 31 '22 21:07 mischnic

@mischnic Thanks for the reply! I tried this (v2.6.2, the nightlies cause errors because some of their deps are for a nightly that's 2.0.0-something) and it improved things a decent amount - incremental builds are now ~5-6s, though this is still a bit slower than the 1-3s I'm used to with webpack. It also fixed https://github.com/parcel-bundler/parcel/issues/8350 which I ran into with the default bundler!

However, the experimental bundler isn't including a bunch of my CSS (seems like everything that's in index-dev.[hash].css in the older bundler) on the page so lots of my styles are broken - is there somewhere I should file that bug?

dsgkirkby avatar Jul 31 '22 21:07 dsgkirkby

Should be a lot faster in v2.8. https://parceljs.org/blog/v2-8-0/

devongovett avatar Nov 27 '22 05:11 devongovett