Skip to content

Macros

asRegion

Mark any imported component as a region: named, default, or a barrel re-export. The escape hatch for imports that the `with { … }` attribute form cannot reach. It operates 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 rides only a default import of one file. Sometimes you can reach a component only through a barrel: the index.ts of a design system, a @company/ui package. It comes in as a named import, and there is no place to hang the with { … }:

import { Header, Footer } from '@company/ui'; // named — no `with { … }` possible

import.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. Thus they cannot drift. Each mode operates:

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: the generated entry imports the component by its export name. Thus 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 very large mixed barrel ships only its own component, not the barrel. The generated entry does import { Header } from '@company/ui'. The bundler tree-shakes it exactly as it would in any location. Thus 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 .svelte host, it mints a placed island. Render it inline (<HeaderIsland/>, or <svelte:component this={HeaderIsland}/>).
  • In a .ts / .js registry or remote, it mints a held binding: a mountable value that a third-party renderer can place, or that region() 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 that a CMS or page builder can render. See held regions for what a .ts binding can do.

The rules

  • Top-level const only. 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. Thus it can never sit in a loop, function, block, larger expression, <script module>, or markup. Each of those is a build error.
  • The first argument is a component that you imported: a bare identifier bound to a top-level import (named or default, not import * as).
  • options is an object literal. No string shorthand: a { wake: 'load' } object, exactly like a with { … } clause.
  • One mechanism per component. A component already marked with an import attribute cannot also be passed to asRegion. Pick one.

Misuse fails at build, with an [ogygia] message that names the file and the fix. It is a compile construct: rewritten to a hoisted binding import. There is no asRegion at runtime.