webpack icon indicating copy to clipboard operation
webpack copied to clipboard

Webpack doesn't split third party library code between bundles

Open LeeKatz1 opened this issue 5 years ago • 18 comments

Bug report

What is the current behavior? The code splitting, using Webpack with Loadable plugin, doesn’t split the code to the correct bundle. It happens when both bundles use the same third party library, but each one imports a different code from that library. The actual result is that the main bundle includes both of the imported codes from the third party library.

For example, using React:

This is the entry point of webpack: index.js

import { Component1 } from 'third-party-components-library';
import * as React from 'react';
import loadable from '@loadable/component';

export const MainComponent = () => {
  const LoadableComponent = loadable(() => import('./LoadableComponent'));
  return (
    <Component1>
      <LoadableComponent />
    </Component1>
  );
};

This is the loadable component: LoadableComponent.js

import { Component2 } from 'third-party-components-library';
import * as React from 'react';

const LoadableComponent = () => {
  return (
    <Component2/>
  );
};
export default LoadableComponent;

Two separated bundles are created: First for index.js, which is the webpack entry point, and the second for LoadableComponent.js. The first one includes both codes for Component1 and Component2 from ‘third-party-components-library’. The second one doesn’t include any code from ‘third-party-components-library’.

If the current behavior is a bug, please provide the steps to reproduce. Use the loadable-components library via its webpack plugin: https://loadable-components.com/docs/getting-started/ https://loadable-components.com/docs/api-loadable-webpack-plugin/ The main bundle, which is the bundle that is created from the webpack entrypoint, should import a component from a third party library. The main bundle should include a loadable-component. The loadable-component should import a different component from the same third party library.

What is the expected behavior? The expected behavior is that webpack will split the code between the main bundle and the loadable bundle in a way that each bundle includes only the relevant code from the third party library. In the context of the previous example: The main bundle (for index.js entry point) should include only the code for Component1 from 'third-party-components-library' and the second bundle (for LoadableComponent.js) should include only the code for Component2 from 'third-party-components-library'.

Other relevant information: webpack version: 5.0.0 Node.js version: 12.18.0 Operating System: Additional tools:

LeeKatz1 avatar Oct 14 '20 07:10 LeeKatz1

Please open an issue in @loadable/webpack-plugin, if you need help please provide reproducible test repo

alexander-akait avatar Oct 14 '20 11:10 alexander-akait

That's a webpack thing, but we don't support that (yet). And probably won't support it in near future.

It's only working if each piece is in an separate file and the main file reexports them and is flagged as side effect free.

sokra avatar Oct 14 '20 17:10 sokra

if theres a static import, then webpack needs to provide it upfront as part of the main bundle since some pages might need it.

ScriptedAlchemy avatar Oct 15 '20 21:10 ScriptedAlchemy

@sokra - I believe I'm having a similar issue (using regular dynamic import(), not loadable-components) after upgrading from 4.x to 5.x - it worked as expected in 4.x. As a result the main bundle size of our app will increase dramatically in 5.x.

It's only working if each piece is in an separate file and the main file reexports them and is flagged as side effect free.

The 3rd party package includes "sideEffects": "false" and the components are all in separate files. Maybe I'm misunderstanding your comment?

joshjg avatar Nov 17 '20 18:11 joshjg

This issue had no activity for at least three months.

It's subject to automatic issue closing if there is no activity in the next 15 days.

webpack-bot avatar Feb 17 '21 12:02 webpack-bot

@sokra Any idea what change from v4-v5 could cause this? This is blocking my team from upgrading to v5.

Update: I investigated some more and traced it to a 3rd party package re-exporting a different 3rd party package, i.e.

// third-party-package-a index.ts
export * from 'third-party-package-b';

which leads to this bailout:

ModuleConcatenation bailout: List of module exports is dynamic

After locally replacing the star export with the explicit named exports, the issue is resolved.

joshjg avatar May 10 '21 19:05 joshjg

Can you show third-party-package-b export?

alexander-akait avatar May 11 '21 13:05 alexander-akait

Bump - we still should address this it not already

ScriptedAlchemy avatar Jun 02 '21 00:06 ScriptedAlchemy

Should work with webpack@5. Feel free to report new issue with reproducible repo.

take a look into runtime feature

vankop avatar Sep 15 '21 21:09 vankop

Still valid

alexander-akait avatar Sep 16 '21 11:09 alexander-akait

@alexander-akait I actually don't understand what is an issue? original issue fixed in webpack@5

vankop avatar Sep 16 '21 11:09 vankop

@vankop Can you provide link on PR?

alexander-akait avatar Sep 16 '21 11:09 alexander-akait

@alexander-akait did not find MR. here is demo https://github.com/vankop/webpack-runtime/tree/main/dist 2 separate chunks in output with different tree shaking

vankop avatar Sep 16 '21 11:09 vankop

@vankop Try to use original code from the issue

alexander-akait avatar Sep 16 '21 12:09 alexander-akait

Related https://github.com/webpack/webpack/issues/7782, small example https://github.com/webpack/webpack/issues/7782#issuecomment-407694117 and bundle, we can move this code to shared chunk, but keep them both in each chunk

alexander-akait avatar Sep 16 '21 13:09 alexander-akait

from issue text:

What is the expected behavior?
The expected behavior is that webpack will split the code between the main bundle
and the loadable bundle in a way that each bundle includes only the relevant code from the third party library.

As I said this is possible within different runtimes

If you have one runtime, webpack can not do this, because one module can be executed once

vankop avatar Sep 16 '21 13:09 vankop

I don't see how runtime fix this problem

alexander-akait avatar Sep 16 '21 13:09 alexander-akait

Issue was closed because of inactivity.

If you think this is still a valid issue, please file a new issue with additional information.

webpack-bot avatar Jan 01 '22 10:01 webpack-bot