Our website is build with heavy node_modules
.
Many heavy package cause heavy node_modules
and eventually affects heavy cost on AWS.
Sowe are trying to reduce total bundle size to reduce some cost.
What I found is, by splitting code with webpack, we can have more but smaller bundles. Though, overall size doesn't change a lot.
What i'm wondering is, does splitting code with webpack can save some AWS cost?
Sorry for poor question, but this is all I can think of right now.
Any great idea would very helpful Thx.
CodePudding user response:
This is a complex topic and equally open-ended question too! To answer this, I will make few assumptions:
- By saving AWS cost, it means reducing bundle size so that outgoing bandwidth cost is saved.
- Application being built is 100% SPA i.e. fully client-side. Server-side optimization gets very complex quickly.
Out of box, Webpack will bundle everything into one big file/bundle. It contains your own code as well as code from third-party libraries. The fundamental idea here is that third-party code rarely changes while our own code frequently changes.
So, we can use Webpack to split our code into two distinct chucks using SplitChunksPlugin. One for our own code and another for third-party code i.e. code from node_modules
folder; lets call it vendor bundle. Now as long as your node_modules
folder remains constant i.e. your lock file - package-lock.json
file is constant, it will always produce the same bundle with exact same content for third-party code.
Then next part of the idea is that you can simply take this vendor bundle and upload it to CDN and then use via CDN. The CDN and browser will do their caching magic and users will hardly need to download this file each time. CDN will use ETag
and/or cache-control
header to achieve this and browser will use that.
However, the reality is different. When you have too many dependencies and or using dependabot to update dependencies, you will often update your lock file. This means on each build a new vendor bundle gets generated even if there is a difference of single byte. The hash id generated by Webpack will be different. And in other scenario, the way you import the dependencies may also change the generated bundle content resulting in a different bundle.
So, architecturally, we do better vendor bundling by making use of CDNs. The first step is to distinguish between stable third-party module and frequently updated third-party module. For example, consider react
, react-dom
and rxjs
, etc. These are not updated often. For these libraries, make use of third-party CDN like cloudflare, cdnjs or unpkg. Add these libraries as CDN based UMD packages.
For this, you will add these dependencies to your index.html
file which is typically generated using html-webpack-plugin
.
<!-- index.html -->
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
Now, simply tell Webpack to not bundle these dependencies which you have already made available via CDN script
. Use Webpack externals to do that:
// webpack.config.js
module.exports = {
externals: {
'react': 'React',
'react-dom': 'ReactDOM'
},
};
With this configuration, Webpack is not only going to exclude React from the bundle but also will speed up your bundling. Where ever you import stuff from react library, Webpack will substitute this for global object React
.
You can then extend this model to all the stable libraries that you are using. Another important advantage of using this way is that there would be other websites that your users may have already visited which would have cached this particular file in their browser using the same CDN.
To automate your workflow, you can customize Webpack or any bundler script to inject these scripts with exact version by reading the packge.json
file for your dependencies and then generating the <script>
tags. It means you would still have single source of truth for your dependencies versions. You can read CDN documentation to understand how they allow you to construct CDN URLs for the dependencies.