diff --git a/.github/actions/custom-surge-preview/action.yml b/.github/actions/custom-surge-preview/action.yml index 488846faff..a5e4f422dd 100644 --- a/.github/actions/custom-surge-preview/action.yml +++ b/.github/actions/custom-surge-preview/action.yml @@ -33,6 +33,13 @@ runs: if: github.event.action != 'closed' shell: bash run: ${{ inputs.build-preview-command }} + - name: List the size of the chunks in the demo + if: github.event.action != 'closed' && contains(inputs.build-preview-command, 'demo') + shell: bash + run: | + scripts/list-demo-lib-chunks.sh + echo "## Demo lib chunk sizes" >> "$GITHUB_STEP_SUMMARY" + scripts/list-demo-lib-chunks.sh --md-simple >> "$GITHUB_STEP_SUMMARY" - name: Manage surge preview if: steps.surge-preview-tools.outputs.can-run-surge-command == 'true' uses: afc163/surge-preview@v1 diff --git a/.github/workflows/fill-gh-draft-release.yml b/.github/workflows/fill-gh-draft-release.yml index 94fa004d70..0b35105426 100644 --- a/.github/workflows/fill-gh-draft-release.yml +++ b/.github/workflows/fill-gh-draft-release.yml @@ -14,6 +14,6 @@ jobs: contents: write steps: # Drafts your next Release notes as Pull Requests are merged into "master" - - uses: release-drafter/release-drafter@v7.2.0 + - uses: release-drafter/release-drafter@v7.1.1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/generate-demo-preview.yml b/.github/workflows/generate-demo-preview.yml index e68ac0f510..dff6628ef2 100644 --- a/.github/workflows/generate-demo-preview.yml +++ b/.github/workflows/generate-demo-preview.yml @@ -12,6 +12,7 @@ on: - '.github/workflows/generate-demo-preview.yml' - 'config/**/*' - 'dev/**/*' + - 'scripts/list-demo-lib-chunks.sh' - 'scripts/prepare-demo-for-publish.mjs' - 'src/**/*' - '.nvmrc' diff --git a/.github/workflows/test-npm-package.yml b/.github/workflows/test-npm-package.yml index 8836820b2f..b93f85930b 100644 --- a/.github/workflows/test-npm-package.yml +++ b/.github/workflows/test-npm-package.yml @@ -51,6 +51,11 @@ jobs: uses: ./.github/actions/build-setup - name: Build npm package run: npm pack + - name: List the size of the npm package bundles + run: | + scripts/list-npm-bundle-sizes.sh + echo "## NPM package bundle sizes" >> "$GITHUB_STEP_SUMMARY" + scripts/list-npm-bundle-sizes.sh --md-simple >> "$GITHUB_STEP_SUMMARY" - name: Upload npm package uses: actions/upload-artifact@v7 with: diff --git a/package-lock.json b/package-lock.json index c6bb4c1494..16e6ff3a7a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5392,14 +5392,14 @@ } }, "node_modules/axios": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.15.0.tgz", - "integrity": "sha512-wWyJDlAatxk30ZJer+GeCWS209sA42X+N5jU2jy6oHTp7ufw8uzUTVFBX9+wTfAlhiJXGS0Bq7X6efruWjuK9Q==", + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz", + "integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==", "dev": true, "dependencies": { - "follow-redirects": "^1.15.11", - "form-data": "^4.0.5", - "proxy-from-env": "^2.1.0" + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" } }, "node_modules/babel-jest": { @@ -8103,9 +8103,9 @@ } }, "node_modules/form-data": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", - "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", "dev": true, "dependencies": { "asynckit": "^0.4.0", @@ -14896,13 +14896,10 @@ } }, "node_modules/proxy-from-env": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", - "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", - "dev": true, - "engines": { - "node": ">=10" - } + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true }, "node_modules/punycode": { "version": "2.3.1", @@ -21420,14 +21417,14 @@ } }, "axios": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.15.0.tgz", - "integrity": "sha512-wWyJDlAatxk30ZJer+GeCWS209sA42X+N5jU2jy6oHTp7ufw8uzUTVFBX9+wTfAlhiJXGS0Bq7X6efruWjuK9Q==", + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz", + "integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==", "dev": true, "requires": { - "follow-redirects": "^1.15.11", - "form-data": "^4.0.5", - "proxy-from-env": "^2.1.0" + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" } }, "babel-jest": { @@ -23245,9 +23242,9 @@ } }, "form-data": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", - "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", "dev": true, "requires": { "asynckit": "^0.4.0", @@ -27836,9 +27833,9 @@ } }, "proxy-from-env": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", - "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "dev": true }, "punycode": { diff --git a/scripts/list-demo-lib-chunks.sh b/scripts/list-demo-lib-chunks.sh new file mode 100755 index 0000000000..dff5b32eaa --- /dev/null +++ b/scripts/list-demo-lib-chunks.sh @@ -0,0 +1,67 @@ +#!/usr/bin/env bash +# List library chunks from the demo build output with their sizes. +# Outputs a plain list and a markdown table for tracking size evolution in PRs, issues, or release notes. +# Usage: list-lib-chunks.sh [--md-simple] +# --md-simple Output a simple markdown table (Dependency | Size) +set -euo pipefail + +MD_SIMPLE=false +if [[ "${1:-}" = "--md-simple" ]]; then + MD_SIMPLE=true +fi + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +DEMO_ASSETS_DIR="${SCRIPT_DIR}/../build/demo/dev/public/assets" + +if [[ ! -d "$DEMO_ASSETS_DIR" ]]; then + echo "Error: demo assets directory not found. Run 'npm run demo:build." >&2 + exit 1 +fi + +# Collect lib chunks with their size in KB +declare -a names=() +declare -a sizes=() + +for file in "$DEMO_ASSETS_DIR"/lib-*.js; do + [[ -f "$file" ]] || continue + filename=$(basename "$file") + # Extract dependency name: lib-.js -> + dep_name=$(echo "$filename" | sed 's/^lib-//;s/\.js$//') + size_kb=$(LC_NUMERIC=C awk "BEGIN {printf \"%.2f\", $(stat --format=%s "$file") / 1000}") + names+=("$dep_name") + sizes+=("$size_kb") +done + +if [[ ${#names[@]} -eq 0 ]]; then + echo "No lib-*.js chunks found in dist/assets." >&2 + exit 1 +fi + +# Compute total +total=$(LC_NUMERIC=C awk "BEGIN {t=0; $(for s in "${sizes[@]}"; do printf "t+=%s;" "$s"; done) printf \"%.2f\", t}") + +if [[ "$MD_SIMPLE" = true ]]; then + # Simple markdown table + echo "| Dependency | Size |" + echo "|---|---|" + for i in "${!names[@]}"; do + echo "| ${names[$i]} | ${sizes[$i]} kB |" + done + echo "| **TOTAL** | **${total} kB** |" +else + # Plain list + echo "=== Lib chunks ===" + for i in "${!names[@]}"; do + printf "%-25s %s kB\n" "${names[$i]}" "${sizes[$i]}" + done + printf "%-25s %s kB\n" "TOTAL" "$total" + echo "" + # Markdown table for tracking size evolution + echo "=== Markdown table ===" + echo "| Dependency | Before | Current |" + echo "|---|---|---|" + for i in "${!names[@]}"; do + echo "| ${names[$i]} | | ${sizes[$i]} kB |" + done + echo "| **TOTAL** | | **${total} kB** |" +fi diff --git a/scripts/list-npm-bundle-sizes.sh b/scripts/list-npm-bundle-sizes.sh new file mode 100755 index 0000000000..a3e2a455ce --- /dev/null +++ b/scripts/list-npm-bundle-sizes.sh @@ -0,0 +1,65 @@ +#!/usr/bin/env bash +# List npm package bundles from dist/ with their sizes (bytes and kB). +# Outputs a plain list and a markdown table for tracking size evolution in PRs, issues, or release notes. +# Usage: list-npm-bundle-sizes.sh [--md-simple] +# --md-simple Output a simple markdown table (Bundle | Size) +set -euo pipefail + +MD_SIMPLE=false +if [[ "${1:-}" = "--md-simple" ]]; then + MD_SIMPLE=true +fi + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +DIST_DIR="${SCRIPT_DIR}/../dist" + +if [[ ! -d "$DIST_DIR" ]]; then + echo "Error: dist directory not found. Run 'npm run build-bundles' first." >&2 + exit 1 +fi + +BUNDLES=( + "bpmn-visualization.min.js" + "bpmn-visualization.js" + "bpmn-visualization.esm.js" +) + +declare -a names=() +declare -a bytes=() +declare -a kb=() + +for bundle in "${BUNDLES[@]}"; do + file="$DIST_DIR/$bundle" + if [[ ! -f "$file" ]]; then + echo "Error: bundle not found: $file. Run 'npm run build-bundles' first." >&2 + exit 1 + fi + size_bytes=$(stat --format=%s "$file") + size_kb=$(LC_NUMERIC=C awk "BEGIN {printf \"%.1f\", $size_bytes / 1024}") + # Format bytes with space as thousands separator (e.g. 998629 -> "998 629") + size_bytes_fmt=$(echo "$size_bytes" | sed ':a;s/\B[0-9]\{3\}\>/ &/;ta') + names+=("$bundle") + bytes+=("$size_bytes_fmt") + kb+=("$size_kb") +done + +if [[ "$MD_SIMPLE" = true ]]; then + echo "| Bundle | Size |" + echo "|---|---|" + for i in "${!names[@]}"; do + echo "| ${names[$i]} | ${kb[$i]} kB |" + done +else + echo "=== NPM package bundles ===" + for i in "${!names[@]}"; do + printf "%-30s %12s bytes %8s kB\n" "${names[$i]}" "${bytes[$i]}" "${kb[$i]}" + done + echo "" + echo "=== Markdown table ===" + echo "| bundle | before | now |" + echo "|---|---|---|" + for i in "${!names[@]}"; do + echo "| ${names[$i]} | | ${bytes[$i]} bytes |" + echo "| | | ${kb[$i]} kB |" + done +fi diff --git a/vite.config.js b/vite.config.js index 54f03f77b6..0c0b228851 100644 --- a/vite.config.js +++ b/vite.config.js @@ -43,12 +43,17 @@ export default defineConfig(({ mode }) => { entryFileNames: `dev/public/assets/[name].js`, chunkFileNames: `dev/public/assets/[name].js`, assetFileNames: `dev/public/assets/[name].[ext]`, - manualChunks: { - // put mxgraph code in a dedicated file. As it is eol, it doesn't change from release to release, so it reduces the changes when uploading the demo to the examples repository - mxgraph: ['mxgraph'], + // Put dependencies in dedicated files to track the impact of their updates on the demo. + manualChunks(id) { + if (id.includes('node_modules/es-toolkit')) return 'lib-es-toolkit'; + if (id.includes('node_modules/fast-xml-parser')) return 'lib-fast-xml-parser'; + if (id.includes('node_modules/mxgraph')) return 'lib-mxgraph'; + // bpmn-visualization code built from src/ + if (!id.includes('node_modules') && id.includes('/src/')) return 'lib-bpmn-visualization'; }, }, }, + // minify: false, // uncomment to see the code in clear chunkSizeWarningLimit: 838, // mxgraph }, preview: {