FormidableLabs / inspectpack

An inspection tool for Webpack frontend JavaScript bundles.
MIT License
591 stars 20 forks source link

Missing documentation for splitting different entry points #180

Open WesSouza opened 2 years ago

WesSouza commented 2 years ago

From the README:

The webpack-stats-plugin can be configured to split up separate stats files if desired in any manner (including splitting per entry point), but this is a more advanced usage not included in this document.

This is not available anywhere, how does one split the output into multiple files without knowledge of how the Webpack compiler works?

Related to https://github.com/FormidableLabs/webpack-stats-plugin/issues/43

ryan-roemer commented 2 years ago

The webpack-stats-plugin is a fairly simple tool that just passes through the stats object, gives users a couple of ways to mutate the data, and then adds it to the webpack compilation (to actually produce the stats file along with the other asset files).

As for

without knowledge of how the Webpack compiler works?

the stats object has different shapes/fields across webpack versions IIRC, so it's a bigger lift to create a feature to do this in the webpack-stats-plugin. We could consider this, but given how simple everything else is, most stats transformation, etc. is usually left to the user (to then look at webpack docs and examine the full stats object structure).

In terms of getting you going -- how to do this for a modern webpack would be in the example code I provided there.

An updated example (with some new webpack-stats-plugin options) would work something like this (untested example):

/**
 * Multiple entry points with per-entry-point stats output example.
 */
const { StatsWriterPlugin } = require("webpack-stats-plugin");

module.exports = {
  // ... all the other webpack options ...
  entry: {
    main: "../src/main.js",
    two: "../src/main.js",
    three: "../src/main.js"
  },
  plugins: [
    new StatsWriterPlugin({
      // The plugin will not emit a stats asset. We'll individually add those in `transform()`
      emit: false,
      fields: ["assets", "modules"],
      transform({ assets, modules }, { compiler }) {
        Object.keys(assets).forEach((assetIdx) => {
          // Reconstitute assets, modules filtered by this specific asset.
          const asset = assets[assetIdx];
          const assetChunks = new Set(asset.chunks);
          const assetStr = JSON.stringify({
            assets: [asset],
            modules: modules.filter((mod) => mod.chunks.some((c) => assetChunks.has(c)))
          });

          // Convert `[hash].[name].js` to `[name]` for later use.
          // This replace depends on how you are specifying asset outputs.
          const assetName = asset.name.replace(/.*?\.(.*?)\.js/, "$1");
          // Add per-asset output.
          compiler.assets[`stats-multi-${assetName}.json`] = {
            source() { return assetStr; },
            size() { return assetStr.length; }
          };
        });
      }
    })
  ]
};

Hope that helps!