Skip to content

Improvement to build report for statically compressed assets #20718

@thebanjomatic

Description

@thebanjomatic

Description

When using plugins (such as vite-plugin-compression2) to compress assets at build time, the build reporter's output is more verbose than I would like since each compressed asset becomes an additional line item (instead of being treated as an encoding of the original asset):

Image

Additionally, because reportCompressedSize is true (default behavior), we are essentially running a second gzip pass with different settings than what the plugin uses, so we are doing extra processing and get slightly different results.

Ideally, I would like for reportCompressedSize to be aware of the common extensions for .gz, .br, and .zst and to be able to consolidate the above into:

dist/client/index.html                     10.37 kB
dist/client/assets/index-LK--dcdj.css     123.58 kB │ gzip:  17.14 kB | br:  14.28 kB
dist/client/assets/index-Dq-t2KRQ.js      403.13 kB │ gzip: 133.49 kB │ br: 115.59 kB │ map: 2,340.08 kB

Suggested solution

Ideally, we could do a preprocessing pass on the list of chunks to filter out any asset that ends in .gz, .br, or .zst for which there is a matching asset with the compression extension removed.

When calling getCompressedSize(asset), we could similarly check for matches for compressed asset extensions and grab the size directly. If no such compressed asset exists, we can run the gzip compress as before.

Lastly, the compressedSize would need to no longer just be a number but a Record<Encoding, number> since each file could have a combination of different compressed sizes and not just one.

Optional customization options:

compressionExtensions: {
  '.deflate': 'deflate',
  '.gz': 'gzip',
  '.br': 'br'
}

This option would allow you to specify a list of known file extensions and what compression format they map to. The values in this object are used for the table header (gzip: , etc). If the user provides a custom value for compressionExtensions it will override the default.

reportCompressedSize: ['br']

The reportCompressedSize option can be enhanced to take an array of compression formats to report. This would allow you to filter down the list so that instead of displaying both gzip and brotli sizes, you could just show brotli size.

dist/client/assets/index-Dq-t2KRQ.js      403.13 kB │ br: 115.59 kB │ map: 2,340.08 kB

The tricky thing is that as a user, I would expect setting reportCompressedSize: ['br'] then I should see an estimate of the brotli size even if I wasn't using static compression (in the same sense that gzip size is calculated today). This calculation is more expensive, so I'm not sure whether we would want to enable that (it seems to have been discouraged in #20306). As a result, I could see the argument that we should either just not allow this customization, or to document that 'br' will only report the size for statically compressed assets with the .br extension, and it will not be computed on demand.

Alternative

I can understand that maybe the specifics of which extensions are used, what algorithms are supported, etc, might fall outside of the scope of what Vite wants to maintain, but there isn't really any extensibility in the emitAsset api to be able to associate one asset as being associated with another.

In theory the same problem could exist if you generate .js and .js.map files as assets dynamically (instead of as chunks). In that scenario the .js.map asset could be emitted with a dependency on the .js asset and associated as a sourcemap. The build reporter would then essentially say "does this asset have an associated sourcemap?" and report the map size while hiding the asset from the main list.

A more general api such as this would still requires enhancements to the build reporter to be able to query for these asset associations, and plugins that emit these kinds of assets would need to be enhanced to emit the assets with the required associations.

As a result, I believe this alternative is worse than allowing the reporter to do this grouping based on well established file conventions.

Additional context

I'm willing to contribute this enhancement if it seems like something that would be accepted by the team and the above proposal seems like a decent approach. I wanted to make sure that was the case though before I began working on things.

Validations

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions