I got a production application where its bundle size is 8.06MB.
# Console log from npm build
File sizes after gzip:
1.67 MB build/static/js/3.73cf59a2.chunk.js
794.29 KB build/typescript.worker.js
131.13 KB build/css.worker.js
104.68 KB build/html.worker.js
104.02 KB build/static/css/3.01bcafd3.chunk.css
67.03 KB build/static/js/main.6acf560d.chunk.js
49.64 KB build/json.worker.js
25.12 KB build/editor.worker.js
7.99 KB build/static/js/54.afc981d1.chunk.js
...
On building the application and running source-map-explorer
npm run build
source-map-explorer 'build/static/js/*.js'
I get a warning from build
:
The bundle size is significantly larger than recommended.
You can inspect the source map.
I would like to reduce the bundle size, from the research I've done, it concluded to:
import Button from 'antd/es/button';
import { Button } from 'antd'; // Imports all library
devDependencies
devDependencies
Why is it important to have a small bundle size?
Because this will reduce the amount of time it takes for users to load your application / site, by reducing the amount of data they have to transfer. This is particularly important for users on low bandwidth connections, including patchy cellular connections.
What is the recommended bundle size, why?
As small as possible. I don't think that it's really possible to give a precise answer here, as every application is different, but generally you want the resources on the "critical" path to be as small as possible, so that you decrease your initial load time, and then load more resources as needed on the fly.
I understand that code-splitting splits your code into various bundles which can then be loaded on-demand or in parallel. How does it help in reducing the bundle size?
Whilst it may not reduce your overall bundle size, it can reduce the amount of data required by an individual user. For example, if you only use monaco-editor
in a particular part of your application, it may make sense to lazily load this only when the user activates that feature.
How do I decide if a library needs to be a part of devDependencies
devDependencies should include any dependencies that are only required whilst developing the project. This would include tooling (eg: webpack, eslint, gulp) and test frameworks (mocha, chai, sinon).
This is more relevant to server side projects however, as true devDependencies should not end up in your bundled code even if you place them in the dependencies section by mistake.
Are there any other approaches?
Primarily you should focus on tree shaking and code splitting/lazy loading.
For example, moment-timezone
is taking up almost 1mb by itself - do you actually need this? For many applications it is enough to just work in the browsers time zone and utc, which shouldn't need moment-timezone
For the antd
library, making sure all your imports are tree-shakable (eg: import individual components as in your example) may significantly reduce the size of the imported code (other libraries like lodash may be a similar story, though if you have dependencies that haven't used tree-shakable imports the whole thing will be included anyway)
For vis
and monaco-editor
consider if they can be loaded on demand, rather than always loaded at startup. Consider if you need codemirror
as well as monaco-editor
- from a glance they appear to fill similar purposes.
ref:
https://webpack.js.org/guides/tree-shaking/
https://webpack.js.org/guides/lazy-loading/