webpack: Duplicate module loaded multiple times
Hi,
Let’s say I have a project with a dependency tree like (all dependencies being declared as “dependencies” in package.json
)
- Main application
- angular
- Sub-module 1
- angular
- Sub-module 2
- angular
When bundling my app, I will end-up with angular being included 2 times in my webpage. I know I can use webpack.optimize.DedupePlugin()
to prevent the file being included multiple times but it will still be called two times at runtime, resulting in a warning “tried to load angular more than once”.
I feel this is the same for every sub-dependencies shared by my app dependencies, every sub-module will have its own version of angular and even though they use the exact same version, it will be loaded multiple times.
Is this tied to the philosophy of not having a flat dependency tree or am I doing something wrong ? One solution I have found is to move all the dependencies of my sub-modules as peerDependencies
and add them as dependencies to my “Main application” but I feel like this is a very bad solution.
Any insights on this ?
Thanks.
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Reactions: 47
- Comments: 24 (1 by maintainers)
Commits related to this issue
- also works, https://github.com/webpack/webpack/issues/2134#issuecomment-192579511 - for prev commit — committed to nkonev/blog by nkonev 7 years ago
You probably do want
angular
to be apeerDependency
, since it is a framework within which your code runs. That’s how I’ve modeled it in an angular component library we use internally at my company.You can then ensure that only one instance of angular is loaded from your
main
module by adding analias
forangular
to your webpack config:For reference, another possible way to handle this is to add
angular
toexternals
and load it onto the page separately through a<script>
tag or a separate bundle. This solution is useful if you’re building your submodules independently as UMD libraries.Is there any solution for this problem? I’m having the same problem.
+1
peerDependency
works well in the case of Angular, because it’s also a dependency of my main package. But I also have some dependencies shared by my sub-modules that aren’t dependencies of my main application and I find it quite ugly to “move up” all the dependencies of my modules just because I have no other way to share them properly. Ex:Here with Webpack,
angular-infinite-scroll
will be executed two times in my bundle, even with the Dedupe plugin (it will just prevent the source from being duplicated but it’s still called multiple times). I don’t think this is a good pattern to moveangular-infinite-scroll
(or any other fancy dependency needed by only one or two sub-modules) to my main application since it doesn’t need it at all. And setting it as a peer dependency of my sub-modules means anyone that will want to use them will be obliged to depend on these modules.I thought
npm dedupe
could be the solution to my problem but since I’m working withnpm link
-ed modules I’m still stucked… https://github.com/npm/npm/issues/7742Anyone else faced this problem before ? 😃
+1
The same module should be loaded only once…
I’m using Webpack 4.x. In my case, I had the same modules loaded multiple times, esp.
React
andlodash
, which caused me a lot of troubles.For some reason, I had several named entries in Webpack config, and some of them must be added to the same page. They do point to the same
React
in bundled in acacheGroup
, but it’s loaded multiple times.Eventually, I’ve solved this by adding
optimization.runtimeChunk: 'single'
, which creates an extraruntime.js
.Back to my issue, I realize that there’re multiple Webpack runtimes (
webpackJsonp
handling logics) in different named entries, each of them will try to install the modules incacheGroup
s but they don’t communicate with each others, which leads to duplicated loadings. By merging the runtimes into the single one, it will always know which modules have been installed and which not, so that duplicated loadings can be avoided.Hope my discovery helps.
I had a similar problem importing a lib from other project. When i did ‘import XXX from xxx’ in my project, my xxx reference was different than xxx reference in lib because webpack import twice the same file but assign it different IDs.
May be this plugin can help you.
https://bitbucket.org/snippets/joaquinfq/KB9Ag
Add it to webpack plugins instead of DedupePlugin:
I have the same problem. A close-like setup is presented in this repo, I created to illustrate the problem.
https://github.com/ru-web-designer/lerna-webpack-typescript
The story below is a simplification of what really happend in my real repo. Ehem…
There is a monorepo with two private local packages,
boopler
andwoopler
.boopler
is depending onwoopler
, both of them haveimport * as $ from "jquery"
.boopler
binds DOMReady event with it,woopler
makes some DOM manipulations. Their deps are perfectly symlinked with Lerna.Finally, there is
index.ts
in the root of the repo, which haveimport "boopler"
. It is an entry point for Webpack bundle.The thing is in that both
boopler
andwoopler
packages has samejquery
dependency version. However, it’s included twice in the outputmain.js
file. And this is sad. I know, that is how resolving works but still. This is sad.You can check it out by browse main.js file, outputted by Webpack.
Possible workarounds listed here, i am up to test them, but still they’re looks clumsy.
@esr360 maybe my solution will help - https://stackoverflow.com/questions/54202131/webpack-include-vendor-in-only-one-module/54232907#54232907