diff --git a/.github/workflows/pull-request-commit.yml b/.github/workflows/pull-request-commit.yml index 85ebae4d..d3aade3f 100644 --- a/.github/workflows/pull-request-commit.yml +++ b/.github/workflows/pull-request-commit.yml @@ -1,4 +1,4 @@ -# Credit https://github.com/expo/expo +# Credit for fingerprint action https://github.com/expo/expo # https://github.com/expo/expo/blob/main/.github/workflows/pr-labeler.yml --- name: PR labeler @@ -14,9 +14,123 @@ concurrency: cancel-in-progress: true jobs: + webpack-analyzer: + runs-on: ubuntu-22.04 + if: ${{ github.event_name == 'pull_request' }} + permissions: + pull-requests: write + steps: + - name: ⬇️ Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: 🔧 Setup Node + uses: actions/setup-node@v4 + with: + node-version-file: .nvmrc + cache: yarn + + - name: ⚙️ Install Dependencies + run: yarn install + + - name: Ensure tracking relevant branches and checkout base + run: | + git checkout ${{ github.head_ref }} + git checkout ${{ github.base_ref }} + + - name: Get the base commit + id: base-commit + run: echo base-commit=$(git log -n 1 ${{ github.base_ref }} --pretty=format:'%H') >> "$GITHUB_OUTPUT" + + - name: Merge PR commit + run: | + # Have to set a git config for the merge to work + git config --global user.email "github-actions[bot]@users.noreply.github.com" + git config --global user.name "github-actions[bot]" + git merge --no-edit ${{ github.head_ref }} + + - name: 🔦 Generate stats file for PR + run: | + yarn generate-webpack-stats-file + mv stats.json ../stats-new.json + + - name: ⬇️ Get base stats from cache + id: get-base-stats + uses: actions/cache@v4 + with: + path: stats-base.json + key: stats-base-${{ steps.base-commit.outputs.base-commit }} + + - name: Restore to base commit + if: ${{ !steps.get-base-stats.outputs.cache-hit }} + run: | + git reset HEAD~ + git restore . + + - name: 🔦 Generate stats file from base commit + if: ${{ !steps.get-base-stats.outputs.cache-hit }} + run: | + yarn generate-webpack-stats-file + mv stats.json stats-base.json + + - name: % Get diff + id: get-diff + uses: NejcZdovc/bundle-size-diff@v1 + with: + base_path: 'stats-base.json' + pr_path: '../stats-new.json' + excluded_assets: '(.+).js.map|(.+).json|(.+).png' + + - name: 🔍 Find old comment if it exists + uses: peter-evans/find-comment@v2 + if: ${{ github.event_name == 'pull_request' }} + id: old_comment + with: + issue-number: ${{ github.event.pull_request.number }} + comment-author: 'github-actions[bot]' + body-includes: + + - name: 💬 Add comment with diff + uses: actions/github-script@v6 + if: ${{ steps.old_comment.outputs.comment-id == '' }} + with: + script: | + const body = ` + | Old size | New size | Diff | + |----------|----------|-----------------------| + | ${{ steps.get-diff.outputs.base_file_string }} | ${{ steps.get-diff.outputs.pr_file_string }} | ${{ steps.get-diff.outputs.diff_file_string }} (${{ steps.get-diff.outputs.percent }}% | + `; + + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: body, + }); + + - name: 💬 Update comment with fingerprint + if: ${{ steps.old_comment.outputs.comment-id != '' }} + uses: actions/github-script@v6 + with: + script: | + const body = ` + | Old size | New size | Diff | + |----------|----------|-----------------------| + | ${{ steps.get-diff.outputs.base_file_string }} | ${{ steps.get-diff.outputs.pr_file_string }} | ${{ steps.get-diff.outputs.diff_file_string }} (${{ steps.get-diff.outputs.percent }}%) | + `; + + github.rest.issues.updateComment({ + issue_number: context.issue.number, + comment_id: '${{ steps.old_comment.outputs.comment-id }}', + owner: context.repo.owner, + repo: context.repo.repo, + body: body, + }); + test-suite-fingerprint: runs-on: ubuntu-22.04 - if: ${{ github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'push' }} + if: ${{ github.event_name == 'pull_request' || github.event_name == 'push' }} # REQUIRED: limit concurrency when pushing main(default) branch to prevent conflict for this action to update its fingerprint database concurrency: fingerprint-${{ github.event_name != 'pull_request' && 'main' || github.run_id }} permissions: @@ -45,9 +159,7 @@ jobs: - name: Get the base commit id: base-commit - run: | - # Since we limit this pr-labeler workflow only triggered from limited paths, we should use custom base commit - echo base-commit=$(git log -n 1 main --pretty=format:'%H') >> "$GITHUB_OUTPUT" + run: echo base-commit=$(git log -n 1 main --pretty=format:'%H') >> "$GITHUB_OUTPUT" - name: 📷 Check fingerprint id: fingerprint diff --git a/.gitignore b/.gitignore index 77dbd00f..b546152c 100644 --- a/.gitignore +++ b/.gitignore @@ -77,6 +77,7 @@ dist/ *.mobileprovision *.orig.* web-build/ +stats.json # Temporary files created by Metro to check the health of the file watcher .metro-health-check* diff --git a/package.json b/package.json index efd48030..47596926 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,10 @@ "intl:compile": "lingui compile", "nuke": "rm -rf ./node_modules && rm -rf ./ios && rm -rf ./android", "update-extensions": "bash scripts/updateExtensions.sh", - "export": "npx expo export" + "export": "npx expo export", + "make-deploy-bundle": "bash scripts/bundleUpdate.sh", + "generate-webpack-stats-file": "EXPO_PUBLIC_GENERATE_STATS=1 yarn build-web", + "open-analyzer": "EXPO_PUBLIC_OPEN_ANALYZER=1 yarn build-web" }, "dependencies": { "@atproto/api": "^0.12.2", @@ -257,6 +260,7 @@ "typescript": "^5.3.3", "url-loader": "^4.1.1", "webpack": "^5.75.0", + "webpack-bundle-analyzer": "^4.10.1", "webpack-cli": "^5.0.1", "webpack-dev-server": "^4.11.1" }, diff --git a/webpack.config.js b/webpack.config.js index 7515db8e..f57ba2e3 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,6 +1,10 @@ const createExpoWebpackConfigAsync = require('@expo/webpack-config') const {withAlias} = require('@expo/webpack-config/addons') const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin') +const {BundleAnalyzerPlugin} = require('webpack-bundle-analyzer') + +const GENERATE_STATS = process.env.EXPO_PUBLIC_GENERATE_STATS === '1' +const OPEN_ANALYZER = process.env.EXPO_PUBLIC_OPEN_ANALYZER === '1' const reactNativeWebWebviewConfiguration = { test: /postMock.html$/, @@ -26,5 +30,17 @@ module.exports = async function (env, argv) { if (env.mode === 'development') { config.plugins.push(new ReactRefreshWebpackPlugin()) } + + if (GENERATE_STATS || OPEN_ANALYZER) { + config.plugins.push( + new BundleAnalyzerPlugin({ + openAnalyzer: OPEN_ANALYZER, + generateStatsFile: true, + statsFilename: '../stats.json', + analyzerMode: OPEN_ANALYZER ? 'server' : 'json', + defaultSizes: 'parsed', + }), + ) + } return config } diff --git a/yarn.lock b/yarn.lock index a2941d5b..5f57bfd4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2821,7 +2821,7 @@ "@gorhom/portal" "1.0.14" invariant "^2.2.4" -"@discoveryjs/json-ext@^0.5.0": +"@discoveryjs/json-ext@0.5.7", "@discoveryjs/json-ext@^0.5.0": version "0.5.7" resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== @@ -4456,6 +4456,11 @@ schema-utils "^3.0.0" source-map "^0.7.3" +"@polka/url@^1.0.0-next.24": + version "1.0.0-next.25" + resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.25.tgz#f077fdc0b5d0078d30893396ff4827a13f99e817" + integrity sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ== + "@popperjs/core@^2.9.0": version "2.11.8" resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f" @@ -8297,6 +8302,11 @@ acorn-walk@^7.1.1: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== +acorn-walk@^8.0.0: + version "8.3.2" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa" + integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A== + acorn-walk@^8.0.2, acorn-walk@^8.1.1: version "8.2.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" @@ -8307,6 +8317,11 @@ acorn@^7.1.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== +acorn@^8.0.4: + version "8.11.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" + integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== + acorn@^8.1.0, acorn@^8.2.4, acorn@^8.4.1, acorn@^8.7.1, acorn@^8.8.1, acorn@^8.8.2, acorn@^8.9.0: version "8.10.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" @@ -10483,6 +10498,11 @@ dayjs@^1.8.15: resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.9.tgz#9ca491933fadd0a60a2c19f6c237c03517d71d1a" integrity sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA== +debounce@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.1.tgz#38881d8f4166a5c5848020c11827b834bcb3e0a5" + integrity sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug== + debug@2.6.9, debug@^2.2.0, debug@^2.6.0, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -13143,7 +13163,7 @@ html-entities@^2.1.0, html-entities@^2.3.2: resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.4.0.tgz#edd0cee70402584c8c76cc2c0556db09d1f45061" integrity sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ== -html-escaper@^2.0.0: +html-escaper@^2.0.0, html-escaper@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== @@ -13782,6 +13802,11 @@ is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" +is-plain-object@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" + integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== + is-potential-custom-element-name@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" @@ -16329,6 +16354,11 @@ mrmime@^1.0.0: resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-1.0.1.tgz#5f90c825fad4bdd41dc914eff5d1a8cfdaf24f27" integrity sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw== +mrmime@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-2.0.0.tgz#151082a6e06e59a9a39b46b3e14d5cfe92b3abb4" + integrity sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw== + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -16851,6 +16881,11 @@ open@^8.0.4, open@^8.0.9, open@^8.3.0, open@^8.4.0: is-docker "^2.1.1" is-wsl "^2.2.0" +opener@^1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" + integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== + optionator@^0.9.3: version "0.9.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" @@ -19864,6 +19899,15 @@ simple-swizzle@^0.2.2: dependencies: is-arrayish "^0.3.1" +sirv@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/sirv/-/sirv-2.0.4.tgz#5dd9a725c578e34e449f332703eb2a74e46a29b0" + integrity sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ== + dependencies: + "@polka/url" "^1.0.0-next.24" + mrmime "^2.0.0" + totalist "^3.0.0" + sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" @@ -20842,6 +20886,11 @@ token-types@^4.1.1: "@tokenizer/token" "^0.3.0" ieee754 "^1.2.1" +totalist@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/totalist/-/totalist-3.0.1.tgz#ba3a3d600c915b1a97872348f79c127475f6acf8" + integrity sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ== + tough-cookie@^4.0.0, tough-cookie@^4.1.2: version "4.1.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf" @@ -21538,6 +21587,25 @@ webidl-conversions@^7.0.0: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== +webpack-bundle-analyzer@^4.10.1: + version "4.10.1" + resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.10.1.tgz#84b7473b630a7b8c21c741f81d8fe4593208b454" + integrity sha512-s3P7pgexgT/HTUSYgxJyn28A+99mmLq4HsJepMPzu0R8ImJc52QNqaFYW1Z2z2uIb1/J3eYgaAWVpaC+v/1aAQ== + dependencies: + "@discoveryjs/json-ext" "0.5.7" + acorn "^8.0.4" + acorn-walk "^8.0.0" + commander "^7.2.0" + debounce "^1.2.1" + escape-string-regexp "^4.0.0" + gzip-size "^6.0.0" + html-escaper "^2.0.2" + is-plain-object "^5.0.0" + opener "^1.5.2" + picocolors "^1.0.0" + sirv "^2.0.3" + ws "^7.3.1" + webpack-cli@^5.0.1: version "5.1.4" resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-5.1.4.tgz#c8e046ba7eaae4911d7e71e2b25b776fcc35759b" @@ -22093,7 +22161,7 @@ ws@^6.2.2: dependencies: async-limiter "~1.0.0" -ws@^7, ws@^7.0.0, ws@^7.4.6, ws@^7.5.1: +ws@^7, ws@^7.0.0, ws@^7.3.1, ws@^7.4.6, ws@^7.5.1: version "7.5.9" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==