An isolated environment to explore how tree shaking works with webpack 4. This was inspired by uncertainty and questions around implementing the best practises described here - https://developers.google.com/web/fundamentals/performance/optimizing-javascript/tree-shaking/.
- Fork this project in the GitHub UI
- Clone your forked copy
git clone https://github.com/[YOUR-USERNAME]/tree-shaking-exploration
- Change into the directory
cd tree-shaking-exploration
- Use node version 10.8.0 and have npm installed
- Run
npm install
to add module dependencies
- Build the bundle in one terminal window with
npm run build
- Open the server in a second terminal window with
npm start
- Your default browser will open the application at localhost:8080
- When finished with the application, close both process with
^c
- Understand how to set up a project correctly for webpack to tree shake the bundle.
- Know how lodash is a strange case and accomodate this to make sure the whole of lodash isn't included in the compiled code.
- Use bundle analyzer to look at the before and after state of a bundle
- Add some commit tools to check that the size of the bundle does not dramatically increase in a commit. Potentially a pre commit hook if all commits go straight into master.
As a developer
So that I can implement and debug tree shaking in a large project
I need an isolated project to build a test case
- Added Lodash and used
get
to access some nested properties in an object. - This meant that building the project generated a bundle of main.js at 187 KiB (using webpack)
- Ran
npx webpack --profile --json > stats.json
to generate an analysis via webpack-bundle-analyzer andnpx webpack-bundle-analyzer ./stats.json
. Main bundle is listed as 649KB in the analyzer out put. Lodash is 527KB stat size, 68.84KB parsed, 24.12KB gzipped. - Here is the initial analysis:
- Changed the import of
get
to access the function fromlodash/get
- Building the project now produces a bundle of main.js at 125 KiB (using webpack)
- Running bundle analyzer and main bundle is listsed as 153.07KB in the analyser output. Lodash is 30.93KB stat size, 7.14KB parsed, 2.16KB gzipped.
- Here is the new analysis:
- Installed
lodash-es
for the lodash library as ES modules. - Changed the import of
get
to access the function fromlodash-es/get
- Building the project now produces a bundle of main.js at 123 KiB (using webpack)
- Running bundle analyzer and main bundle is listsed as 152.97KB in the analyser output. Lodash-es is insanely small: 171B stat size, 116B parsed, 114B gzipped. Here is the analyzer as proof:
- Here is the new analysis:
- Parsed size of the bundle corresponds with the output of the webpack
npm run build
step. - First bundle analyzer lists lodash as 527KB. First main bundle (649KB) minus this lodash (527KB) is 122KB - essentially the main bundle using
lodash/get
andlodash-es
. - It is not 'OK' to use
import * as _ from 'lodash'
. But you do not have to uselodash-es
to reduce the bundle. - Save the browser having to process approximately 527KB of javascript in your bundle by using cherry picking from
lodash/[function_name]
orlodash-es/[function_name]
to import only the functions you specifically need in the client side app. - If you're using more than one or two utility functions from lodash in your client side app, the fact that code can be shared across the ES modules means that there will be aggregated bundle size improvements from choosing
lodash-es/[function_name]
as detailed in this investigation - https://itnext.io/lodash-es-vs-individual-lodash-utilities-size-comparison-676f14b07568.
- Why does the 30KB of lodash from
lodash/get
not impact the bundle size more. I.e. causing a bigger difference between iteraction 2 and 3.