webpack-bundle-size-analyzer icon indicating copy to clipboard operation
webpack-bundle-size-analyzer copied to clipboard

Support for per-chunk breakdown?

Open MrBlenny opened this issue 8 years ago • 2 comments

Is there any way the output can be split out by the bundle? I'm not currently sure how to use this in a multi-chunk webpack build.

MrBlenny avatar May 14 '17 03:05 MrBlenny

webpack-bundle-size-analyzer currently does not support reporting a breakdown by chunk, but there is enough information in the output from webpack --json that this could be implemented. Help with this would be welcome.

It currently generates the breakdown by processing the modules array in the JSON output, which is an array of all modules that appear in all chunks. There is also a chunks array in the JSON output, each of which contains a modules array that contains only the modules that appear in that chunk.

robertknight avatar May 14 '17 05:05 robertknight

Unfortunately I couldn't quite figure out what was going on so I wrote my own. This will give a breakdown of every chunk. Maybe useful to someone that needs the chunk breakdown...

image

const Promise = require('bluebird')
const fs = Promise.promisifyAll(require('fs'))
const path = require('path')
const _ = require('lodash')
const colors = require('colors')

// Change the path to your stats.json here
const pathToStats = '../reports/stats.json'

const toBytes = (bytes, precision = 1) => {
  if (bytes==='0' || bytes===0 || isNaN(parseFloat(bytes)) || !isFinite(bytes)) {
    return '-'
  }
  const units = ['B', 'kB', 'MB', 'GB', 'TB', 'PB']
  const number = Math.floor(Math.log(bytes) / Math.log(1024))
  return (bytes / Math.pow(1024, Math.floor(number))).toFixed(precision) + ' ' + units[number];
}

fs.readFileAsync(path.join(__dirname, pathToStats)).then((data) => {
  const stats = JSON.parse(data)

  const chunkedModules = {}
  stats.modules.forEach((module) => {
    module.chunks.forEach((chunkId) => {
      const alreadyExists = !!chunkedModules[chunkId]
      if (alreadyExists) {
        chunkedModules[chunkId].push(module)
      } else {
        chunkedModules[chunkId] = [module]
      }
    })
  })

  Object.keys(chunkedModules).forEach((chunkId) => {
    const chunk = chunkedModules[chunkId]
    console.log(`\n------------------------------------ Chunk ${chunkId} ------------------------------------`.green)
    const totalSize = _.sum(chunk.map(chunk => chunk.size))
    console.log(`Total Size: ${toBytes(totalSize)}\n`.green)

    const chunkHeirachy = {}

    const orderedChunk = _.orderBy(chunk, ['size', 'name'], ['desc', 'asc'])    

    orderedChunk.forEach((module) => {
      const nameReplaced = module.name.replace('./', '').replace('~/', '')
      const nameSplit = nameReplaced.split('/')

      _.set(chunkHeirachy, nameSplit, {
        name: nameReplaced,
        size: module.size,
        chunks: module.chunks,
        level: nameSplit.length - 1,
        baseLevel: true,
      })
    })

    const getSize = (items) => {
      return _.sum(Object.keys(items).map((itemName) => {
        const item = items[itemName]
        if (item.baseLevel) {
          return item.size
        } else {
          return getSize(item)
        }
      }))
    }

    const spacing = 3
    const logItems = (items = {}, level) => {
      const spacer = new Array(level * spacing + 1).join(' ')

      Object.keys(items).forEach((itemName) => {
        const item = items[itemName]
        if (!item.baseLevel) {
          const size = getSize(item)
          const sizeString = `${toBytes(size)}          `
          const sizeStringLimited = sizeString.substring(0, 7)
          console.log(`${spacer}${sizeStringLimited}`.red, `${itemName}`)
          logItems(item, level + 1)
        } else {
          const size = item.size
          const sizeString = `${toBytes(size)}          `
          const sizeStringLimited = sizeString.substring(0, 7)
          console.log(`${spacer}${sizeStringLimited}`.red, `${itemName}`)
        }
      })
    }

    logItems(chunkHeirachy, 0)
  })
})


MrBlenny avatar May 14 '17 14:05 MrBlenny