<h1 dir="auto">Bug report</h1>
<p dir="auto"><strong>What is the current behavior?</strong></p>
<p dir="auto">When the same library from the same location is imported via commonjs <code class="notranslate">require</code> and es6 <code class="notranslate">import</code> results in two different instances for classes and duplicate code in the bundle.</p>
<p dir="auto"><strong>If the current behavior is a bug, please provide the steps to reproduce.</strong></p>
<p dir="auto">If an app imports a class directly and then uses a commonjs-based 3rd party library that uses the same library it results having duplicate code in the bundle and <code class="notranslate">instancesof</code> does not work properly. The real issue happens with <code class="notranslate">superstruct</code> package, however, see the demo below with boiled down-version.</p>
<p dir="auto">Visualization:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="[&quot;app&quot; - es6 / `import`] -&gt; [library] -&gt; index.es.js -&gt; class CustomError {}
         |
[3rd party module - commonjs / `require`] -&gt; [library] -&gt; index.cjs -&gt; class CustomError {}"><pre class="notranslate"><code class="notranslate">["app" - es6 / `import`] -&gt; [library] -&gt; index.es.js -&gt; class CustomError {}
         |
[3rd party module - commonjs / `require`] -&gt; [library] -&gt; index.cjs -&gt; class CustomError {}
</code></pre></div>
<p dir="auto">Repro: <a href="https://github.com/oleg-slapdash/webpack-issue-commonjs-es6-deduplication">https://github.com/oleg-slapdash/webpack-issue-commonjs-es6-deduplication</a></p>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="git clone https://github.com/oleg-slapdash/webpack-issue-commonjs-es6-deduplication
cd webpack-issue-commonjs-es6-deduplication/
cd app
yarn
yarn webpack
yarn node dist/main.js

Output:
localError.source() ===  index.es.js
thirdPartyError.source() ===  index.cjs
localError instanceof CustomError === true
thirdPartyError instanceof CustomError ===  false"><pre class="notranslate">git clone https://github.com/oleg-slapdash/webpack-issue-commonjs-es6-deduplication
<span class="pl-c1">cd</span> webpack-issue-commonjs-es6-deduplication/
<span class="pl-c1">cd</span> app
yarn
yarn webpack
yarn node dist/main.js

Output:
<span class="pl-en">localError.source</span>() ===  index.es.js
<span class="pl-en">thirdPartyError.source</span>() ===  index.cjs
localError instanceof CustomError === <span class="pl-c1">true</span>
thirdPartyError instanceof CustomError ===  <span class="pl-c1">false</span></pre></div>
<p dir="auto"><strong>What is the expected behavior?</strong></p>
<p dir="auto">Webpack should be able to de-duplicate commonjs and es6 imports of the same library. The bundle should contain only one implementation of the library and instances should be able to be checked via <code class="notranslate">instanceof</code>.</p>
<p dir="auto"><strong>Other relevant information:</strong><br>
webpack version: ^5.46.0<br>
Node.js version: v15.1.0<br>
Operating System: Mac OS 10.15.7<br>
Additional tools: N/A</p>
<p dir="auto">This is mostly to open discussion on how to solve a specific problem at this point, I only have a crude idea in my head of how this could be made to work.</p>
<p dir="auto">I currently have an isomorphic website (<a href="https://www.toons.tv" rel="nofollow">www.toons.tv</a>) that's built using React and Webpack on both the server and the client. The current build setup is quite clunky and accounts for a big portion of code in the whole project - the main reason for this is that in order to have an efficient development setup, I of course want to be watching all the assets and rebuild them when changed. However, every time the assets are rebuilt, the JS (both client and server) needs to know the new asset URLs. This means a very complex setup where webpack is only building the JS, and the rest (icon fonts, web fonts, images and other assets) is handled by gulp, and then all these update a <code class="notranslate">build-manifest.json</code> file that is required by the JS, so that the webpack builds are triggered as well.</p>
<p dir="auto">I'd like to move the asset pipeline completely to webpack instead, but this is problematic because currently you can only have one target (and set of options) per compiler, so the assets would be rebuilt twice and given that some of the assets are not generated deterministically (e.g. the icon fonts), the client could end up with different asset URLs than the server, which could easily lead to resources being loaded twice on the client.</p>
<p dir="auto">At some point, I would also like to take service workers into use, and the worker would also need the same asset URLs.</p>
<p dir="auto">One proposal that comes to mind is that you could define per-entry options:</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="webpack({
  entry: {
    client: {
      entry: &quot;/path/to/client/entry.js&quot;,
      target: &quot;browser&quot;,
    },
    server: {
      entry: &quot;/path/to/server/entry.js&quot;,
      target: &quot;node&quot;,
    },
  },
});"><pre class="notranslate"><span class="pl-en">webpack</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">entry</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">client</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">entry</span>: <span class="pl-s">"/path/to/client/entry.js"</span><span class="pl-kos">,</span>
      <span class="pl-c1">target</span>: <span class="pl-s">"browser"</span><span class="pl-kos">,</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>
    <span class="pl-c1">server</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">entry</span>: <span class="pl-s">"/path/to/server/entry.js"</span><span class="pl-kos">,</span>
      <span class="pl-c1">target</span>: <span class="pl-s">"node"</span><span class="pl-kos">,</span>
    <span class="pl-kos">}</span><span class="pl-kos">,</span>
  <span class="pl-kos">}</span><span class="pl-kos">,</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">I do realize that this would probably be a pain to implement, especially if the different entries are supposed to share parts of the pipeline while diverging at some points (e.g. if there's different plugins and/or loaders used by different entries), and also possibly require breaking changes to the plugin API, but I do hope to see this use case solved by webpack at some point.</p>
<p dir="auto">Cheers! <g-emoji class="g-emoji" alias="heart" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/2764.png">❤️</g-emoji> <g-emoji class="g-emoji" alias="sparkles" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/2728.png">✨</g-emoji></p>