Macros
asRegion
Mark any imported component as a region — named, default, or a barrel re-export. The escape hatch for imports the `with { … }` attribute form can't reach, working the same in .svelte, .ts, and .js.
On this page
The import-attribute form is the usual way to mark a region:
import Counter from './Counter.svelte' with { wake: 'visible' };But an import attribute only rides a default import of one file. A component you can only reach through a barrel — a design system’s index.ts, a @company/ui package — comes in as a named import, and there is nowhere to hang the with { … }:
import { Header, Footer } from '@company/ui'; // named — no `with { … }` possibleimport.meta.og.asRegion(Comp, options) is the escape hatch. It marks any imported component — named, default, from a barrel — as a region:
<script>
import { Header } from '@company/ui';
const HeaderIsland = import.meta.og.asRegion(Header, { wake: 'load' });
</script>
<HeaderIsland {...props} />The options are exactly with { … }
options is an object that accepts exactly what an import attribute accepts — no more, no less. Both funnel through one parser, so they can’t drift. Every mode works:
const HeaderIsland = import.meta.og.asRegion(Header, { wake: 'load' }); // placed island
const ChartHole = import.meta.og.asRegion(Chart, { render: 'deferred', wake: 'visible' }); // server hole
const BlockRaw = import.meta.og.asRegion(Block, { region: 'raw' }); // held → region(BlockRaw, …)The output is identical to the with { … } form too — the only difference is the generated entry imports the component by its export name. So region identity keys on source#exportName: two named exports of one barrel are two distinct regions, never a collision.
Tree-shaking is preserved
A region off a huge mixed barrel ships only its own component, not the barrel. The generated entry does import { Header } from '@company/ui', and the bundler tree-shakes it exactly as it would anywhere — so a 100-component barrel with one region marked pulls in one component.
Works in .svelte, .ts, and .js
The same call, two shapes, depending on where it lives:
- In a
.sveltehost it mints a placed island — render it inline (<HeaderIsland/>, or<svelte:component this={HeaderIsland}/>). - In a
.ts/.jsregistry or remote it mints a held binding — a mountable value a third-party renderer can place, or thatregion()can turn into a held region:
import { Header } from '@company/ui';
// a mountable held binding — Builder.io's <svelte:component> places it directly,
// and region() can still cross it over the wire
const HeaderRegion = import.meta.og.asRegion(Header, { wake: 'visible' });
export const registry = [{ name: 'header', component: HeaderRegion }];This is the one line that turns a barrel-imported component into something a CMS or page builder can render. See held regions for what a .ts binding can do.
The rules
- Top-level
constonly.const Local = import.meta.og.asRegion(Comp, options)— one binding per statement, at the top level of the module or<script>. It compiles to a hoisted import, so it can never sit in a loop, function, block, larger expression,<script module>, or markup. Any of those is a build error. - The first argument is a component you imported — a bare identifier bound to a top-level import (named or default, not
import * as). optionsis an object literal. No string shorthand; a{ wake: 'load' }object, exactly like awith { … }clause.- One mechanism per component. A component already marked with an import attribute can’t also be passed to
asRegion— pick one.
Misuse fails at build with an [ogygia] message naming the file and the fix. It is a compile construct: rewritten to a hoisted binding import, there is no asRegion at runtime.