Skip to content

[Feature] report file size for ui extensions on build and dev#7205

Open
robin-drexler wants to merge 1 commit intomainfrom
rd/bundle-size-reporting
Open

[Feature] report file size for ui extensions on build and dev#7205
robin-drexler wants to merge 1 commit intomainfrom
rd/bundle-size-reporting

Conversation

@robin-drexler
Copy link
Copy Markdown
Member

@robin-drexler robin-drexler commented Apr 6, 2026

WHY are these changes introduced?

With 2025-10 version, we introduced strict 64kb limits for ui extensions. It's been difficult for developers to analyze their file sizes. We've already shipped a change that emits esbuild metafiles and allows developers to find out what's in their bundles.

The issue is that those sizes are being reported uncompressed. And while this is useful to sport large libraries etc, it doesn't give you the full picture and is confusing to some folks.

WHAT is this pull request doing?

This PR now shows extension file uncompressed and compressed sizes when running app build or app dev making it easier to spot when an extension is getting too big.

We are not (yet) adding any size limit warnings. That information is currently afaik only available in the backend when you try to upload an extension. We can look into this at a later point. Just adding the information itself imo is already pretty useful.

build

image

dev

image

rebuild
image

How to test your changes?

  • have an app with ui extension(s)
  • run pnpm shopify app build --path=/path/to/your/app inside the cli repo
  • The command should print the sizes for extensions
  • Ensure the file sizes printed are close to what's shown for
    • original
/bin/ls -l /path/to/your/app/extensions/some-extensions/dist/some-extension.js | awk '{printf "%.2f KB\n", $5/1024}'
  • compressed
python3 -c "import sys,zlib; print('%.2f KiB' % (len(zlib.compress(sys.stdin.buffer.read()))/1024))" < /path/to/your/app/extensions/some-extensions/dist/some-extension.js

Post-release steps

Measuring impact

How do we know this change was effective? Please choose one:

  • n/a - this doesn't need measurement, e.g. a linting rule or a bug-fix
  • Existing analytics will cater for this addition
  • PR includes analytics changes to measure impact

Checklist

  • I've considered possible cross-platform impacts (Mac, Linux, Windows)
  • I've considered possible documentation changes

Copy link
Copy Markdown
Member Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@robin-drexler robin-drexler force-pushed the rd/bundle-size-reporting branch 9 times, most recently from abf63b1 to b75d5eb Compare April 7, 2026 13:21
@robin-drexler robin-drexler changed the title report bundle size for extensions report file size for extensions on build and dev Apr 7, 2026
@robin-drexler robin-drexler force-pushed the rd/bundle-size-reporting branch 2 times, most recently from 47bd3d6 to 675a667 Compare April 7, 2026 13:29
@robin-drexler robin-drexler changed the title report file size for extensions on build and dev [Feature] report file size for extensions on build and dev Apr 7, 2026
@robin-drexler robin-drexler force-pushed the rd/bundle-size-reporting branch from 675a667 to 25e7d56 Compare April 7, 2026 13:40
@robin-drexler robin-drexler marked this pull request as ready for review April 7, 2026 13:55
@robin-drexler robin-drexler requested review from a team as code owners April 7, 2026 13:55
Copilot AI review requested due to automatic review settings April 7, 2026 13:55
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds reporting of UI extension bundle sizes (original + compressed) to build and dev workflows to help developers understand proximity to Shopify’s 64kb compressed limit.

Changes:

  • Append original and deflated-compressed bundle size information to UI extension build output (app build).
  • Append bundle size information after successful rebuilds during app dev for esbuild-managed extensions.
  • Introduce bundle-size utility + unit tests, and add a changeset for @shopify/app.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/app/src/cli/services/dev/app-events/app-event-watcher.ts Adds bundle size suffix to “Build successful” messages on rebuild during dev.
packages/app/src/cli/services/build/extension.ts Adds bundle size suffix to UI extension “successfully built” output.
packages/app/src/cli/services/build/bundle-size.ts New utility to compute raw + deflate-compressed sizes and format as a suffix.
packages/app/src/cli/services/build/bundle-size.test.ts Adds unit tests for raw/compressed sizing and formatting behavior.
.changeset/tricky-results-roll.md Declares a minor release for @shopify/app to ship the feature.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +13 to +14
const [rawBytes, content] = await Promise.all([fileSize(filePath), readFile(filePath)])
const compressed = await deflateAsync(Buffer.from(content))
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getBundleSize calls readFile(filePath) with the default {encoding: 'utf8'} and then wraps it in Buffer.from(content). For accurate byte-level compression (and to keep this utility safe for non-text/binary bundles), read the file as a Buffer explicitly (e.g., pass an options object that yields a Buffer) and deflate that buffer directly.

Suggested change
const [rawBytes, content] = await Promise.all([fileSize(filePath), readFile(filePath)])
const compressed = await deflateAsync(Buffer.from(content))
const [rawBytes, content] = await Promise.all([fileSize(filePath), readFile(filePath, {encoding: null})])
const compressed = await deflateAsync(content)

Copilot uses AI. Check for mistakes.
@robin-drexler robin-drexler force-pushed the rd/bundle-size-reporting branch 3 times, most recently from f1e1e0d to d8e7d01 Compare April 7, 2026 16:40
@robin-drexler robin-drexler force-pushed the rd/bundle-size-reporting branch from d8e7d01 to dac58c5 Compare April 7, 2026 18:39
@robin-drexler robin-drexler changed the title [Feature] report file size for extensions on build and dev [Feature] report file size for ui extensions on build and dev Apr 7, 2026
* Uses the same compression algorithm as the Shopify backend (Zlib::Deflate.deflate).
*/
export async function getBundleSize(filePath: string) {
const [rawBytes, content] = await Promise.all([fileSize(filePath), readFile(filePath)])
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this need to wrap in a try/catch in case we exhaust the buffer? i'm unfamiliar with how we run the build and compression here

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the only actual usage of this already wraps it in a try / catch. should be good for now? https://github.com/Shopify/cli/pull/7205/changes/BASE..dac58c54bb75c3790b3fcdd8d7f63424aa4d135e

Copy link
Copy Markdown
Contributor

@ryancbahan ryancbahan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems reasonable to me. left a q about the read from buffer on the file, but i'm low context there

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants