summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Nate Moore <natemoo-re@users.noreply.github.com> 2022-05-26 11:49:29 -0500
committerGravatar GitHub <noreply@github.com> 2022-05-26 11:49:29 -0500
commit2f4ee560dd29253dd086a1600fd1bafd13405006 (patch)
treea511372aec29755f3a5829eb3c01cdc161691de5
parentd92d28317f221f4cccdd5e83365675a256944fd3 (diff)
downloadastro-2f4ee560dd29253dd086a1600fd1bafd13405006.tar.gz
astro-2f4ee560dd29253dd086a1600fd1bafd13405006.tar.zst
astro-2f4ee560dd29253dd086a1600fd1bafd13405006.zip
Add bundle-size check action (#3454)
* feat: add scripts action, bundle-size checker * chore: trigger action * fix: update prefix logic
Diffstat (limited to '')
-rw-r--r--.github/scripts/bundle-size.mjs81
-rw-r--r--.github/workflows/scripts.yml48
-rw-r--r--packages/astro/src/runtime/client/idle.ts2
-rw-r--r--packages/astro/src/runtime/client/load.ts2
-rw-r--r--packages/astro/src/runtime/client/media.ts2
-rw-r--r--packages/astro/src/runtime/client/only.ts4
-rw-r--r--packages/astro/src/runtime/client/visible.ts2
7 files changed, 135 insertions, 6 deletions
diff --git a/.github/scripts/bundle-size.mjs b/.github/scripts/bundle-size.mjs
new file mode 100644
index 000000000..4166735a9
--- /dev/null
+++ b/.github/scripts/bundle-size.mjs
@@ -0,0 +1,81 @@
+import { build } from 'esbuild';
+
+const CLIENT_RUNTIME_PATH = 'packages/astro/src/runtime/client/';
+
+function formatBytes(bytes, decimals = 2) {
+ if (bytes === 0) return '0 B';
+
+ const k = 1024;
+ const dm = decimals < 0 ? 0 : decimals;
+ const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
+
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
+
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
+}
+
+export default async function checkBundleSize({ github, context }) {
+ const PR_NUM = context.payload.pull_request.number;
+ const SHA = context.payload.pull_request.head.sha;
+
+ const { data: files } = await github.rest.pulls.listFiles({
+ ...context.repo,
+ pull_number: PR_NUM,
+ });
+ const clientRuntimeFiles = files.filter(({ filename }) => filename.startsWith(CLIENT_RUNTIME_PATH));
+ if (clientRuntimeFiles.length === 0) return;
+
+ const table = [
+ '| File | Old Size | New Size | Change |',
+ '| ---- | -------- | -------- | ------ |',
+ ];
+ const output = await bundle(clientRuntimeFiles);
+
+ for (let [filename, { oldSize, newSize, sourceFile }] of Object.entries(output)) {
+ filename = filename !== 'hmr' ? `client:${filename}` : filename;
+ const prefix = (newSize - oldSize) === 0 ? '' : (newSize - oldSize) > 0 ? '+ ' : '- ';
+ const change = `${prefix}${formatBytes(newSize - oldSize)}`;
+ table.push(`| [\`${filename}\`](https://github.com/${context.repo.owner}/${context.repo.repo}/tree/${context.payload.pull_request.head.ref}/${sourceFile}) | ${formatBytes(oldSize)} | ${formatBytes(newSize)} | ${change} |`);
+ }
+
+ const { data: comments } = await github.rest.issues.listComments({
+ ...context.repo,
+ issue_number: PR_NUM
+ })
+ const comment = comments.find(comment => comment.user.login === 'github-actions[bot]' && comment.body.includes('Bundle Size Check'));
+ const method = comment ? 'updateComment' : 'createComment';
+ const payload = comment ? { comment_id: comment.id } : { issue_number: PR_NUM };
+ await github.rest.issues[method]({
+ ...context.repo,
+ ...payload,
+ body: `### ⚖️ Bundle Size Check
+
+Latest commit: ${SHA}
+
+${table.join('\n')}`,
+ });
+}
+
+async function bundle(files) {
+ const { metafile } = await build({
+ entryPoints: [...files.map(({ filename }) => filename), ...files.map(({ filename }) => `main/${filename}`)],
+ bundle: true,
+ minify: true,
+ sourcemap: false,
+ target: ['es2018'],
+ outdir: 'out',
+ metafile: true,
+ })
+
+ return Object.entries(metafile.outputs).reduce((acc, [filename, info]) => {
+ filename = filename.slice('out/'.length);
+ if (filename.startsWith('main/')) {
+ filename = filename.slice('main/'.length).replace(CLIENT_RUNTIME_PATH, '').replace('.js', '');
+ const oldSize = info.bytes;
+ return Object.assign(acc, { [filename]: Object.assign(acc[filename] ?? {}, { oldSize }) });
+ }
+ filename = filename.replace(CLIENT_RUNTIME_PATH, '').replace('.js', '');
+ const newSize = info.bytes;
+ return Object.assign(acc, { [filename]: Object.assign(acc[filename] ?? {}, { newSize, sourceFile: Object.keys(info.inputs).find(src => src.endsWith('.ts')) }) });
+ }, {});
+}
diff --git a/.github/workflows/scripts.yml b/.github/workflows/scripts.yml
new file mode 100644
index 000000000..40a29ee61
--- /dev/null
+++ b/.github/workflows/scripts.yml
@@ -0,0 +1,48 @@
+name: Scripts
+
+on:
+ pull_request:
+ branches:
+ - 'main'
+
+# Automatically cancel in-progress actions on the same branch
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event_name == 'pull_request_target' && github.head_ref || github.ref }}
+ cancel-in-progress: true
+
+defaults:
+ run:
+ shell: bash
+
+jobs:
+ bundle:
+ name: Bundle Size
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout Repo
+ uses: actions/checkout@v2
+
+ - name: Checkout Main into tmp
+ uses: actions/checkout@v2
+ with:
+ ref: main
+ path: main
+
+ - name: Setup PNPM
+ uses: pnpm/action-setup@v2.2.1
+
+ - name: Setup Node
+ uses: actions/setup-node@v3
+ with:
+ node-version: 16
+ cache: 'pnpm'
+
+ - name: Install dependencies
+ run: pnpm install
+
+ - name: Check Bundle Size
+ uses: actions/github-script@v6
+ with:
+ script: |
+ const { default: script } = await import('${{ github.workspace }}/.github/scripts/bundle-size.mjs')
+ await script({ github, context })
diff --git a/packages/astro/src/runtime/client/idle.ts b/packages/astro/src/runtime/client/idle.ts
index 627d896db..e1e1c5b2f 100644
--- a/packages/astro/src/runtime/client/idle.ts
+++ b/packages/astro/src/runtime/client/idle.ts
@@ -1,7 +1,7 @@
import type { GetHydrateCallback, HydrateOptions } from '../../@types/astro';
/**
- * Hydrate this component as soon as the main thread is free
+ * Hydrate this component as soon as the main thread is free!
* (or after a short delay, if `requestIdleCallback`) isn't supported
*/
export default async function onIdle(
diff --git a/packages/astro/src/runtime/client/load.ts b/packages/astro/src/runtime/client/load.ts
index cf4cd83af..d969b4061 100644
--- a/packages/astro/src/runtime/client/load.ts
+++ b/packages/astro/src/runtime/client/load.ts
@@ -1,7 +1,7 @@
import type { GetHydrateCallback, HydrateOptions } from '../../@types/astro';
/**
- * Hydrate this component immediately
+ * Hydrate this component immediately!
*/
export default async function onLoad(
astroId: string,
diff --git a/packages/astro/src/runtime/client/media.ts b/packages/astro/src/runtime/client/media.ts
index 32e883908..edaa9a433 100644
--- a/packages/astro/src/runtime/client/media.ts
+++ b/packages/astro/src/runtime/client/media.ts
@@ -1,7 +1,7 @@
import type { GetHydrateCallback, HydrateOptions } from '../../@types/astro';
/**
- * Hydrate this component when a matching media query is found
+ * Hydrate this component when a matching media query is found!
*/
export default async function onMedia(
astroId: string,
diff --git a/packages/astro/src/runtime/client/only.ts b/packages/astro/src/runtime/client/only.ts
index 6400d44b8..04937c608 100644
--- a/packages/astro/src/runtime/client/only.ts
+++ b/packages/astro/src/runtime/client/only.ts
@@ -1,9 +1,9 @@
import type { GetHydrateCallback, HydrateOptions } from '../../@types/astro';
/**
- * Hydrate this component immediately
+ * Hydrate this component only on the client
*/
-export default async function onLoad(
+export default async function onOnly(
astroId: string,
options: HydrateOptions,
getHydrateCallback: GetHydrateCallback
diff --git a/packages/astro/src/runtime/client/visible.ts b/packages/astro/src/runtime/client/visible.ts
index e0c1fdc73..e9c3e3310 100644
--- a/packages/astro/src/runtime/client/visible.ts
+++ b/packages/astro/src/runtime/client/visible.ts
@@ -1,7 +1,7 @@
import type { GetHydrateCallback, HydrateOptions } from '../../@types/astro';
/**
- * Hydrate this component when one of it's children becomes visible.
+ * Hydrate this component when one of it's children becomes visible!
* We target the children because `astro-root` is set to `display: contents`
* which doesn't work with IntersectionObserver
*/