Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide a mechanism to build manualChunks which can be reused across multiple outputs. #5498

Open
Danielku15 opened this issue Apr 28, 2024 · 0 comments

Comments

@Danielku15
Copy link

Feature Use Case

I want to bundle multiple separate outputs but share some chunks across these outputs. I'm using Vite with a main application and multiple web workers being generated. But its the same when using Rollup directly with multiple inputs/outputs.

Every workers pull some functions from the shared library. Imagine a dependency chart like this:

flowchart LR
    mylib.main.mjs --> mylib.shared.mjs 
    mylib.worker.mjs --> mylib.shared.mjs 
    mylib.shared.mjs --> 3rdparty.mjs

My goal is to share the chunk between the main and worker outputs as the shared codebase can be quite heavy. To do so I defined a manualChunks for the shared file on all compilations.

But I end up with different chunks duplicating my code:

  • When I additionally set { moduleSideEffects: "no-treeshake" } via a custom plugin I end up with different chunks.
  • When I disable tree shaking fully via treeshake: false I still end up with different chunks.

The mylib-shared chunk has different exports for each compilation depending on what is imported. Hence sharing of the chunk across compilations is not possible resulting in duplicate code shipped.

Feature Proposal

Similar to the mechanisms of disabling tree shaking, there should be a way to force an export of all symbols from a chunk.

This flagging should be possible either via "moduleSideEffects" on plugins or configs:

config:

const shared = {
  manualChunks: {
    ["mylib-shared"]: mylib/mylib.shared.mjs"
  },
  treeshake: {
    moduleSideEffects(id) {
        if(id.includes('mylib.shared.mjs')) {
            return "full-exports"; // no-treeshake + unfiltered exports
        }
        return true;
    }
  }
};

export default [
  {
    input: 'main.mjs',
    output: {
      file: 'dist/main.mjs',
      format: 'es',
      ....shared
    }
  },
  {
    input: 'worker.js',
    output: {
      file: 'dist/worker.js',
      format: 'es'
       ....shared
    }
  }
];

plugin:

  plugins.push({
    name: "rollup-plugin-mylib-full-exports",
    transform(code, id) {
      if (id.includes("mylib.shared.mjs")) {
        return { moduleSideEffects: "full-exports" };
      }
    },
  });

In both outputs the mylib-shared chunk would contain the same content, with all exports from mylib.shared.mjs and produce the same hash. This way it can be shared between main.js and worker.js.

In a perfect version this "full-exports" would only prevent any tree-shaking and export removal of the specific module. e.g. any unused functions of a 3rd party lib is still removed, only the symbols of mylib remain.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant