Skip to content

perf(website): Lazy-load Ace editor via dynamic import#1587

Merged
yamadashy merged 2 commits into
mainfrom
perf/lazy-ace-editor
May 21, 2026
Merged

perf(website): Lazy-load Ace editor via dynamic import#1587
yamadashy merged 2 commits into
mainfrom
perf/lazy-ace-editor

Conversation

@yamadashy

Copy link
Copy Markdown
Owner

Summary

  • Wrap TryItResultContent.vue with defineAsyncComponent in TryItResult.vue so ace-builds / vue3-ace-editor (~480 KB of JS) load on demand instead of as part of the landing-page bundle.

Why

The Ace editor is only needed once the user has packed a repository, but it was previously imported statically and shipped with the initial bundle. Deferring it shrinks the homepage payload and improves Core Web Vitals (LCP/INP), particularly on mobile / low-bandwidth connections.

Verification

  • node --run docs:build produces a separate TryItResultContent.*.js chunk (~480 KB) confirming the editor is now split out.

Checklist

  • Run node --run lint (website/client)
  • Run node --run docs:build (website/client)

`TryItResultContent.vue` pulls in `ace-builds` and `vue3-ace-editor`,
which add ~480 KB of JS that the landing page does not need until the
user actually packs a repository. Wrapping the import with
`defineAsyncComponent` moves that work into a separately fetched chunk,
trimming the initial bundle and improving LCP/INP on the homepage.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented May 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 52c42aa9-b25a-42af-9c5f-92b25684fa59

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

TryItResultContent component import is converted from static to lazy-loaded. The import statement now uses defineAsyncComponent with dynamic import() to defer loading the heavy editor-based view until the component is actually rendered.

Changes

Lazy-load TryItResultContent component

Layer / File(s) Summary
Lazy-load TryItResultContent component
website/client/components/Home/TryItResult.vue
defineAsyncComponent is imported and replaces the static TryItResultContent import with a dynamically imported async component, deferring the load of the editor-based view.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~5 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: lazy-loading the Ace editor via dynamic import, which matches the core objective of deferring editor imports for performance.
Description check ✅ Passed The description includes all required template sections with comprehensive details: summary of changes, rationale, verification steps, and a completed checklist. However, the specific test commands from the template are not mentioned.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch perf/lazy-ace-editor

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist gemini-code-assist Bot left a comment

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.

Code Review

This pull request optimizes the TryItResult.vue component by converting the TryItResultContent import into an asynchronous component using defineAsyncComponent to reduce the initial bundle size. The reviewer suggested enhancing this implementation by using the object syntax for defineAsyncComponent to include a loading component and error handling, which addresses potential UI gaps during the asynchronous loading of the heavy Ace editor dependencies.

Comment thread website/client/components/Home/TryItResult.vue Outdated
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented May 21, 2026

Copy link
Copy Markdown

Deploying repomix with  Cloudflare Pages  Cloudflare Pages

Latest commit: 797fd46
Status:⚡️  Build in progress...

View logs

@github-actions

github-actions Bot commented May 21, 2026

Copy link
Copy Markdown
Contributor

⚡ Performance Benchmark

Latest commit:797fd46 fix(website): Address PR review feedback for lazy Ace editor
Status:✅ Benchmark complete!
Ubuntu:0.68s (±0.01s) → 0.68s (±0.01s) · +0.00s (+0.4%)
macOS:0.63s (±0.20s) → 0.63s (±0.23s) · -0.01s (-1.1%)
Windows:0.96s (±0.02s) → 0.95s (±0.01s) · -0.00s (-0.2%)
Details
  • Packing the repomix repository with node bin/repomix.cjs
  • Warmup: 2 runs (discarded), interleaved execution
  • Measurement: 20 runs / 30 on macOS (median ± IQR)
  • Workflow run
History

981cfeb perf(website): Lazy-load Ace editor via dynamic import

Ubuntu:0.66s (±0.01s) → 0.66s (±0.02s) · +0.00s (+0.3%)
macOS:0.39s (±0.03s) → 0.40s (±0.04s) · +0.01s (+2.0%)
Windows:0.86s (±0.01s) → 0.86s (±0.01s) · +0.01s (+0.7%)

@claude

claude Bot commented May 21, 2026

Copy link
Copy Markdown
Contributor

Claude Review

Clean, well-scoped change — verified end-to-end that TryItResultContent.vue is the only runtime entry point for ace-builds / vue3-ace-editor (the one other reference in website/client/components/utils/resultViewer.ts is a type-only import and erased at compile time), and that the boundary is correctly placed under v-else-if="result" so the chunk is only fetched after a successful pack. No security, code-quality, or regression concerns.

Details

Recommended (non-blocking)

  1. Consider the object form of defineAsyncComponent to handle the loading/error UI gaps (this matches the gemini reviewer's suggestion). On a slow network the result panel could appear briefly empty after the pack RPC returns. You already have suitable components imported in this file:

    const TryItResultContent = defineAsyncComponent({
      loader: () => import('./TryItResultContent.vue'),
      loadingComponent: TryItLoading,
      errorComponent: TryItResultErrorContent,
      timeout: 30000,
    });

    That said, since the chunk fetch happens after the user has already waited for the server pack RPC, the gap is usually imperceptible — feel free to skip if you've validated this on a throttled connection.

  2. Prefetch on user intent. The chunk fetch currently begins only when result becomes truthy. You could overlap it with the server roundtrip by triggering a warm-up import('./TryItResultContent.vue') when the user first focuses the URL input or clicks Pack, e.g. inside the submit handler before awaiting the server. Hides the entire 480 KB fetch behind work the user is already waiting for. Probably a follow-up rather than this PR.

  3. PR description checklist. The repo's .github/pull_request_template.md includes a checklist (npm run test, npm run lint) that isn't in the current description. Minor process nit.

Nit

  • The inline comment is great — optionally mention the rough size (~480 KB) so future contributors think twice before re-static-importing.
  • This is the first use of defineAsyncComponent in website/client/ — the syntax is the canonical Vue 3 form, so it sets a fine precedent.

Other notes

  • Security: No surface change. The import specifier is a compile-time constant, no new dependencies, identical trust boundary.
  • Tests: website/client/ has no Vue component test infrastructure today, so there's nothing to update or break. A future guardrail could be a tiny CI check (grep, or rollup-plugin-visualizer snapshot) asserting that ace-builds lands in a separate chunk — out of scope here.
  • Other lazy-load candidates: TryItFileSelection.vue (~373 lines) and TryItResultErrorContent.vue (~161 lines) are also post-execution components, but their payloads are pure Vue/TS — marginal benefit vs. ace-builds. Not worth bundling into this PR.

LGTM — safe to merge as-is.

Use the object form of `defineAsyncComponent` so the chunk fetch shows
`TryItLoading` after a short `delay` and surfaces a timeout instead of
leaving the panel blank if the fetch stalls. Also annotate the
inline comment with the rough chunk size (~480 KB) so future
contributors think twice before re-static-importing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@yamadashy yamadashy merged commit 3372946 into main May 21, 2026
24 of 25 checks passed
@yamadashy yamadashy deleted the perf/lazy-ace-editor branch May 21, 2026 15:19
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.

1 participant