Repository: parcel-bundler/parcel
File: packages/core/core/src/requests/BundleGraphRequest.js (JavaScript)

Code before:

    // Recompute the cache key to account for new dev dependencies and invalidations.
    let {cacheKey: updatedCacheKey} = await this.getHashes(graph);
    this.api.storeResult(
      {
        bundlerHash,
        bundleGraph: internalBundleGraph,
        changedAssets: new Map(),
      },
      updatedCacheKey,
    );

    return {
      bundleGraph: internalBundleGraph,
      bundlerHash,
      changedAssets: changedRuntimes,
    };
  }

  async getHashes(assetGraph: AssetGraph): Promise<{|
    cacheKey: string,
    bundlerHash: string,
  |}> {
    // BundleGraphRequest needs hashes based on content (for quick retrieval)
    // and not-based on content (determine if the environment / config
    // changes that violate incremental bundling).
    let configs = (
      await Promise.all(
        [...this.configs].map(([pluginName, config]) =>
          getConfigHash(config, pluginName, this.options),
        ),
      )
    ).join('');

    let devDepRequests = [...this.devDepRequests.values()]
      .map(d => d.hash)
      .join('');

    let invalidations = await getInvalidationHash(
      this.api.getInvalidations(),
      this.options,
    );

    let plugin = await this.config.getBundler();

    return {
      cacheKey: hashString(
        PARCEL_VERSION +
          assetGraph.getHash() +
          configs +
          devDepRequests +

Review comment (performance):
Why do we need a cache key here? (And tangentially: what does `storeResult` even do compared to just the return value of the run function?)

Code after:
        previousDevDeps: this.previousDevDeps,
        devDepRequests: this.devDepRequests,
        configs: this.configs,
      });

      // Store the serialized bundle graph in an in memory cache so that we avoid serializing it
      // many times to send to each worker, and in build mode, when writing to cache on shutdown.
      // Also, pre-compute the hashes for each bundle so they are only computed once and shared between workers.
      internalBundleGraph.getBundleGraphHash();
      cacheSerializedObject(internalBundleGraph);
    }

    await dumpGraphToGraphViz(
      // $FlowFixMe
      internalBundleGraph._graph,
      'after_runtimes',
      bundleGraphEdgeTypes,
    );

    this.api.storeResult(
      {
        bundleGraph: internalBundleGraph,
        changedAssets: new Map(),
        assetRequests: [],
      },
      this.cacheKey,
    );

    return {
      bundleGraph: internalBundleGraph,
      changedAssets: changedRuntimes,
      assetRequests,
    };
  }

  async nameBundles(bundleGraph: InternalBundleGraph): Promise<void> {
    let namers = await this.config.getNamers();
    // inline bundles must still be named so the PackagerRunner
    // can match them to the correct packager/optimizer plugins.
    let bundles = bundleGraph.getBundles({includeInline: true});
    await Promise.all(
      bundles.map(bundle => this.nameBundle(namers, bundle, bundleGraph)),
    );

    // Add dev deps for namers, AFTER running them to account for lazy require().
    for (let namer of namers) {
      let devDepRequest = await createDevDependency(
        {
          specifier: namer.name,
          resolveFrom: namer.resolveFrom,
        },