Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(gatsby): enable granular chunks #22253

Merged

Conversation

wardpeet
Copy link
Contributor

@wardpeet wardpeet commented Mar 13, 2020

Description

Enable granular chunking for Gatsby. This PR helps us improve our webpages in 2 ways:

Less duplications (less javascript)

By bundling a dependency that is at least used in 2 pages we can bundle them together so we don't have to download duplicate libraries over and over again. This won't benefit first-page load but it improves page navigation as you'll need less javascript for the next route.

Big libraries over 160kb are moved to a separate library all together to improve js parsing & execution costs.

Our commons chunk is used to put in code that is used over all our pages (commons). So we don't bloat any pages more than we need

Caching

We've added a framework bundle which contains react, react-dom as this is a chunk that will hardly ever change. Commons & shared libraries can change when new pages are created which is more likely to happen than react being upgraded. We might want to move other modules into it, like @reach/router.

Overall caching is improved as chunks will change less often.

site kb diff % diff
https://www.gatsbyjs.org/ -680kb -22,6%
https://www.thirdandgrove.com/ -390kb -25,5%
https://ghost.org/ -1110kb -34,79%
https://reactjs.org/ -80,58kb -8,15%
https://gatsby-starter-blog-demo.netlify.com/ +0,38kb -0%

These are the links for gatsbyjs.org & reactjs.org as they are opensource sites.

gatsbyjs.org before
gatsbyjs.org after
reactjs.org before
reactjs.org after

What's next?

MDX is still a black box as it's now added to app.js and should be part of the shared libs, which is not the case. Firstly I'll be looking at our polyfill strategy to reduce our bundles and afterwards, I'll check out how to optimize mdx.

Big shoutout to @developit, @housseindjirdeh and the nextjs team

Documentation

I might need to update https://www.gatsbyjs.org/docs/production-app/ to resemble the correct information.

Related Issues

@wardpeet wardpeet requested a review from a team as a code owner March 13, 2020 15:50
Copy link
Contributor

@pieh pieh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking awesome!

packages/gatsby/src/utils/webpack.config.js Show resolved Hide resolved
packages/gatsby/src/utils/webpack.config.js Outdated Show resolved Hide resolved
packages/gatsby/src/utils/webpack.config.js Show resolved Hide resolved
if (/@babel(?:\/|\\{1,2})runtime|core-js/.test(modulePath)) {
// TODO this needs rework, this is buggy as hell
if (
/@babel(?:\/|\\{1,2})runtime|core-js|react|react-dom|scheduler|prop-types/.test(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this regex probably needs directory boundaries to avoid /react/ matching react-foo.

@wardpeet wardpeet force-pushed the wardpeet/ch298/granular-code-splitting branch from 1635e9c to d918a05 Compare March 20, 2020 13:45
@freiksenet freiksenet requested review from a team as code owners March 20, 2020 13:45
@laurieontech
Copy link
Contributor

Yes, I'd say https://www.gatsbyjs.org/docs/production-app/ should be updated as part of this.
Also wondering if other pages like creating a custom webpack config need a section on this. Essentially I'd like there to be at least one write up on how users can take advantage of chunking themselves.

@wardpeet wardpeet force-pushed the wardpeet/ch298/granular-code-splitting branch from d918a05 to 946f6d3 Compare March 20, 2020 17:38
Copy link
Contributor

@laurieontech laurieontech left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Ward! Left some suggestions below but looks really good.

docs/docs/production-app.md Outdated Show resolved Hide resolved
commons: {},
// When a module is used more than once we create a shared bundle to save user's bandwidth
shared: {},
// All css is bundled into one stylesheet
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// All css is bundled into one stylesheet
// All CSS is bundled into one stylesheet
},
// Keep maximum initial requests to 25
maxInitialRequests: 25,
// A chunk should be at least 20kb to be considered into splitChunks
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// A chunk should be at least 20kb to be considered into splitChunks
// A chunk should be at least 20kb before using splitChunks
minimizers: [
// Minify javascript using Terser (https://terser.org/)
plugins.minifyJs(),
// Minify css by using cssnano (https://cssnano.co/)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Minify css by using cssnano (https://cssnano.co/)
// Minify CSS by using cssnano (https://cssnano.co/)
@@ -62,6 +93,14 @@ This bundle is produced from [production-app.js](https://github.com/gatsbyjs/gat

This contains the small [webpack-runtime](https://webpack.js.org/concepts/manifest/#runtime) as a separate bundle (configured in `optimization` section). In practice, the app and webpack-runtime are always needed together.

##### framework-[contenthash].js

The framework bundle contains the react framework. We've noticed that React hardly gets upgraded to a newer version. Creating a separate bundle improves users' browser cache hit rate as this bundle is likely not going to be updated often.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The framework bundle contains the react framework. We've noticed that React hardly gets upgraded to a newer version. Creating a separate bundle improves users' browser cache hit rate as this bundle is likely not going to be updated often.
The framework bundle contains the React framework. Based on user behavior, React hardly gets upgraded to a newer version. Creating a separate bundle improves users' browser cache hit rate as this bundle is likely not going to be updated often.

##### commons-[contenthash].js

Libraries used on every gatsby page are bundled into the commons javascript file. By bundling these all together, we make sure your user only needs to download this bundle once.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Libraries used on every gatsby page are bundled into the commons javascript file. By bundling these all together, we make sure your user only needs to download this bundle once.
Libraries used on every Gatsby page are bundled into the commons javascript file. By bundling these together, you can make sure your users only need to download this bundle once.
laurieontech
laurieontech previously approved these changes Mar 23, 2020
Copy link
Contributor

@laurieontech laurieontech left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Ward! Would it be possible to add a paragraph that just primes the user on chunking as a concept?

@wardpeet
Copy link
Contributor Author

Thanks Ward! Would it be possible to add a paragraph that just primes the user on chunking as a concept?

To the app-production.md file? Not 100% sure what you want me to explain, chunks & modules are webpack terms. Technically a module contains chunks & chunks are pieces of code (a file or bundle of files)

@laurieontech
Copy link
Contributor

This section has an intro paragraph. Perhaps mention that we make use of chunking with a link to the applicable webpack docs on the topic?

Copy link
Contributor

@laurieontech laurieontech left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Ward! Think that helps a lot. I made some suggestions since we're trying to move away from "we", but overall think it looks good.

docs/docs/production-app.md Outdated Show resolved Hide resolved
Co-Authored-By: LB <laurie@gatsbyjs.com>
Copy link
Contributor

@laurieontech laurieontech left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding the right docs info!

Copy link
Contributor

@LekoArts LekoArts left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added just one question :)

docs/docs/production-app.md Show resolved Hide resolved
Copy link
Contributor

@KyleAMathews KyleAMathews left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks awesome! Excited to get this in!

@wardpeet wardpeet merged commit 0f02ea7 into gatsbyjs:master Mar 26, 2020
@wardpeet wardpeet deleted the wardpeet/ch298/granular-code-splitting branch March 26, 2020 07:10
@wardpeet
Copy link
Contributor Author

Published in gatsby@2.20.7

@fk
Copy link
Contributor

fk commented Apr 21, 2020

(very late to the party, but 💜 🙏 🎉)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
8 participants