Webpack including its own dependencies in bundle

Viewed 1182

I am fairly new to webpack and I have a Vue project using the vue cli. While analyzing the webpack bundle (built in production mode using vue-cli-service build) using webpack-bundle-analyzer, I found that one particular file bn.js is being included multiple times in the bundle. When running npm ls bn.js I found that it's parent dependency is webpack itself.

`-- webpack@4.44.1
  `-- node-libs-browser@2.2.1
    `-- crypto-browserify@3.12.0
      +-- browserify-sign@4.2.1
      | +-- bn.js@5.1.3
      | +-- browserify-rsa@4.0.1
      | | `-- bn.js@4.11.9
      | +-- elliptic@6.5.3
      | | `-- bn.js@4.11.9
      | `-- parse-asn1@5.1.6
      |   `-- asn1.js@5.4.1
      |     `-- bn.js@4.11.9
      +-- create-ecdh@4.0.4
      | `-- bn.js@4.11.9
      +-- diffie-hellman@5.0.3
      | +-- bn.js@4.11.9
      | `-- miller-rabin@4.0.1
      |   `-- bn.js@4.11.9
      `-- public-encrypt@4.0.3
        `-- bn.js@4.11.9

So my question is that why is webpack including it's own dependencies in the final bundle when webpack is added as a devDependency (earlier it was a dependency, then I changed it to devDepenency) in the project?

Or if this is the correct behavior then please point me to any docs/resources explaining this behavior.

3 Answers

Well it turns out that it was a npm thing. Earlier I had webpack as a dependency in package.json. Then I ran npm uninstall webpack --save and then again did npm install webpack --save-dev in order to make it a dev dependency. Turns out that it wasnt enough. I stopped getting webpack dependencies in my bundle only after I deleted my node_modules folder and then did npm install again.

A tip for how I found which framework was the problem. In Webpack configs I set {node: false} and then I built the production code. Webpack should flag the offending framework. This can be a problem for code that was originally written for the server side and expects certain packages to be available and do not show up on package-lock.json.

If you're using something like create-react-app, then you can use a framework like react-app-rewired to customize the Webpack configs.

Happy unused code busting!

I faced a similar issue where I was unable to find why a library called bn.js, elliptic etc. were being imported.

Turns out, it was because we were using a library called [generate-password][1] that was importing crypto and because of that I was seeing multiple modules that I never imported. Have a look at this image below.

Many instances of bn.js and elliptic

If you ever find yourself in such a situation where you can't find the import statements for a particular library in your codebase, just do:

npm ls libname

Result of npm ls on the library name

There are cases where there are some libraries that are importing these methods internally and therefore, causing your vendor bundle to bloat. In the case of generate-password, it was importing the crypto module from node. The whole module ended up in the vendor bundle because generate-password was using one function from the crypto module.

How I avoided importing crypto:

  1. Copied the generate-password source code into my codebase as a util.
  2. Replaced the randomBytes function from crypto lib with a specific npm version of the randomBytes.
  3. Remove node_modules and rebuild using yarn/npm.
Related