OpenZeppelin / OpenZeppelin/openzeppelin-ui

feat(components): make CodeView language grammars tree-shakeable

Open
#227 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
TypeScript
Stars
7
Forks
3
Avg merge
20h 20m
Merged PRs (30d)
26

Description

Summary

Today, importing @openzeppelin/ui-components/code-view statically registers all highlight.js grammars in one module. Bundlers cannot drop unused languages based on the runtime language prop. Make grammar loading tree-shakeable (or otherwise optional per language) so apps that only need a subset do not pay for every grammar.

Related: add TypeScript / JavaScript / Solidity — #226. Context from CodeView in #225.

Current behaviour

// highlight.ts — all grammars are static imports
const lowlight = createLowlight({ bash, ini, json, markdown, rust });
  • App never imports ./code-view: highlighter is correctly excluded (subpath boundary).
  • App imports CodeView once: every registered grammar ships, regardless of which language values are used.

Documented contract: tokenization is synchronous in render, memoized on [source, language].

Why this is non-trivial

Per-language tree-shaking needs either lazy import() (async first paint) or opt-in side-effect imports (awkward DX). Both are deliberate API/invariant changes, not a half-day cleanup.

Options to evaluate (Design)

Approach Tree-shake? Trade-off
Lazy grammar import() + cache; plaintext/skeleton until ready Yes Breaks pure sync first highlight; needs loading path + invariant/docs rewrite
Opt-in side-effect entrypoints (e.g. code-view/languages/rust) Yes Hosts must import every language they use; easy to miss
Consumer-registered grammars Yes Larger API; fights closed private registry

Preference to explore first: lazy load + one-frame plaintext (or last-good) fallback — cleanest product shape if we accept a contract change.

Acceptance criteria

  • Design note chooses an approach and updates CodeView invariants/docs for sync vs async highlighting.
  • An app that only ever highlights e.g. rust + plaintext does not include unused grammar modules in a production bundle (proven with a packed-consumer or rollup/vite size check).
  • Fail-soft behaviour preserved (tokenizer errors → plaintext).
  • No requirement for consumers to supply themes/colors.
  • Changeset + docs for the new loading / import model.

Out of scope

  • Adding new languages (#226) — but the design should scale to TS/JS/Solidity without a second rewrite.
  • Replacing lowlight/highlight.js wholesale.

Motivation

As we add TypeScript, JavaScript, and especially Solidity (#226), the shared ./code-view chunk grows for every consumer. Tree-shaking keeps that expansion from punishing apps that only need a subset.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the highlight.ts static grammar imports and the CodeView context in #225, then compare the listed lazy-loading, opt-in entrypoint, and consumer-registration approaches. Validate the chosen design with a packed consumer or Rollup/Vite size check, and update the sync/async invariants, fail-soft behavior, changeset, and loading documentation.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
frontend, performance
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
32/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.