Skip to content

feat: add @primer/view-components/lazy entrypoint with Catalyst lazyDefine#4140

Draft
mattcosta7 with Copilot wants to merge 3 commits into
mainfrom
copilot/add-lazy-entrypoint
Draft

feat: add @primer/view-components/lazy entrypoint with Catalyst lazyDefine#4140
mattcosta7 with Copilot wants to merge 3 commits into
mainfrom
copilot/add-lazy-entrypoint

Conversation

Copilot AI commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Adds an opt-in @primer/view-components/lazy entrypoint so consumers can code-split Primer JS and only load element chunks on demand — without touching the default eager behavior.

What are you trying to accomplish?

Today every custom element registers synchronously at import time via a single bundle. Consumers who only use a few components still pay the cost of all ~30 elements on every page load. This adds a lazy opt-in backed by @github/catalyst's lazyDefine so elements register only when their tag appears in the DOM.

// default — unchanged, fully eager
import '@primer/view-components'

// new opt-in — elements register on DOM presence via Catalyst lazyDefine
import '@primer/view-components/lazy'

Screenshots

N/A — no visual changes.

Integration

No changes required in production. The default entry is unchanged. Consumers must explicitly opt in to @primer/view-components/lazy.

List the issues that this change affects.

Risk Assessment

  • Low risk the change is small, highly observable, and easily rolled back.

Additive only. Default entry untouched. New file, new export, new build output.

What approach did you choose and why?

app/components/primer/lazy.ts — single lazyDefine({...}) call (batch object form) mapping each of the 29 element tag names to a dynamic import(). Side-effect-only modules (shared_events, utils) and base deps (@github/include-fragment-element, @github/remote-input-element) are imported eagerly since they have no custom element tag. The lazyDefine call is guarded with typeof document !== 'undefined' for SSR safety.

The trigger is DOM presence (Catalyst uses a MutationObserver; default strategy is ready — fires after DOMContentLoaded when the tag is in the DOM, not viewport intersection). No IntersectionObserver special-casing is needed.

rollup.config.js — changed from a single object to an array. The second config targets lazy.js with format: 'es', output.dir (code-split), and preserveEntrySignatures: false. The existing IIFE build is untouched. Shared onwarn and terserOptions extracted to avoid duplication.

package.json./lazy subpath export added before the ./* catch-all:

"./lazy": {
  "types": "./app/components/primer/lazy.d.ts",
  "import": "./app/components/primer/lazy.js"
}

component_generator.thor — new register_in_lazy_ts step inserts entries into lazy.ts's lazyDefine object via an // [GENERATOR ANCHOR] comment, keeping eager and lazy in sync for future scaffolded components.

test/lib/js_entrypoints_test.rb — drift test: parses primer.ts imports and lazy.ts dynamic import paths by regex and asserts the sets are identical. Fails loudly if they diverge.

docs/contributors/lazy-entrypoint.md — documents both entrypoints, DOM-presence trigger semantics, data-load-on override, and the sync enforcement mechanism.

Anything you want to highlight for special attention from reviewers?

  • The lazy entry re-uses each element module's existing self-registration guard (if (!customElements.get(tag)) customElements.define(...)) for dedup — no double-define risk.
  • details-menu (→ ./alpha/dropdown), auto-complete, clipboard-copy, relative-time, and tab-container are mapped via their wrapper modules, which in turn import the corresponding @github/* packages.
  • The drift test is the primary safety net. The generator hook keeps things in sync going forward.

Accessibility

No UI changes — no accessibility impact.

Merge checklist

  • Added/updated tests
  • Added/updated documentation
  • Added/updated previews (Lookbook)
  • Tested in Chrome
  • Tested in Firefox
  • Tested in Safari
  • Tested in Edge

@changeset-bot

changeset-bot Bot commented Jul 18, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: a414e0e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@primer/view-components Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copilot AI changed the title [WIP] Add lazy entrypoint for custom elements registration feat: add @primer/view-components/lazy entrypoint with Catalyst lazyDefine Jul 18, 2026
Copilot AI requested a review from mattcosta7 July 18, 2026 18:04
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.

2 participants