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

Support for per-chunk breakdown? #39

Open
MrBlenny opened this issue May 14, 2017 · 2 comments
Open

Support for per-chunk breakdown? #39

MrBlenny opened this issue May 14, 2017 · 2 comments

Comments

@MrBlenny
Copy link

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.

@robertknight
Copy link
Owner

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.

@MrBlenny
Copy link
Author

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)
  })
})

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

No branches or pull requests

2 participants