| | |

Parcel 28 ๐Ÿ“ฆ Performance Analysis โ€” Bundle reports & build profiling

โฑ๏ธ Estimated read: 13 min | |

Parcel’s performance analysis has two distinct surfaces: the bundle report that tells you what the output contains, and the build trace that tells you where the time went. They are not the same tool, and they answer different questions. The bundle report is generated automatically at the end of a production build, and it is more accurate in Parcel 2 than it was in Parcel 1 because it is based on source maps and excludes the code that tree shaking and minification removed . The build trace is opt-in, it is written to a JSON file, and it is analysed with Perfetto or a SQL query rather than a treemap .

The bundle report is the first thing to check when the output is larger than expected. It shows the size of each bundle and the assets that compose it. The report is in the CLI output, and it is based on the source maps rather than the raw file sizes, which means a bundle that was tree-shaken down to a small fraction of its original code is reported at the smaller size . The second thing to check is the trace, which shows the time spent in each phase of the build and the plugins that consumed the most time.

Key point: The bundle report is automatic and CLI-based; it shows the composition and size of the output. The build trace is opt-in via --trace, it is a JSON file, and it is analysed with Perfetto for SQL-based queries of phase and plugin durations. The two are complementary: the report tells you what shipped, and the trace tells you why the build took as long as it did.


Why the two surfaces are separate

The bundle report problem. The output of a Parcel build is a set of bundles, and the report is the summary of what each bundle contains. The report is generated at the end of a production build, and it is more accurate in Parcel 2 because the source maps preserve the location information through the tree-shaking and minification steps . The report does not tell you which plugin took the most time; it tells you what the output looks like after all the plugins have run.

The build trace problem. The trace is a record of the build’s execution. It tracks the phasesโ€”building, bundling, packaging, optimizingโ€”and the plugins that were called in each phase, and how long each call took . The trace answers questions that the bundle report cannot: which plugin is the bottleneck, which file takes the longest to transform, and which phase dominates the build time. The trace is opt-in because the JSON file can be large, and the overhead is non-zero, though it is less expensive than a CPU sampling profile .

The analysis tool problem. The bundle report is a CLI output that a human reads. The trace is a JSON file that is analysed with Perfetto, which loads the data into an SQLite database and allows SQL queries against it . The trace is not a visualization in the way the bundle report is; it is a dataset that the developer queries. The parcel-plugin-bundle-visualiser is the third-party alternative that produces a treemap of the bundle contents, but it is a plugin for the older Parcel 1 and is not the official Parcel 2 surface .

The trade-off. The bundle report is free and automatic, but it only shows the output. The trace costs an opt-in flag and a large JSON file, but it shows the process. A project that is troubleshooting a large bundle uses the report first, and a project that is troubleshooting a slow build uses the trace first. The two tools are not interchangeable, and the audit is the discipline of using the right one for the question.


a. The bundle report and the composition audit

The bundle report is generated automatically when the production build completes. It is based on the source maps, which means the sizes are the post-tree-shaking and post-minification sizes rather than the pre-processing sizes . The report is in the CLI output, and it lists each bundle with its size and the assets that compose it.

# The production build generates the bundle report.
parcel build index.html

# The report appears at the end of the build output.
# It lists the bundles and their sizes.

The parcel-plugin-bundle-visualiser is the third-party treemap tool for a more visual composition analysis. It is installed as a dev dependency and generates a report.html file in the output directory when the production build runs. The treemap shows each asset as a rectangle proportional to its size, and the hover tooltip shows the asset’s path, size, and estimated gzip size .

# Install the visualizer (third-party, for a treemap view)
npm install --save-dev parcel-plugin-bundle-visualiser

# Run the production build.
parcel build index.html

# The report is at dist/report.html.

The visualizer is useful for finding the largest assets in the bundle, but it is not the official Parcel 2 analysis surface. The official surface is the CLI report, and the visualizer is the community tool for the treemap view.


b. The build trace and the phase audit

The build trace is enabled with the --trace flag. Parcel writes a JSON file to the project root and logs the filename when the build starts. The trace uses the Chrome Tracing Format, and it consists of complete events (ph: "X") with a timestamp, a duration, a category, and a name .

# Generate the trace.
parcel build index.html --trace

# Parcel logs the trace filename at the start of the build.
# The file is written to the project root.

The API form is the shouldTrace: true option plus the @parcel/reporter-tracer reporter in the additionalReporters array. The reporter is the component that writes the JSON file .

// The API form of the trace
import { Parcel } from '@parcel/core';

const bundler = new Parcel({
  entries: 'index.html',
  shouldTrace: true,
  additionalReporters: [
    {
      packageName: '@parcel/reporter-tracer',
      resolveFrom: __dirname,
    },
  ],
});

await bundler.run();

The trace is analysed with Perfetto, which is a Google tool designed for large traces and non-browser data. Perfetto loads the trace into an SQLite database, and the developer queries it with SQL. The Vite documentation provides the example queries for the phase breakdown and the plugin duration breakdown .

-- The phase breakdown query
select
  name, SUM(CAST(dur AS double)/1000/1000) as dur_ms
from
  slice s
where
  s.category = "Core"
group by name
order by dur_ms desc

The query returns the total duration for each core phaseโ€”building, bundling, packagingโ€”in milliseconds. The durations are the sampled time, which may exceed the wall time because Parcel is multi-threaded . The plugin query is the second useful query: it groups the events by category and name to show which plugins consumed the most time.

The --trace flag was added in Parcel 2.9.0, and it is the official profiling surface. The PARCEL_PROFILE environment variable is the older profiling mechanism, and it requires the inspector module, which is not available in every Node.js distribution . The --trace flag is the recommended approach for a build-phase analysis.


Complete Example Session

// ============================================
// PART 1: THE BUNDLE REPORT
// ============================================

// parcel build index.html
//
// The report is at the end of the CLI output.
// It is based on the source maps.
// It excludes the tree-shaken and minified code.
// The sizes are the post-processing sizes.

// ============================================
// PART 2: THE BUNDLE VISUALIZER
// ============================================

// npm install --save-dev parcel-plugin-bundle-visualiser
// parcel build index.html
//
// The report is at dist/report.html.
// The treemap shows the assets by size.
// The hover tooltip shows the path, size, and gzip estimate.

// ============================================
// PART 3: THE TRACE FLAG
// ============================================

// parcel build index.html --trace
//
// The trace JSON file is written to the project root.
// Parcel logs the filename at the start of the build.
// The file uses the Chrome Tracing Format.

// ============================================
// PART 4: THE API TRACE
// ============================================

// The API form:
import { Parcel } from '@parcel/core';

const bundler = new Parcel({
  entries: 'index.html',
  shouldTrace: true,
  additionalReporters: [
    { packageName: '@parcel/reporter-tracer', resolveFrom: __dirname },
  ],
});

await bundler.run();

// The shouldTrace option enables the events.
// The reporter writes the JSON file.

// ============================================
// PART 5: THE PERFETTO ANALYSIS
// ============================================

// Open the trace in Perfetto (ui.perfetto.dev).
// The trace is loaded into an SQLite database.
// The "Query (SQL)" function runs the queries.

// ============================================
// PART 6: THE PHASE BREAKDOWN QUERY
// ============================================

// The query for the phase breakdown:
select
  name, SUM(CAST(dur AS double)/1000/1000) as dur_ms
from
  slice s
where
  s.category = "Core"
group by name
order by dur_ms desc

// The result shows the building, bundling, packaging,
// and optimizing phases with their durations.

// ============================================
// PART 7: THE PLUGIN BREAKDOWN QUERY
// ============================================

// The query for the plugin breakdown:
select
  s.category, name, SUM(CAST(dur AS double)/1000/1000) as dur_ms
from
  slice s
where
  s.category = "transform"
group by name
order by dur_ms desc

// The result shows which transformers consumed the most time.

// ============================================
// PART 8: THE PARCEL_PROFILE ALTERNATIVE
// ============================================

// The older profiling mechanism:
// PARCEL_PROFILE=true parcel build index.html
//
// It requires the Node.js inspector module.
// It is not available in every Node.js distribution.
// The --trace flag is the recommended approach.

// ============================================
// PART 9: THE PERFORMANCE CONTEXT
// ============================================

// Parcel 2 uses SWC for the JavaScript transform.
// SWC is 20x faster than Babel .
// The scope hoisting linker operates on strings, not ASTs .
// The build is up to 10x faster than Parcel 1 .
// The trace shows where the remaining time is spent.

// ============================================
// PART 10: THE CHECKLIST
// ============================================

// [ ] The bundle report is checked after the production build.
// [ ] The visualizer is used for a treemap view if needed.
// [ ] The --trace flag is used for a build-phase analysis.
// [ ] The trace is opened in Perfetto.
// [ ] The phase breakdown query is run.
// [ ] The plugin breakdown query is run.
// [ ] The PARCEL_PROFILE alternative is used only if the inspector is available.

The ten parts covered the bundle report, the visualizer, the trace flag, the API trace, the Perfetto analysis, the phase query, the plugin query, the PARCEL_PROFILE alternative, the performance context, and the checklist. The through-line is that the bundle report is the output audit and the trace is the process audit.


Quick Reference

The bundle report

AspectDetail
GenerationAutomatic, production build
AccuracyBased on source maps, post-tree-shaking
OutputCLI report
Treemapparcel-plugin-bundle-visualiser (third-party)

The build trace

AspectDetail
Flag--trace
API optionshouldTrace: true
Reporter@parcel/reporter-tracer
FormatChrome Tracing Format (JSON)
Analysis toolPerfetto (SQL queries)

The key queries

QueryPurpose
Phase breakdownwhere category = "Core"
Plugin breakdownwhere category = "transform"

Best Practices

โœ… Do This:

# Check the bundle report after the production build
parcel build index.html                                           // โœ…

# Use the trace for a slow-build investigation
parcel build index.html --trace                                   // โœ…

# Analyse the trace in Perfetto with the phase query
// The query shows the dominant phase.                          // โœ…

โŒ Don’t Do This:

# Use PARCEL_PROFILE on a Node.js distribution without the inspector
PARCEL_PROFILE=true parcel build index.html // may fail           // โŒ

# Assume the bundle report shows the pre-minification sizes
// The report is based on the source maps.                       // โŒ

Common Pitfalls

PitfallWhy It HappensFix
The trace file is hugeThe trace records every eventUse it for targeted investigations, not every build
PARCEL_PROFILE failsThe inspector module is unavailableUse --trace instead
The bundle report is inaccurateThe source maps are disabledEnsure the source maps are generated
The plugin query returns nothingThe category name is wrongUse the transform category

Real-World Examples

1. The bundle report

parcel build index.html

2. The visualizer

npm install -D parcel-plugin-bundle-visualiser && parcel build index.html

3. The trace

parcel build index.html --trace

4. The API trace

new Parcel({ shouldTrace: true, additionalReporters: [{ packageName: '@parcel/reporter-tracer', resolveFrom: __dirname }] })

5. The phase query

select name, SUM(CAST(dur AS double)/1000/1000) as dur_ms from slice s where s.category = "Core" group by name order by dur_ms desc

6. The plugin query

select s.category, name, SUM(CAST(dur AS double)/1000/1000) as dur_ms from slice s where s.category = "transform" group by name order by dur_ms desc

7. The Perfetto URL

https://ui.perfetto.dev/

8. The PARCEL_PROFILE alternative

PARCEL_PROFILE=true parcel build index.html

9. The visualizer output

dist/report.html

10. The trace output

parcel-trace-<timestamp>.json

Visual

The Two Analysis Surfaces

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  BUNDLE REPORT VS BUILD TRACE                                 โ”‚
โ”‚                                                              โ”‚
โ”‚  Bundle report              Build trace                      โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”         โ”‚
โ”‚  โ”‚ What shipped        โ”‚   โ”‚ Where the time went โ”‚         โ”‚
โ”‚  โ”‚ Automatic           โ”‚   โ”‚ Opt-in (--trace)    โ”‚         โ”‚
โ”‚  โ”‚ CLI output          โ”‚   โ”‚ JSON file           โ”‚         โ”‚
โ”‚  โ”‚ Source-map based    โ”‚   โ”‚ Perfetto analysis   โ”‚         โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜         โ”‚
โ”‚                                                              โ”‚
โ”‚  The report audits the output.                              โ”‚
โ”‚  The trace audits the process.                              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

The Trace Analysis Flow

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  FROM TRACE TO QUERY                                          โ”‚
โ”‚                                                              โ”‚
โ”‚  parcel build --trace                                        โ”‚
โ”‚         โ”‚                                                    โ”‚
โ”‚         โ–ผ                                                    โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                    โ”‚
โ”‚  โ”‚ The trace JSON file โ”‚  Chrome Tracing Format             โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                    โ”‚
โ”‚             โ”‚                                                โ”‚
โ”‚             โ–ผ                                                    โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                    โ”‚
โ”‚  โ”‚ Perfetto            โ”‚  Loads into SQLite                 โ”‚
โ”‚  โ”‚ ui.perfetto.dev     โ”‚                                    โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                    โ”‚
โ”‚             โ”‚                                                โ”‚
โ”‚             โ–ผ                                                    โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                    โ”‚
โ”‚  โ”‚ SQL query           โ”‚  Phase breakdown                   โ”‚
โ”‚  โ”‚                     โ”‚  Plugin breakdown                  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                    โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

The Phase Breakdown

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  THE QUERY SHOWS THE DOMINANT PHASE                           โ”‚
โ”‚                                                              โ”‚
โ”‚  Building:   โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ  1200ms        โ”‚
โ”‚  Bundling:   โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ                           300ms        โ”‚
โ”‚  Packaging:  โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ                             200ms        โ”‚
โ”‚  Optimizing: โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ                     500ms        โ”‚
โ”‚                                                              โ”‚
โ”‚  The building phase dominates.                              โ”‚
โ”‚  The plugin query shows which transformer is responsible.   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Summary

ItemValue
Bundle reportAutomatic, source-map based, CLI output
Treemapparcel-plugin-bundle-visualiser (third-party)
Build trace--trace flag, JSON file
Trace formatChrome Tracing Format
Analysis toolPerfetto (SQL queries)
Phase querywhere category = "Core"
Plugin querywhere category = "transform"
Older profilingPARCEL_PROFILE (requires inspector)

Key takeaways:

  • The bundle report and the build trace answer different questions. The bundle report is the composition audit: it shows what the output contains and how large each bundle is. It is automatic, it is based on the source maps, and it excludes the tree-shaken and minified code . The build trace is the process audit: it shows where the time went, which phases dominated, and which plugins consumed the most time .
  • The trace is opt-in and Perfetto-analysed. The --trace flag writes a JSON file in the Chrome Tracing Format, and the file is opened in Perfetto, which loads it into an SQLite database. The SQL queries for the phase breakdown and the plugin breakdown are the two starting points .
  • The PARCEL_PROFILE variable is the older mechanism. It requires the Node.js inspector module, which is not available in every distribution. The --trace flag is the recommended approach for a build-phase analysis .
  • The visualizer is the third-party treemap tool. parcel-plugin-bundle-visualiser generates a report.html with a treemap of the bundle contents, and it is useful for a visual composition audit. It is not the official Parcel 2 analysis surface .
  • The performance context is the SWC rewrite. Parcel 2 uses SWC for the JavaScript transform, which is 20ร— faster than Babel, and the scope hoisting linker operates on strings rather than ASTs. The build is up to 10ร— faster than Parcel 1, and the trace shows where the remaining time is spent .

Remember: Parcel’s performance analysis has two tools: the bundle report and the build trace. The bundle report is automatic and shows what shipped. The build trace is opt-in and shows where the time went. The report is the CLI output; the trace is a JSON file analysed in Perfetto. The report is for the composition audit; the trace is for the phase and plugin audit. The two are complementary, and the audit is the discipline of using the right one for the question.

Was this helpful?


Stop using slow, ad-bloated tool sites! ๐Ÿคฎ

๐Ÿ”Ž Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
โœ… Finance (Mortgage, Interest, Inflation)
โœ… Tech (Base64, JSON, Dev Suite, IP)
โœ… Health (BMI, BMR, TDEE)
โœ… Productivity (Timer, Workspace, QR)

โšก๏ธ Fast & Private
๐Ÿ”’ No data leaves your device
๐Ÿ’Ž 100% Free

๐Ÿ”— Use it now: https://tools.kandz.me
๐Ÿ”– Bookmark itโ€”youโ€™ll need it later!