# Incremental rendering and performance

Understand default caching, declare custom dependencies and measure update work.

Most integrations do not need cache tuning. Keep message identity and configuration stable so unchanged content can be reused. This page is for custom reading contributions and investigations into long-document update costs.

## What is reused by default

`QuireMarkdown` and `MdProse` cache complete top-level Vue block projections by default.
Reuse requires identical native Tree identity, source positions, reference destinations,
footnote numbering/navigation and rendering configuration. Late definitions can still update
earlier blocks. Growing paragraphs, lists and tables are projected again; individual nested
blocks, table rows and cells have no independent cache. Use `:cache="false"` for a full-projection
comparison without disabling incremental parsing.

## Declare custom dependencies

Custom reading contributions reproject conservatively by default, because their codec,
render and load functions can read the entire document. `cacheKey(document)` declares all
outside-node source and external-state dependencies; results are compared with `Object.is`.
Contributions that only read their own source, attrs and locale may return a constant key,
as the Status example does with `cacheKey: () => null`. For reference-dependent output, include
resolution status and target values; for external configuration, include its version or stable
identity. A constant must not hide actual dependencies. Built-in links and footnotes are still
checked automatically. `renderNode` has the equivalent `renderNodeKey(state)`; without it,
all blocks reproject. HTML blocks with allowLink/allowImage callbacks also reproject so reactive
policy inputs continue to be observed.

## Inspect work and bound retention

Advanced consumers can create one `MarkdownRenderer` per reader from the Vue entry, call
`renderer.render(state, locale, prefix, onError, options)`, and inspect `renderer.work`.
Call `clear()` when replacing a document or unmounting; Vue unmounting releases resources.
Keep the onError function identity stable. `renderMarkdown(...)` always performs full projection.
Default retention is at most 2048 blocks and 2,000,000 UTF-16 source units, configurable through
constructor options `maxBlocks/maxSourceUnits`; exceeding a budget falls back to projection.
These counters and budgets do not measure heap bytes, parsing time or browser painting.

## Other integration options

The package does not implement the earlier Incremark APIs; see the [algorithm comparison](/en/guide/comparison).
remark/rehype plugins and MDC templates also need separate adaptation.
React uses a [separate adapter](/en/guide/react) over the shared parser and cache rules. Arbitrary HTML template execution and content collections/routing are outside the reading API. The editor's `MdProse` shares this reading implementation and retains its
product diagram nodes and existing API; see [MD Editor](https://msfe.quirekit.com/en/guide/md-editor).


## Reproduce a comparison

Use a production build and identical documents with 20 UTF-16 units every 30ms. Compare cache=true and cache=false, warm up each mode, then repeat measurements.
Verify final text, link destinations, footnote counts and backlinks in both modes; also inspect intermediate prefixes and retained source after stopping.

Measure parsing, VNode projection, Vue commits and forced layout separately. Playback duration is not parse time, and forced layout does not measure browser painting.
Large lists, tables and paragraphs may each remain a single reprojected block. Top-level traversal and global reference checks still exist; constant cost per chunk is not guaranteed.
`MarkdownRenderer.work` counts only the most recent projection. The Playground does not present an uncontrolled engine speed ranking.

Historical dirty-worktree measurements do not describe a current release. Record source revision, document hash, browser, hardware, warmups and repetitions alongside correctness results.
