Treeshaking and Codesplitting Default Behaviour
See original GitHub issueSummary
I’m opening this as a question as I’m unsure if Gatsby’s behaviour in this instance is correct / expected. It certainly doesn’t seem to be optimal, but it could be something I’ve overlooked. If this is unexpected I’ll open this as a bug.
Our Gatsby site consumes a number of packages from our monorepo. Two of these packages are:
@example/utils
@example/site-forms
@example/utils
contains a lot of utility functions, many of which wrap other npm libraries, so has a lot of third-party dependencies, however it often only uses a small subset of those dependencies’ apis.
@example/site-forms
contains a large number of React components representing forms we use on the site. The forms are fairly complex and non-trivial in size. Almost every form is used on a single page of the site only.
Both packages are transpiled, but leave ES6 imports/exports intact to facilitate tree-shaking. Both packages’ package.json
have sideEffects: false
. Both packages use re-exports from an index.js
file which is their main
file:
Either:
export * from './utils/api'
Or
export { default as ContactForm } from './forms/ContactForm'
Expected behaviour
From reading the docs on Gatsby’s usage of code-splitting and treeshaking, I would expect the following:
- Any exports that are not used in the site are not included in any bundles.
- Any exports that are used on every page are included in the
commons
bundle. - Any exports that are used on a single page only are included in the bundle for that individual page.
Observed behaviour
- Any exports that are not used in the site are not included in any bundles.
- Any exports that are used in three or more files are included in the
commons
bundle. - Any exports that are used on a single page only are included in the bundle for that individual page.
For 2. I’m seeing every export from either of these packages that is used anywhere in the site being included in the commons
bundle.
For 3. I’m seeing bundles being generated for individual pages, but these only include page-specific code that is defined within my gatsby project (not third-party).
So the end result is that I have a huge commons
bundle and lots of very small page bundles.
As far as my understanding goes, this is definitely not optimal behaviour and appears to be unexpected in relation to the documentation. Am I expecting too much from Gatsby/Webpack? The packages themselves are used by more than one page, but their exports are not.
Note that I’m seeing similar behaviour with third-party libs. For example, netlify-cms-app
is used only on our /admin/
page, however, at least some of its dependencies are included in thecommons
chunk.
Relevant information
-
I have no custom Webpack configuration.
-
Imports of form components are happening directly from the packages within templates. There is no hidden interdependency going on.
-
gatsby@2.23.1
-
gatsby-cli@2.12.44
Issue Analytics
- State:
- Created 3 years ago
- Reactions:2
- Comments:9 (9 by maintainers)
Top GitHub Comments
@wardpeet I can’t I’m afraid, but I’ll see if I can get permission. Definitely something strange going on. This combined with the disaster of Lighthouse 6 scores is tanking my week 😉
Hi!
I’m going to close this now, as we can’t do much to help without a reproduction. If you are able to create a minimal reproduction for this then please do reopen the issue.
Thanks!