mirror of
https://github.com/apache/superset.git
synced 2026-08-05 21:42:48 +00:00
ci(frontend): track bundle size over time with benchmark-action
Superset's frontend bundle size is a recurring complaint, but until now
there's been no ongoing visibility into it -- only periodic manual cleanup
efforts. This adds a `bundle-size` job to superset-frontend.yml that builds
the real production bundle (npm run build), reduces its per-entrypoint
sizes to a few headline numbers, and tracks them over time via
benchmark-action/github-action-benchmark, posting a PR comment when a
change regresses past 110% of the last recorded baseline.
Reuses the already-built CI Docker image (same image sharded-jest-tests /
lint-frontend / etc. already download), so the only new cost is the
production webpack build itself -- and that's cheap after the first run:
webpack's persistent filesystem cache (already configured in
webpack.config.js) makes warm rebuilds ~20s locally vs several minutes
cold, confirmed by hand against this repo's real build.
webpack.config.js gains a BUNDLE_SIZE_STATS env-gated stats override
(mirrors the existing BUNDLE_ANALYZER pattern). The default `stats:
'minimal'` omits per-asset sizes entirely; `--stats=normal` includes them
but also serializes the full ~15k-module dependency graph, producing a
560+MB stats.json for this app -- large enough to exceed Node's max
string length on a plain fs.readFileSync. The env-gated override requests
just `{ assets: true, entrypoints: true }`, verified end-to-end against a
minimal synthetic webpack project (same webpack/webpack-cli versions) and
against real stats pulled from this repo's actual production build.
History storage deliberately avoids the gh-pages branch (benchmark-action's
usual default) since that branch is the live Helm chart index published by
superset-helm-release.yml, not free real estate. Instead uses
external-data-json-path with actions/cache: restored on every run (PR or
push) so PRs get a same-baseline comparison and regression comment, but
only saved back to the cache on push to master, so an unmerged PR's numbers
never become the shared baseline. No gh-pages branch is touched in any
code path, and no PAT/GitHub App is needed -- comment-on-alert only needs
the default per-job GITHUB_TOKEN.
This commit is contained in:
72
.github/workflows/superset-frontend.yml
vendored
72
.github/workflows/superset-frontend.yml
vendored
@@ -195,3 +195,75 @@ jobs:
|
||||
run: |
|
||||
docker run --rm $TAG bash -c \
|
||||
"npm run build-storybook && npx playwright install-deps && npx playwright install chromium && npm run test-storybook:ci"
|
||||
|
||||
bundle-size:
|
||||
needs: frontend-build
|
||||
if: needs.frontend-build.outputs.should-run == 'true'
|
||||
runs-on: ubuntu-26.04
|
||||
timeout-minutes: 15
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Download Docker Image Artifact
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
|
||||
with:
|
||||
name: docker-image
|
||||
|
||||
- name: Load Docker Image
|
||||
run: |
|
||||
zstd -d < docker-image.tar.zst | docker load
|
||||
|
||||
# Only ever pull the last recorded data point off the cache, keyed by
|
||||
# run ID -- `restore-keys` prefix-matches the most recently created
|
||||
# entry. Absent on the very first run ever; benchmark-action starts a
|
||||
# fresh history in that case.
|
||||
- name: Restore bundle size history
|
||||
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||||
with:
|
||||
path: bundle-size-history.json
|
||||
key: bundle-size-history-${{ github.run_id }}
|
||||
restore-keys: |
|
||||
bundle-size-history-
|
||||
|
||||
- name: Build production bundle with stats
|
||||
run: |
|
||||
mkdir -p ${{ github.workspace }}/superset-frontend/bundle-stats
|
||||
docker run \
|
||||
-v ${{ github.workspace }}/superset-frontend/bundle-stats:/app/superset-frontend/bundle-stats \
|
||||
--rm $TAG \
|
||||
bash -c \
|
||||
"npm i && BUNDLE_SIZE_STATS=true npm run build -- --json=bundle-stats/stats.json"
|
||||
|
||||
- name: Summarize bundle size
|
||||
run: |
|
||||
node superset-frontend/scripts/bundle-size-summary.js \
|
||||
superset-frontend/bundle-stats/stats.json > bundle-size-summary.json
|
||||
rm -rf superset-frontend/bundle-stats
|
||||
|
||||
- name: Track bundle size
|
||||
uses: benchmark-action/github-action-benchmark@52576c92bccf6ac60c8223ec7eb2565637cae9ba # v1.22.1
|
||||
with:
|
||||
tool: customSmallerIsBetter
|
||||
output-file-path: bundle-size-summary.json
|
||||
external-data-json-path: bundle-size-history.json
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
comment-on-alert: true
|
||||
alert-threshold: "110%"
|
||||
fail-on-alert: false
|
||||
summary-always: true
|
||||
|
||||
# Only the trunk's own bundle size becomes the baseline everyone else
|
||||
# is compared against -- an unmerged PR's numbers (including ones that
|
||||
# regress on purpose to test something) never get persisted.
|
||||
- name: Save bundle size history
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
|
||||
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||||
with:
|
||||
path: bundle-size-history.json
|
||||
key: bundle-size-history-${{ github.run_id }}
|
||||
|
||||
Reference in New Issue
Block a user