web-infra-dev / rspack

The fast Rust-based web bundler with webpack-compatible API 🦀️
https://rspack.dev
MIT License
9.76k stars 561 forks source link

Support DLLPlugin #4036

Open andtii opened 1 year ago

andtii commented 1 year ago

What problem does this feature solve?

The thing stopping us from use rspack is that we rely heavily on the dllplugin (https://webpack.js.org/plugins/dll-plugin/). Is it possible to add the support in rspack?

What does the proposed API of configuration look like?

https://webpack.js.org/plugins/dll-plugin/

hardfist commented 1 year ago

what's your usage of dllplugin?

ScriptedAlchemy commented 1 year ago

@andtii you could swap out dll plugin with module federation shared modules. This is at runtime and not as unreliable or prone to central failure as dll and externals. Federation is DLL at runtime, more or less. Same effect.

The reason i mention federation is we will likely pick up support for Module Federation in next Q. Would federation module sharing work?

andtii commented 1 year ago

@hardfist @ScriptedAlchemy We use the dllplugin and dllreference in our custom build system we have created where we are using manifests to specify which resources should end up in which bundles and then are then using this over multiple projects and have built a custom loader that dynamically loads the manifest and bundles based on the load rules specified in the manifests. To make this work we need to do it on build time so im not sure if module federation helps in this case? We basically have our own module fedaration framwork but use the dllplugin as part of the build step

ScriptedAlchemy commented 1 year ago

Federation was founded on DLL. If you look at classes. We have container pkugin and container reference. You can control the at runtime dependency loading or decisioning. As far as I know it can do anything DLL could, plus more - but it's mansifest are baked into the runtime

sergei-startsev commented 1 year ago

@ScriptedAlchemy while MF can potentially replace DllPlugin and DllReferencePlugin in some scenarios, its distributed nature is a significant limitation for others.

In our world we use DllPlugin and DllReferencePlugin to implement an effective caching strategy for a large multipage app (>300 pages). We use clustering algorithms to build a tree of bundles chains in which parent bundles share their entries with child bundles, so child bundles don't include modules included in parent packages.

image

Essentially, you need to build a tree of bundles that contain shared modules, where leaves of this tree are "applications". It's possible because child bundles "know" about parent ones at build time. MF was designed to not know anything about manifests of dependent bundles at build time. MF key feature is the main limitation in this scenario.

andtii commented 1 year ago

Thank you @sergei-startsev this is what we use it for also but you explained it in a better way im not familiar with how MF works

ScriptedAlchemy commented 1 year ago

Gotcha. Thanks for the information.

andtii commented 1 year ago

@hardfist Do you think this will ever happen or else we ne need to start looking for alternatives because our build times is not funny right now :(

hardfist commented 1 year ago

@hardfist Do you think this will ever happen or else we ne need to start looking for alternatives because our build times is not funny right now :(

sorry we are not gonna support dll plugin in the near future,we will revisit it when we have manpower,it is low priority now,we will implement MF this quarter

andtii commented 10 months ago

Hey @hardfist new year so maybe this could part of upcoming sprint?

hardfist commented 10 months ago

Hey @hardfist new year so maybe this could part of upcoming sprint?

FYI we already support MF, and I can fully understand your usage about DLLPlugin, but the team doesn't have extra man power to implement this feature due to the complex of this feature, but we're opening for outside contributions for this feature, we may revisit it when we have extra man power

ScriptedAlchemy commented 10 months ago

Rspack includes v1.5 update of module federation apis. DLL and DLLReference are very similar to Container and ContainerReference, just the json versions of them, but its still externals.

IF caching is the main concern here, due to federation historically being nondeterministic about "what" it picks from "where" - we have introduced a runtime api which does provide a resolveShare hook, which would let you control where "react" is got from each time. In this case, you could create a vendor remote of sorts, and all applications will resolve any shared module requests first to the "vendor" container before looking elsewhere for a module.

Might not serve your need, but within the context of wanting predictable cacheable resource loading... you can achieve same via federation. you could also set shared modules to import:false in MFP config, this would mean those bundles will no include any fallback and be totally dependent on someone else vending it its dependency. Giving you the single point of failure approach that DLL plugin did, which was make eveything externals and dont tree shake those exports out of someone else.

For example, in next.js i use this runtime plugin api to make share always resolve to the host for react or next.js deps.

    resolveShare(args) {
      if (
        args.pkgName !== 'react' &&
        args.pkgName !== 'react-dom' &&
        !args.pkgName.startsWith('next/')
      ) {
        return args;
      }
      const { shareScopeMap, scope, pkgName, version, GlobalFederation } = args;

      const host = GlobalFederation['__INSTANCES__'][0];
      if (!host) {
        return args;
      }
      args.resolver = function () {
       //could also be return window.vendorBundle.options.shared[pkgName]
        shareScopeMap[scope][pkgName][version] = host.options.shared[pkgName]; // replace local share scope manually with desired module
        return shareScopeMap[scope][pkgName][version];
      };
      return args;
    },
ScriptedAlchemy commented 10 months ago

this would be the same as DLL, if you served the assets together (vendor remote + the bundle), you can control the module routing and force everyone to explicitly load from vendorRemote, thus you can cache it knowing everyone will always prefer it if it exists, but federation could let you provide fallback in event of missing DLL bundle.

const vendorRemote = GlobalFederation.INSTANCES.find((container)=>container.name === 'vendorBundle')

I think thats the closest youll get without someone copying over similar implementation of container and container reference to DLL and DLLReference. Or porting the JS plugin to rust in a PR

stale[bot] commented 6 months ago

This issue has been automatically marked as stale because it has not had recent activity. If this issue is still affecting you, please leave any comment (for example, "bump"). We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!

andtii commented 6 months ago

@hardfist Any updates? Could this be implemented soon?

andtii commented 6 months ago

@sergei-startsev Did you find any other solution?

sergei-startsev commented 6 months ago

@andtii I don't see any other real options for our scenarios other than DLLPlugin & DLLReferencePlugin support.

If Rspack considers compatibility with existing webpack plugins as a competitive advantage, I believe that support of core webpack plugins is crucial. If I have to reinvent my ecosystem from scratch, I don't see why Rspack is better than other options available today.

zackarychapple commented 6 months ago

Nuding this one as well, its part of a project migration.

stale[bot] commented 4 months ago

This issue has been automatically marked as stale because it has not had recent activity. If this issue is still affecting you, please leave any comment (for example, "bump"). We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!

hardfist commented 4 months ago

bump

andtii commented 4 months ago

@hardfist I read somewhere that it could be possible to run plugins using the js version of webpack plugins but it will be slower does this mean we can still move to rspack?

ScriptedAlchemy commented 4 months ago

After I finish http import APIs I'll take a look at this plugin and see how hard it would be to port into rust.

stale[bot] commented 2 months ago

This issue has been automatically marked as stale because it has not had recent activity. If this issue is still affecting you, please leave any comment (for example, "bump"). We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!

hardfist commented 2 months ago

bump

andtii commented 2 weeks ago

@ScriptedAlchemy Did you have time to do some investigation?

GiveMe-A-Name commented 2 weeks ago

@ScriptedAlchemy Did you have time to do some investigation?

I working on investigation, I will start develop directly or write RFC firstly watch the situation in this week.

GiveMe-A-Name commented 2 days ago

Implement by https://github.com/web-infra-dev/rspack/pull/8296