📜 ⬆️ ⬇️

Obvious non-obviousness in assembly using a webpack

image


Working in a large company, it was possible to intercept an internal project that had to be completed yesterday. The people roamed and tramped along it, developing the culture of Saint Copipasta. And package.json grew by leaps and bounds. After only a year, we managed to start refactoring. In this article we will focus on one specific optimization, which I have not heard anything about on the Runet.


It all began ...


... from my surprise. The non-minimized application bundle weighed 44 MB, included about 4 thousand modules, the assembly took about 8 minutes. With even more surprise, I looked at the simultaneously connected lodash and lodash-es. Dances with a tambourine, cutting out a "dead" code, removing modules that almost duplicate each other (for example, all the same lodash and lodash-es) and as a result - 3 thousand modules, 30 MB, 5 minutes. Then there were more searches on Habré and non-dumb, application of the information found, cutting off the extra locales of the moment, switching to TypeScript (currently used only as a transpiler, but this is a completely different story) - 2.5 thousand modules, 1 min. 30 sec., 20 MB.
It is worthy.


But once exploring the beta version of the material-ui came across an interesting page . If you clicked on the link, read and understood everything, then you will not be interested further.


For those who are still with us


Suppose we have a small project, in the root directory of which are:



{ "name": "webpack-bundle-example", "version": "1.0.0", "scripts": { "start": "webpack" }, "dependencies": { "lodash-es": "^4.17.4", "webpack": "^3.6.0", "webpack-bundle-analyzer": "^2.9.0" } } 


 const {BundleAnalyzerPlugin} = require('webpack-bundle-analyzer'); const path = require('path'); module.exports = { entry: './index', output: { filename: 'index.bundle.js', path: path.resolve(__dirname, 'build') }, plugins: [ new BundleAnalyzerPlugin({ analyzerMode: 'static' }) ] }; 


 import {mapValues} from 'lodash-es'; console.log(mapValues({a: 0, b: 1}, (...args) => args)); 

At the root, execute npm i and after installing the dependencies, run the npm start build.


The BundleAnalyzerPlugin plugin BundleAnalyzerPlugin generate for us a map, which will be clear from what the bundle consists of.
And on this map, we see that the bundle contains files from the node_modules directory node_modules total weight of 608 Kb (!).


And we just imported one function from lodash-es. Bold, is not it?


No obvious solution


The solution is as simple as twice two. For me it turned out to be so obvious that I still consider it absolutely not obvious.


You can import directly from lodash-es/ to avoid pulling in unused modules. For instance, instead of:


 import {mapValues} from 'lodash-es'; 

use:


 import mapValues from 'lodash-es/mapValues'; 

And after the assembly we get the following map of our modules and we are surprised - 82 Kb:


Having changed only one line in the project, we got almost an 8-fold reduction in the size of the bundle.


Do you still remember the project from the beginning of the article? So ... 11 MB, 40 seconds, 1.7 thousand modules


')

Source: https://habr.com/ru/post/339190/


All Articles