bundle({ bundleGraph }) {
    let bundleRoots /*: Map<Bundle, Array<Asset>> */ = new Map();
    let bundlesByEntryAsset /*: Map<Asset, Bundle> */ = new Map();
    let siblingBundlesByAsset /*: Map<string, Array<Bundle>> */ = new Map();

    // Step 1: create bundles for each of the explicit code split points.
    bundleGraph.traverse({
      enter: (node, context, actions) => {
        if (node.type !== "dependency") {
          return {
            ...context,
            bundleGroup: context && context.bundleGroup,
            bundleByType: context && context.bundleByType,
            parentNode: node,
            parentBundle:
              bundlesByEntryAsset.get(node.value) || (context && context.parentBundle),
          };
        }

        let dependency = node.value;
        // if (bundleGraph.isDependencySkipped(dependency)) {
        //   actions.skipChildren();
        //   return;
        // }

        let assets = bundleGraph.getDependencyAssets(dependency);
        let resolution = bundleGraph.getDependencyResolution(dependency);
        // Create a new bundle for entries, async deps, isolated assets, and inline assets.
        if (
          (dependency.isEntry && resolution) ||
          (dependency.isAsync && resolution) ||
          (dependency.isIsolated && resolution) ||
          (resolution && resolution.isIsolated) ||
          (resolution && resolution.isInline)
        ) {
          let bundleGroup = context && context.bundleGroup;
          let bundleByType /*: Map<string, Bundle> */ =
            (context && context.bundleByType) || new Map();

          // Only create a new bundle group for entries, async dependencies, and isolated assets.
          // Otherwise, the bundle is loaded together with the parent bundle.
          if (
            !bundleGroup ||
            dependency.isEntry ||
            dependency.isAsync ||
            resolution.isIsolated
          ) {
            bundleGroup = bundleGraph.createBundleGroup(
              dependency,
              nullthrows(dependency.target || (context && context.bundleGroup && context.bundleGroup.target))
            );

            bundleByType = new Map();
          }

          for (let asset of assets) {
            let bundle = bundleGraph.createBundle({
              entryAsset: asset,
              isEntry:
                asset.isIsolated || asset.isInline
                  ? false
                  : Boolean(dependency.isEntry),
              isInline: asset.isInline,
              target: bundleGroup.target,
            });
            bundleByType.set(bundle.type, bundle);
            bundlesByEntryAsset.set(asset, bundle);
            siblingBundlesByAsset.set(asset.id, []);
            bundleGraph.addBundleToBundleGroup(bundle, bundleGroup);

            // The bundle may have already been created, and the graph gave us back the original one...
            if (!bundleRoots.has(bundle)) {
              bundleRoots.set(bundle, [asset]);
            }

            // If the bundle is in the same bundle group as the parent, create an asset reference
            // between the dependency and the asset, and a bundle reference between the parent bundle
            // and the child bundle.
            if (bundleGroup === (context && context.bundleGroup)) {
              bundleGraph.createAssetReference(dependency, asset);
              bundleGraph.createBundleReference(
                nullthrows(context && context.parentBundle),
                bundle
              );
            }
          }

          return {
            bundleGroup,
            bundleByType,
            parentNode: node,
            parentBundle: context && context.parentBundle,
          };
        }

        invariant(context != null);
        invariant(context.parentNode.type === "asset");
        invariant(context.parentBundle != null);
        let parentAsset = context.parentNode.value;
        let parentBundle = context.parentBundle;
        let bundleGroup = nullthrows(context.bundleGroup);
        let bundleByType = nullthrows(context.bundleByType);
        let siblingBundles = nullthrows(
          siblingBundlesByAsset.get(parentAsset.id)
        );
        let allSameType = assets.every((a) => a.type === parentAsset.type);

        for (let asset of assets) {
          let siblings = siblingBundlesByAsset.get(asset.id);

          if (parentAsset.type === asset.type) {
            if (allSameType && siblings) {
              // If any sibling bundles were created for this asset or its subtree previously,
              // add them all to the current bundle group as well. This fixes cases where two entries
              // depend on a shared asset which has siblings. Due to DFS, the subtree of the shared
              // asset is only processed once, meaning any sibling bundles created due to type changes
              // would only be connected to the first bundle group. To work around this, we store a list
              // of sibling bundles for each asset in the graph, and when we re-visit a shared asset, we
              // connect them all to the current bundle group as well.
              for (let bundle of siblings) {
                bundleGraph.addBundleToBundleGroup(bundle, bundleGroup);
              }
            } else if (!siblings) {
              // Propagate the same siblings further if there are no bundles being created in this
              // asset group, otherwise start a new set of siblings.
              siblingBundlesByAsset.set(
                asset.id,
                allSameType ? siblingBundles : []
              );
            }

            continue;
          }

          let existingBundle = bundleByType.get(asset.type);
          if (existingBundle) {
            // If a bundle of this type has already been created in this group,
            // merge this subgraph into it.
            nullthrows(bundleRoots.get(existingBundle)).push(asset);
            bundlesByEntryAsset.set(asset, existingBundle);
            bundleGraph.createAssetReference(dependency, asset);
          } else {
            let bundle = bundleGraph.createBundle({
              uniqueKey: asset.id,
              env: asset.env,
              type: asset.type,
              target: bundleGroup.target,
              isEntry:
                asset.isInline || dependency.isEntry === false
                  ? false
                  : parentBundle.isEntry,
              isInline: asset.isInline,
              isSplittable: asset.isSplittable || true,
              pipeline: asset.pipeline,
            });
            bundleByType.set(bundle.type, bundle);
            siblingBundles.push(bundle);
            bundlesByEntryAsset.set(asset, bundle);
            bundleGraph.createAssetReference(dependency, asset);
            bundleGraph.createBundleReference(parentBundle, bundle);
            bundleGraph.addBundleToBundleGroup(bundle, bundleGroup);

            // The bundle may have already been created, and the graph gave us back the original one...
            if (!bundleRoots.has(bundle)) {
              bundleRoots.set(bundle, [asset]);
            }
          }

          if (!siblings) {
            siblingBundlesByAsset.set(asset.id, []);
          }
        }

        return {
          ...context,
          parentNode: node,
        };
      },
    });

    for (let [bundle, rootAssets] of bundleRoots) {
      for (let asset of rootAssets) {
        bundleGraph.addEntryToBundle(asset, bundle, (dependency) => {
          let resolution = bundleGraph.getDependencyResolution(dependency);
          return (
            bundleGraph.isDependencySkipped(dependency) &&
            (!resolution || path.basename(resolution.filePath) !== "b.js")
          )
        });
      }
    }
  }
// 6. If two assets are always seen together, put them in the same extracted bundle
6. If two assets are always seen together, put them in the same extracted bundle
6 . If two assets are always seen together put them in the same extracted bundle
bundle({ bundleGraph }) {
    let bundleRoots  = new Map();
    let bundlesByEntryAsset  = new Map();
    let siblingBundlesByAsset  = new Map();
    bundleGraph.traverse({
      enter: (node, context, actions) => {
        if (node.type !== "dependency") {
          return {
            ...context,
            bundleGroup: context && context.bundleGroup,
            bundleByType: context && context.bundleByType,
            parentNode: node,
            parentBundle:
              bundlesByEntryAsset.get(node.value) || (context && context.parentBundle),
          };
        }
        let dependency = node.value;
        let assets = bundleGraph.getDependencyAssets(dependency);
        let resolution = bundleGraph.getDependencyResolution(dependency);
        if (
          (dependency.isEntry && resolution) ||
          (dependency.isAsync && resolution) ||
          (dependency.isIsolated && resolution) ||
          (resolution && resolution.isIsolated) ||
          (resolution && resolution.isInline)
        ) {
          let bundleGroup = context && context.bundleGroup;
          let bundleByType  =
            (context && context.bundleByType) || new Map();
          if (
            !bundleGroup ||
            dependency.isEntry ||
            dependency.isAsync ||
            resolution.isIsolated
          ) {
            bundleGroup = bundleGraph.createBundleGroup(
              dependency,
              nullthrows(dependency.target || (context && context.bundleGroup && context.bundleGroup.target))
            );
            bundleByType = new Map();
          }
          for (let asset of assets) {
            let bundle = bundleGraph.createBundle({
              entryAsset: asset,
              isEntry:
                asset.isIsolated || asset.isInline
                  ? false
                  : Boolean(dependency.isEntry),
              isInline: asset.isInline,
              target: bundleGroup.target,
            });
            bundleByType.set(bundle.type, bundle);
            bundlesByEntryAsset.set(asset, bundle);
            siblingBundlesByAsset.set(asset.id, []);
            bundleGraph.addBundleToBundleGroup(bundle, bundleGroup);
            if (!bundleRoots.has(bundle)) {
              bundleRoots.set(bundle, [asset]);
            }
            if (bundleGroup === (context && context.bundleGroup)) {
              bundleGraph.createAssetReference(dependency, asset);
              bundleGraph.createBundleReference(
                nullthrows(context && context.parentBundle),
                bundle
              );
            }
          }
          return {
            bundleGroup,
            bundleByType,
            parentNode: node,
            parentBundle: context && context.parentBundle,
          };
        }
        invariant(context != null);
        invariant(context.parentNode.type === "asset");
        invariant(context.parentBundle != null);
        let parentAsset = context.parentNode.value;
        let parentBundle = context.parentBundle;
        let bundleGroup = nullthrows(context.bundleGroup);
        let bundleByType = nullthrows(context.bundleByType);
        let siblingBundles = nullthrows(
          siblingBundlesByAsset.get(parentAsset.id)
        );
        let allSameType = assets.every((a) => a.type === parentAsset.type);
        for (let asset of assets) {
          let siblings = siblingBundlesByAsset.get(asset.id);
          if (parentAsset.type === asset.type) {
            if (allSameType && siblings) {
              for (let bundle of siblings) {
                bundleGraph.addBundleToBundleGroup(bundle, bundleGroup);
              }
            } else if (!siblings) {
              siblingBundlesByAsset.set(
                asset.id,
                allSameType ? siblingBundles : []
              );
            }
            continue;
          }
          let existingBundle = bundleByType.get(asset.type);
          if (existingBundle) {
            nullthrows(bundleRoots.get(existingBundle)).push(asset);
            bundlesByEntryAsset.set(asset, existingBundle);
            bundleGraph.createAssetReference(dependency, asset);
          } else {
            let bundle = bundleGraph.createBundle({
              uniqueKey: asset.id,
              env: asset.env,
              type: asset.type,
              target: bundleGroup.target,
              isEntry:
                asset.isInline || dependency.isEntry === false
                  ? false
                  : parentBundle.isEntry,
              isInline: asset.isInline,
              isSplittable: asset.isSplittable || true,
              pipeline: asset.pipeline,
            });
            bundleByType.set(bundle.type, bundle);
            siblingBundles.push(bundle);
            bundlesByEntryAsset.set(asset, bundle);
            bundleGraph.createAssetReference(dependency, asset);
            bundleGraph.createBundleReference(parentBundle, bundle);
            bundleGraph.addBundleToBundleGroup(bundle, bundleGroup);
            if (!bundleRoots.has(bundle)) {
              bundleRoots.set(bundle, [asset]);
            }
          }
          if (!siblings) {
            siblingBundlesByAsset.set(asset.id, []);
          }
        }
        return {
          ...context,
          parentNode: node,
        };
      },
    });
    for (let [bundle, rootAssets] of bundleRoots) {
      for (let asset of rootAssets) {
        bundleGraph.addEntryToBundle(asset, bundle, (dependency) => {
          let resolution = bundleGraph.getDependencyResolution(dependency);
          return (
            bundleGraph.isDependencySkipped(dependency) &&
            (!resolution || path.basename(resolution.filePath) !== "b.js")
          )
        });
      }
    }
  }
bundle ( { bundleGraph } ) { let bundleRoots = new Map ( ) ; let bundlesByEntryAsset = new Map ( ) ; let siblingBundlesByAsset = new Map ( ) ; bundleGraph . traverse ( { enter : ( node , context , actions ) => { if ( node . type !== "dependency" ) { return { ... context , bundleGroup : context && context . bundleGroup , bundleByType : context && context . bundleByType , parentNode : node , parentBundle : bundlesByEntryAsset . get ( node . value ) || ( context && context . parentBundle ) , } ; } let dependency = node . value ; let assets = bundleGraph . getDependencyAssets ( dependency ) ; let resolution = bundleGraph . getDependencyResolution ( dependency ) ; if ( ( dependency . isEntry && resolution ) || ( dependency . isAsync && resolution ) || ( dependency . isIsolated && resolution ) || ( resolution && resolution . isIsolated ) || ( resolution && resolution . isInline ) ) { let bundleGroup = context && context . bundleGroup ; let bundleByType = ( context && context . bundleByType ) || new Map ( ) ; if ( ! bundleGroup || dependency . isEntry || dependency . isAsync || resolution . isIsolated ) { bundleGroup = bundleGraph . createBundleGroup ( dependency , nullthrows ( dependency . target || ( context && context . bundleGroup && context . bundleGroup . target ) ) ) ; bundleByType = new Map ( ) ; } for ( let asset of assets ) { let bundle = bundleGraph . createBundle ( { entryAsset : asset , isEntry : asset . isIsolated || asset . isInline ? false : Boolean ( dependency . isEntry ) , isInline : asset . isInline , target : bundleGroup . target , } ) ; bundleByType . set ( bundle . type , bundle ) ; bundlesByEntryAsset . set ( asset , bundle ) ; siblingBundlesByAsset . set ( asset . id , [ ] ) ; bundleGraph . addBundleToBundleGroup ( bundle , bundleGroup ) ; if ( ! bundleRoots . has ( bundle ) ) { bundleRoots . set ( bundle , [ asset ] ) ; } if ( bundleGroup === ( context && context . bundleGroup ) ) { bundleGraph . createAssetReference ( dependency , asset ) ; bundleGraph . createBundleReference ( nullthrows ( context && context . parentBundle ) , bundle ) ; } } return { bundleGroup , bundleByType , parentNode : node , parentBundle : context && context . parentBundle , } ; } invariant ( context != null ) ; invariant ( context . parentNode . type === "asset" ) ; invariant ( context . parentBundle != null ) ; let parentAsset = context . parentNode . value ; let parentBundle = context . parentBundle ; let bundleGroup = nullthrows ( context . bundleGroup ) ; let bundleByType = nullthrows ( context . bundleByType ) ; let siblingBundles = nullthrows ( siblingBundlesByAsset . get ( parentAsset . id ) ) ; let allSameType = assets . every ( ( a ) => a . type === parentAsset . type ) ; for ( let asset of assets ) { let siblings = siblingBundlesByAsset . get ( asset . id ) ; if ( parentAsset . type === asset . type ) { if ( allSameType && siblings ) { for ( let bundle of siblings ) { bundleGraph . addBundleToBundleGroup ( bundle , bundleGroup ) ; } } else if ( ! siblings ) { siblingBundlesByAsset . set ( asset . id , allSameType ? siblingBundles : [ ] ) ; } continue ; } let existingBundle = bundleByType . get ( asset . type ) ; if ( existingBundle ) { nullthrows ( bundleRoots . get ( existingBundle ) ) . push ( asset ) ; bundlesByEntryAsset . set ( asset , existingBundle ) ; bundleGraph . createAssetReference ( dependency , asset ) ; } else { let bundle = bundleGraph . createBundle ( { uniqueKey : asset . id , env : asset . env , type : asset . type , target : bundleGroup . target , isEntry : asset . isInline || dependency . isEntry === false ? false : parentBundle . isEntry , isInline : asset . isInline , isSplittable : asset . isSplittable || true , pipeline : asset . pipeline , } ) ; bundleByType . set ( bundle . type , bundle ) ; siblingBundles . push ( bundle ) ; bundlesByEntryAsset . set ( asset , bundle ) ; bundleGraph . createAssetReference ( dependency , asset ) ; bundleGraph . createBundleReference ( parentBundle , bundle ) ; bundleGraph . addBundleToBundleGroup ( bundle , bundleGroup ) ; if ( ! bundleRoots . has ( bundle ) ) { bundleRoots . set ( bundle , [ asset ] ) ; } } if ( ! siblings ) { siblingBundlesByAsset . set ( asset . id , [ ] ) ; } } return { ... context , parentNode : node , } ; } , } ) ; for ( let [ bundle , rootAssets ] of bundleRoots ) { for ( let asset of rootAssets ) { bundleGraph . addEntryToBundle ( asset , bundle , ( dependency ) => { let resolution = bundleGraph . getDependencyResolution ( dependency ) ; return ( bundleGraph . isDependencySkipped ( dependency ) && ( ! resolution || path . basename ( resolution . filePath ) !== "b.js" ) ) } ) ; } } }
6.
6 .
/*: Map<Bundle, Array<Asset>> */ /*: Map<Asset, Bundle> */ /*: Map<string, Array<Bundle>> */ // Step 1: create bundles for each of the explicit code split points. // if (bundleGraph.isDependencySkipped(dependency)) { //   actions.skipChildren(); //   return; // } // Create a new bundle for entries, async deps, isolated assets, and inline assets. /*: Map<string, Bundle> */ // Only create a new bundle group for entries, async dependencies, and isolated assets. // Otherwise, the bundle is loaded together with the parent bundle. // The bundle may have already been created, and the graph gave us back the original one... // If the bundle is in the same bundle group as the parent, create an asset reference // between the dependency and the asset, and a bundle reference between the parent bundle // and the child bundle. // If any sibling bundles were created for this asset or its subtree previously, // add them all to the current bundle group as well. This fixes cases where two entries // depend on a shared asset which has siblings. Due to DFS, the subtree of the shared // asset is only processed once, meaning any sibling bundles created due to type changes // would only be connected to the first bundle group. To work around this, we store a list // of sibling bundles for each asset in the graph, and when we re-visit a shared asset, we // connect them all to the current bundle group as well. // Propagate the same siblings further if there are no bundles being created in this // asset group, otherwise start a new set of siblings. // If a bundle of this type has already been created in this group, // merge this subgraph into it. // The bundle may have already been created, and the graph gave us back the original one...