9

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.

ravi kumar
  • 1,548
  • 1
  • 13
  • 47
  • 1
    I had this problem due to importing -- directly, and by using node packages that indirectly imported -- nodes `crypto` module. It was a bear to get rid of, since I didn't really find a way to trace which dependency was responsible. it was a lot of trial an error. eventually I replaced everything that required `crypto` with browser friendly version. Thanks to `tweetnacl` and `jsrsasign` @kjur – domoarigato Oct 16 '20 at 20:49

3 Answers3

1

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.

ravi kumar
  • 1,548
  • 1
  • 13
  • 47
1

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!

David Chu
  • 329
  • 2
  • 3
0

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.
Arthur
  • 108
  • 8