From 575202fe09df0ceb2b59585d87712a82618febc2 Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Sat, 5 Nov 2022 14:10:31 -0700 Subject: [PATCH 1/5] Draft blog post for v2.8 --- src/blog/v2-8-0/v2-8-0.md | 56 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 src/blog/v2-8-0/v2-8-0.md diff --git a/src/blog/v2-8-0/v2-8-0.md b/src/blog/v2-8-0/v2-8-0.md new file mode 100644 index 00000000..928afadb --- /dev/null +++ b/src/blog/v2-8-0/v2-8-0.md @@ -0,0 +1,56 @@ +--- +layout: layout.njk +title: Parcel v2.8.0 +eleventyNavigation: + key: blog-parcel-2-8-0 + title: Parcel v2.8.0 +date: 2022-11-09 +--- + +We are excited to announce the release of Parcel v2.8.0! This release includes a brand new bundling algorithm with improved automatic code splitting, much better build performance for large projects, and fixes for many bugs. It also includes major performance improvements for HMR updates, and tree shaking changes that we've seen reduce bundle sizes by up to 50%. + +## New bundling algorithm + +Since our initial v2 release, Parcel has supported [automatic code splitting](/features/code-splitting/#shared-bundles), which deduplicates shared modules between multiple parts of your app (e.g. pages, dynamic imports, etc.). This allows commonly used dependencies like React or a design system to be cached independently from application code, reducing the amount of code that must be loaded when navigating between pages. Because it is automatic, it doesn't need to be configured or updated manually by developers, keeping your app optimal as you make changes. + +Our initial implementation worked well on small to medium size projects, but hit scalability issues on larger projects. The algorithm involved many nested graph traversals (quadratic time complexity), and often ended up doing work which was later undone. In addition, the implementation was somewhat buggy, sometimes resulting in unnecessary duplication, or even missing modules. + +The team at Atlassian has contributed a new bundling algorithm that solves these problems, significantly improving both build time and runtime performance. It takes a different approach than the previous implementation: rather than initially placing all assets into bundles based on manual code split points (e.g. dynamic import) and then removing duplication afterward, it starts with a graph containing no duplication (each asset is in only one bundle) and then combines bundles as needed to meet constraints like parallel request limits and minimum bundle size requirements. It also reduces time complexity by pre-computing more information and removing nested graph traversals. + +This results in both smaller bundles and much faster builds. For a very large project, overall build time was reduced from over 25 minutes to 9 minutes (**2.7x faster**). The total bundle size for the whole project went from 952 MB to 370 MB (**2.5x smaller**). + +We've been working on this new bundling algorithm for a long time, and we're excited to finally make it the default in this release. Huge thanks to the Atlassian team for contributing this improvement! + +## HMR rebuild performance + +In addition to improving bundling performance, we have also been working on making incremental rebuilds and HMR updates even faster. This release includes three new features in this area: incremental bundling, single threaded compilation, and earlier HMR updates. + +Some tools avoid bundling entirely in development by utilizing ESM in the browser to send each module individually. This means when a file changes, only that one file needs to be transformed, rather than recomputing the entire bundle. However, for large projects with many modules, this approach means the browser must make hundreds or even thousands of cascading HTTP requests on page load. Additionally, when performing an HMR update, the updated file and all recursive dependent modules must be reloaded, since there is no way to invalidate a single module in the ESM registry. This slows down updates for large projects with deep module graphs. + +Parcel already has a development-only packager which does a lot less work than the production one (e.g. no tree shaking), but for large apps, the bundling algorithm described above could still be a bottleneck. However, most code changes are fairly simple – they affect only a single file, without adding or removing any dependencies. In these cases rebundling is unnecessary, and Parcel can now simply update the asset in place without rerunning the entire bundling algorithm. In addition, Parcel now compiles and packages on the main thread when only a single file changed to avoid the cost of serializing the bundle graph to send between threads. + +This incremental bundling can make a huge difference – for example, rebuild times for the large project described above were reduced from 40 seconds to 4 seconds (**10x faster**)! + +In addition, Parcel now sends HMR updates to the browser over a websocket before packaging bundles is even complete. Our custom development-only module format enables us to re-evalutate the changed modules and swap them in place with no additional network requests necessary. This effectively means HMR updates require the same amount of work as if they were not bundled, while avoiding network waterfalls during both page load and HMR updates. + +We've been benchmarking our end-to-end HMR update performance versus other tools. The results speak for themselves: + +~~ TODO ~~ + +## Tree shaking improvements + +This release also includes improvements to tree shaking with code splitting. Previously, if you used a large library containing an index file with many re-exports, Parcel would always place all of the used exports in the same bundle. For example, if you used different components from a component library on different pages or code split points (e.g dynamic import), all used components across your whole project would be placed into the entry bundles. This could mean loading much more JavaScript than necessary on initial page load. + +Parcel now rewrites dependencies to point to their final destinations, following all re-exports found along the way. This means re-exports now have no effect on code splitting, and only used exports within each bundle are loaded. In many applications, this means the entry bundle will become much smaller since more code will only be loaded when needed. + +Results will depend on how many re-exports you rely on and your code splitting setup, but we have seen impressive results in several applications so far. One very large app saw over **40% smaller JS entry bundles**, while another saw a 25% smaller JS entry and 50% smaller CSS. + +Thanks to [Niklas Mischkulnig](https://twitter.com/mischnic) for contributing this improvement! + +## Thanks! + +Parcel v2.8.0 includes several other smaller features, bug fixes, and improvements. Check out the full [release notes]() for more details. + +- [GitHub](https://github.com/parcel-bundler/parcel) +- [Discord community](https://discord.gg/XSCzqGRuvr) +- [Support us on Open Collective](https://opencollective.com/parcel) From bb937bc99f280910fbc668c517de6b1cc1177c5f Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Sat, 5 Nov 2022 17:54:13 -0700 Subject: [PATCH 2/5] Add benchmark results --- src/blog/v2-8-0/v2-8-0.md | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/blog/v2-8-0/v2-8-0.md b/src/blog/v2-8-0/v2-8-0.md index 928afadb..d9357ae5 100644 --- a/src/blog/v2-8-0/v2-8-0.md +++ b/src/blog/v2-8-0/v2-8-0.md @@ -25,17 +25,25 @@ We've been working on this new bundling algorithm for a long time, and we're exc In addition to improving bundling performance, we have also been working on making incremental rebuilds and HMR updates even faster. This release includes three new features in this area: incremental bundling, single threaded compilation, and earlier HMR updates. -Some tools avoid bundling entirely in development by utilizing ESM in the browser to send each module individually. This means when a file changes, only that one file needs to be transformed, rather than recomputing the entire bundle. However, for large projects with many modules, this approach means the browser must make hundreds or even thousands of cascading HTTP requests on page load. Additionally, when performing an HMR update, the updated file and all recursive dependent modules must be reloaded, since there is no way to invalidate a single module in the ESM registry. This slows down updates for large projects with deep module graphs. +Some tools avoid bundling entirely in development by utilizing ESM in the browser to load each module individually. This means when a file changes, only that one file needs to be transformed, rather than recomputing the entire bundle. However, for large projects with many modules, this approach means the browser must make hundreds or even thousands of cascading HTTP requests on page load. Additionally, when performing an HMR update, the browser must make a network request to reload each updated file. Dependent modules must also be manually updated since there is no way of invalidating a module in the ESM module registry. -Parcel already has a development-only packager which does a lot less work than the production one (e.g. no tree shaking), but for large apps, the bundling algorithm described above could still be a bottleneck. However, most code changes are fairly simple – they affect only a single file, without adding or removing any dependencies. In these cases rebundling is unnecessary, and Parcel can now simply update the asset in place without rerunning the entire bundling algorithm. In addition, Parcel now compiles and packages on the main thread when only a single file changed to avoid the cost of serializing the bundle graph to send between threads. +Parcel already has a development-only packager which does a lot less work than the production one (e.g. no tree shaking), but for large apps, the bundling algorithm described above could still be a bottleneck. However, most code changes are fairly simple – they affect only a single file, without adding or removing any dependencies. In these cases rebundling is unnecessary, and Parcel can now simply update the asset in place without rerunning the entire bundling algorithm. In addition, Parcel now compiles and packages on the main thread when only a single file changed to avoid the cost of serializing the bundle graph to send between workers. This incremental bundling can make a huge difference – for example, rebuild times for the large project described above were reduced from 40 seconds to 4 seconds (**10x faster**)! -In addition, Parcel now sends HMR updates to the browser over a websocket before packaging bundles is even complete. Our custom development-only module format enables us to re-evalutate the changed modules and swap them in place with no additional network requests necessary. This effectively means HMR updates require the same amount of work as if they were not bundled, while avoiding network waterfalls during both page load and HMR updates. +In addition, Parcel now sends HMR updates to the browser over a websocket before packaging bundles is even complete. Our custom development-only module format enables us to re-evalutate the changed modules and swap them in place with no additional network requests necessary. This effectively means HMR updates require the same amount of work as if they were not bundled, scaling with the size of the changes rather than size of the project, and avoiding network waterfalls during page load. -We've been benchmarking our end-to-end HMR update performance versus other tools. The results speak for themselves: +We've been benchmarking our end-to-end HMR update performance versus other tools. The following results show the time from saving a file to seeing updates in the browser for a React app with 1000 components: -~~ TODO ~~ +| | Vite | Turbopack | Parcel | +| -------- | ------- | --------- | ---------- | +| **Root** | 293.5ms | 274.8ms | **88.6ms** | +| **Leaf** | 143.8ms | 57ms | **37.4ms** | + +- Parcel is 68% faster than Turbopack, and 70% faster than Vite at updating the root component. +- Parcel is 34% faster than Turbopack, and 74% faster than Vite at updating the leaf component. + +See [this repo](https://github.com/devongovett/parcel-vs-vite-vs-turbopack-hmr) for full benchmark source code and results. ## Tree shaking improvements From 01f5612298d7b0027cf60fa79be21c6e2f082134 Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Sun, 6 Nov 2022 18:39:33 -0800 Subject: [PATCH 3/5] Add size details and webpack comparison --- src/blog/v2-8-0/v2-8-0.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/blog/v2-8-0/v2-8-0.md b/src/blog/v2-8-0/v2-8-0.md index d9357ae5..f65ed955 100644 --- a/src/blog/v2-8-0/v2-8-0.md +++ b/src/blog/v2-8-0/v2-8-0.md @@ -15,9 +15,9 @@ Since our initial v2 release, Parcel has supported [automatic code splitting](/f Our initial implementation worked well on small to medium size projects, but hit scalability issues on larger projects. The algorithm involved many nested graph traversals (quadratic time complexity), and often ended up doing work which was later undone. In addition, the implementation was somewhat buggy, sometimes resulting in unnecessary duplication, or even missing modules. -The team at Atlassian has contributed a new bundling algorithm that solves these problems, significantly improving both build time and runtime performance. It takes a different approach than the previous implementation: rather than initially placing all assets into bundles based on manual code split points (e.g. dynamic import) and then removing duplication afterward, it starts with a graph containing no duplication (each asset is in only one bundle) and then combines bundles as needed to meet constraints like parallel request limits and minimum bundle size requirements. It also reduces time complexity by pre-computing more information and removing nested graph traversals. +The team at Atlassian has contributed a new bundling algorithm that solves these problems, significantly improving both build time and runtime performance. It takes a different approach than the previous implementation: rather than initially placing all assets into bundles based on manual code split points (e.g. dynamic import) and then removing duplication afterward, it starts with a graph containing no duplication (each asset is in only one bundle). It then combines bundles as needed to meet constraints like parallel request limits and minimum bundle size requirements. It also reduces time complexity by pre-computing more information and removing nested graph traversals. -This results in both smaller bundles and much faster builds. For a very large project, overall build time was reduced from over 25 minutes to 9 minutes (**2.7x faster**). The total bundle size for the whole project went from 952 MB to 370 MB (**2.5x smaller**). +This results in both smaller bundles and much faster builds. For a very large real-world project with over 60,000 assets, overall build time was reduced from over 25 minutes to 9 minutes (**2.7x faster**). The total bundle size for the whole project went from 952 MB to 370 MB (**2.5x smaller**). For comparison, building the same app with webpack takes over 45 minutes. We've been working on this new bundling algorithm for a long time, and we're excited to finally make it the default in this release. Huge thanks to the Atlassian team for contributing this improvement! @@ -51,7 +51,7 @@ This release also includes improvements to tree shaking with code splitting. Pre Parcel now rewrites dependencies to point to their final destinations, following all re-exports found along the way. This means re-exports now have no effect on code splitting, and only used exports within each bundle are loaded. In many applications, this means the entry bundle will become much smaller since more code will only be loaded when needed. -Results will depend on how many re-exports you rely on and your code splitting setup, but we have seen impressive results in several applications so far. One very large app saw over **40% smaller JS entry bundles**, while another saw a 25% smaller JS entry and 50% smaller CSS. +Results will depend on how many re-exports you rely on and your code splitting setup, but we have seen some impressive improvements in several applications so far. One very large app saw over **40% smaller JS entry bundles**, while another saw a 25% smaller JS entry and 50% smaller CSS. Thanks to [Niklas Mischkulnig](https://twitter.com/mischnic) for contributing this improvement! From 9c8d7e715cba72590549c9d543c50924c30487a7 Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Mon, 7 Nov 2022 18:52:42 -0800 Subject: [PATCH 4/5] Add note about side effects --- src/blog/v2-8-0/v2-8-0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blog/v2-8-0/v2-8-0.md b/src/blog/v2-8-0/v2-8-0.md index f65ed955..7e1f068d 100644 --- a/src/blog/v2-8-0/v2-8-0.md +++ b/src/blog/v2-8-0/v2-8-0.md @@ -49,7 +49,7 @@ See [this repo](https://github.com/devongovett/parcel-vs-vite-vs-turbopack-hmr) This release also includes improvements to tree shaking with code splitting. Previously, if you used a large library containing an index file with many re-exports, Parcel would always place all of the used exports in the same bundle. For example, if you used different components from a component library on different pages or code split points (e.g dynamic import), all used components across your whole project would be placed into the entry bundles. This could mean loading much more JavaScript than necessary on initial page load. -Parcel now rewrites dependencies to point to their final destinations, following all re-exports found along the way. This means re-exports now have no effect on code splitting, and only used exports within each bundle are loaded. In many applications, this means the entry bundle will become much smaller since more code will only be loaded when needed. +Parcel now rewrites dependencies to point to their final destinations, following all re-exports found along the way. This means re-exports in [side effect-free packages](/features/scope-hoisting/#side-effects) now have no effect on code splitting, and only used exports within each bundle are loaded. In many applications, this means the entry bundle will become much smaller since more code will only be loaded when needed. Results will depend on how many re-exports you rely on and your code splitting setup, but we have seen some impressive improvements in several applications so far. One very large app saw over **40% smaller JS entry bundles**, while another saw a 25% smaller JS entry and 50% smaller CSS. From 945e8dcf1f902c3fbb22105358492fc1f2d750fc Mon Sep 17 00:00:00 2001 From: Devon Govett Date: Tue, 8 Nov 2022 21:54:13 -0800 Subject: [PATCH 5/5] Add release notes link --- src/blog/v2-8-0/v2-8-0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blog/v2-8-0/v2-8-0.md b/src/blog/v2-8-0/v2-8-0.md index 7e1f068d..5a4b3d3e 100644 --- a/src/blog/v2-8-0/v2-8-0.md +++ b/src/blog/v2-8-0/v2-8-0.md @@ -57,7 +57,7 @@ Thanks to [Niklas Mischkulnig](https://twitter.com/mischnic) for contributing th ## Thanks! -Parcel v2.8.0 includes several other smaller features, bug fixes, and improvements. Check out the full [release notes]() for more details. +Parcel v2.8.0 includes several other smaller features, bug fixes, and improvements. Check out the full [release notes](https://github.com/parcel-bundler/parcel/releases/tag/v2.8.0) for more details. - [GitHub](https://github.com/parcel-bundler/parcel) - [Discord community](https://discord.gg/XSCzqGRuvr)