Recently, I have been working on optimizing the page loading time of a complex low-code application. Previously, I have done some similar optimization work in other projects, but they are not react projects. As it’s based on Webpack, in order to reduce the page loading time, I have to try to optimize the webpack bundle size or the chunk size of the application, in the mean time, I need to do some code splitting work.
Use The Webpack Bundle Analyzer
I’ve done some research on the webpack bundle analyzer, and I found that it can help me to analyze the bundle size(Gzip compressed size in particular) of the application. So, I decided to use it. I’ve installed it in my project, and I’ve set it up in my webpack config file. After that, I can run the command: npm run analyze. And I can see the bundle size of the whole application in details. I can easily figure out some abandoned modules that are not used in the application, but they are bundled in the application. Secondly, I alse have found some large modules or libraries that are bundled into a huge bundle. Lastly, I found the source map setting is enabled, which is not good for the performance.
Optimize The Application
From the analysis above, I can easily figure out that the application is too large for some known reasons. So, firstly, I try to delete some unused modules one by one. Secondly, I try to split the large modules or libraries into smaller modules or libraries by using the webpack split-chunks plugin or using external strategy in config file. Finally, I disable the source map setting in production mode.
Use ES Module Instead
Use es module instead, because of some of the react components provide a better way to import the module instead. In JavaScript land, tree-shaking has been possible since the ECMAScript module (ESM) specification in ES2015, previously known as ES6. Since then, tree-shaking has been enabled by default in most bundlers because they reduce output size without changing the program’s behaviour. Tree-shaking means removing unreachable code (also known as dead code) from a bundle. As Webpack version 3’s documentation states:
“You can imagine your application as a tree. The source code and libraries you actually use represent the green, living leaves of the tree. Dead code represents the brown, dead leaves of the tree that are consumed by autumn. In order to get rid of the dead leaves, you have to shake the tree, causing them to fall.”
import { Com } from 'react-awesome-components;' // CommonJS import { Com } from 'react-awesome-components/esm'; // ESM - Tree shaking friendly
Dive into the Tree-Shaking: A Reference Guide.
Code-Splitting
We can follow the Official React Code-Splitting Guide to code-splitting your app. Most React apps will have their files “bundled” using tools like Webpack, Rollup or Browserify. Bundling is the process of following imported files and merging them into a single file: a “bundle”. This bundle can then be included on a webpage to load an entire app at once. Code-splitting your app can help you “lazy-load” just the things that are currently needed by the user, which can dramatically improve the performance of your app. While you haven’t reduced the overall amount of code in your app, you’ve avoided loading code that the user may never need, and reduced the amount of code needed during the initial load. Dive into the React Code-Splitting Advanced Guide.
Another very useful way is to use the popular react plugein – react-loadable A higher order component for loading components with promises. In this way we can easily code-split our react components by wrapping them with react-loadable
.
Besides, we can alse use the remote-component strategy. Believe it or not? If you ever use this awesome react plugin, you will definitely be in love with it.
Lastly, may be we can upgrade Webpack 4 → 5 to use the awesome Module Federation, which can do the Micro-Frontends works, but is not limited to that. Dive into Webpack5 Module Federation.
Trying To Apply The CDN Strategy
The CDN strategy is to use the CDN(Content Delivery Network service) to serve the static files. The CDN is a service that provides a static file server. With CDN, you can serve the static files from a single server, which is faster than the traditional way. That sounds good, right? However, we need to tackle the problem of the CDN. What’s the problem? For some reasons(CORS and the like), the frontend application and the backend application are in the same domain. If we need fire a ajax request inside some static javascript files, we have to take the CORS(Cross-Origin Resource Sharing, the same-origin security policy) into consideration. I am considering to use the partial CDN strategy to solve the problem. For example, if we are using axios to make ajax request, we can’t put the axios.js file into the CDN. For other static files, we can put them into the CDN. Testing ha…
What’s next?
I’m still working on the optimization of the application in the rendering process, such as the SSR(Server Side Render) strategy, or adding some loading animation while the application is not ready, or optimize the code in the rendering process and make it more efficient and so on.