Skip to content

Conversation

@developit
Copy link
Owner

@developit developit commented Jul 22, 2019

This pull request reduces the total JS size of a Next.js application down by as much as 65%. It achieves this for modern JavaScript output, which means it's best paired with @janicklas-ralph's module/nomodule PR.

Here's a summary the changes:

  • Compile out all inlined polyfills. This is possible because they're not needed for ES Modules-supporting browsers. A legacy bundle with polyfills and ES5 syntax can be generated and served to these browers.
  • Switch to modern modern JavaScript. This achieves a ~20% size reduction by avoiding over-transpilation due to jagged browser support, while still remaining fully functional (and more debuggable!) in the necessary browsers - Edge 15, Safari 10.1, Firefox 60 & Chrome 61.
  • Ship next/* client libraries as modern JS. This was already being done in part, but I've further reduced their size by tuning all configurations. Client-side next modules are processed by the same Babel configuration as userland JavaScript code, so it's okay to assume a baseline of ES2018 support.
  • Move global modules into the commons chunk. @atcastle has a much more comprehensive PR for this, my goal here was simply to correct a few of the most notable chunking issues present in applications as simple as the basic integration test app. This amounts to moving scheduler and next/* packages into the commons chunk.
  • Build tuning. There were a few cases where Next was relying on runtime features that were statically known at build time. For example, the webpack loader responsible for wrapping page chunks with autoregistration wraps its HMR logic in if (module.hot) {} - using DefinePlugin to replace module.hot=false during production builds removes the unnecessary HMR code from every route. Similarly, Webpack's default behavior is to inject shims for various Node features (setImmediate, Buffer, etc). While it's possible some users would like to have these available, the fact that they're not used by Next.js itself means it would make more sense to include them conditionally (via config or usage detection).

To test out the changes:

# download & install:
git clone https://github.com/developit/next.js.git next-lite && cd next-lite
git checkout -b bundle-size-optimization origin/bundle-size-optimization
yarn && npm i -g gzip-sizes

# run a build everything:
yarn run prepublish &&
  rm -rf test/integration/basic/.next &&
  yarn run next build test/integration/basic

# show the output sizes:
gzip-sizes -d test/integration/basic/.next/static -s size- "**/*.js"

@developit developit marked this pull request as ready for review April 19, 2020 03:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants