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

Reconciling npm aliases and shared dependencies. #4311

Open
WattyRev opened this issue Nov 13, 2024 · 3 comments
Open

Reconciling npm aliases and shared dependencies. #4311

WattyRev opened this issue Nov 13, 2024 · 3 comments

Comments

@WattyRev
Copy link

Here's a proposed scenario:

Parent module has the following dependency:

"dependencies": {
  "myDep": "^2.0.0"
}

and it defines myDep as a shared dependency like so:

shared: {
  myDep: {
    requiredVersion: "^2.0.0"
  }
}

Child module that is rendered inside Parent has the following dependencies:

"dependencies": {
  "myDep-2": "npm:myDep@^2.0.0",
  "myDep": "^1.0.0"
}

and it defines shared dependencies like so:

shared: {
  myDep-2: {
    requiredVersion: "^2.0.0"
  },
  myDep: {
    requiredVersion: "^1.0.0"
  }
}

In my testing, a scenario like this will result in [email protected] being downloaded the browser once, and [email protected] being downloaded to the browser twice.
Parent is loaded and brings [email protected] with it, creating the first v2 download.
Child loads and does not find a provided dependency named "myDep-2" in order to satisfy its requiredVersion, so v2 gets downloaded again.
Child also looks for the provided "myDep" dependency, finds one that doesn't satisfy the required version, and downloads v1.

Is there any way to take a scenario like this and get Child to recognize that the parent's [email protected] satisfies its needs for myDep-2 and use it accordingly, preventing a duplicate dependency download?

@ScriptedAlchemy
Copy link
Member

ScriptedAlchemy commented Nov 14, 2024

Thats because they have different share keys.

you can try setting shareKey yourself

/*
 * This file was automatically generated.
 * DO NOT MODIFY BY HAND.
 * Run `yarn special-lint-fix` to update
 */

/**
 * Modules that should be shared in the share scope. When provided, property names are used to match requested modules in this compilation.
 */
export type Shared = (SharedItem | SharedObject)[] | SharedObject;
/**
 * A module that should be shared in the share scope.
 */
export type SharedItem = string;

/**
 * Options for shared modules.
 */
export interface SharePluginOptions {
  /**
   * Share scope name used for all shared modules (defaults to 'default').
   */
  shareScope?: string;
  /**
   * Modules that should be shared in the share scope. When provided, property names are used to match requested modules in this compilation.
   */
  shared: Shared;
}
/**
 * Modules that should be shared in the share scope. Property names are used to match requested modules in this compilation. Relative requests are resolved, module requests are matched unresolved, absolute paths will match resolved requests. A trailing slash will match all requests with this prefix. In this case shareKey must also have a trailing slash.
 */
export interface SharedObject {
  /**
   * Modules that should be shared in the share scope.
   */
  [k: string]: SharedConfig | SharedItem;
}
/**
 * Advanced configuration for modules that should be shared in the share scope.
 */
export interface SharedConfig {
  /**
   * Include the provided and fallback module directly instead behind an async request. This allows to use this shared module in initial load too. All possible shared modules need to be eager too.
   */
  eager?: boolean;
  /**
   * Provided module that should be provided to share scope. Also acts as fallback module if no shared module is found in share scope or version isn't valid. Defaults to the property name.
   */
  import?: false | SharedItem;
  /**
   * Package name to determine required version from description file. This is only needed when package name can't be automatically determined from request.
   */
  packageName?: string;
  /**
   * Version requirement from module in share scope.
   */
  requiredVersion?: false | string;
  /**
   * Module is looked up under this key from the share scope.
   */
  shareKey?: string;
  /**
   * Share scope name.
   */
  shareScope?: string;
  /**
   * Allow only a single version of the shared module in share scope (disabled by default).
   */
  singleton?: boolean;
  /**
   * Do not accept shared module if version is not valid (defaults to yes, if local fallback module is available and shared module is not a singleton, otherwise no, has no effect if there is no required version specified).
   */
  strictVersion?: boolean;
  /**
   * Version of the provided module. Will replace lower matching versions, but not higher.
   */
  version?: false | string;
}

@WattyRev
Copy link
Author

WattyRev commented Nov 14, 2024

Ah, that seems like it has nudged me in the right direction.

Based on my testing with this so far, if Child has shared config like this:

shared: {
  myDep-2: {
    requiredVersion: "^2.0.0"
    shareKey: "myDep"
  },
  myDep: {
    requiredVersion: "^1.0.0"
  }
}

In this scenario, v2 will be only downloaded once because its requiredVersion is satisfied by its parent's myDep dependency. v1 will also be downloaded because its requiredVersion is not satisfied by its parent's myDep dependency.

Very helpful, thank you!

@ScriptedAlchemy
Copy link
Member

Yes that's correct! Happy it helped. I'll update my doc site to include all the types

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

No branches or pull requests

2 participants