Library Builds#

The @sigx/vite/lib subpath exports defineLibConfig, a helper that produces a Vite 8 / Rolldown library-build config for @sigx/* packages. It normalizes entries, externalizes the SignalX runtime, and applies sensible defaults so every package builds consistently.

TypeScript
import { defineLibConfig } from '@sigx/vite/lib';

A direct re-export of Vite's own defineConfig is also available from the same subpath, for composing custom configs alongside defineLibConfig:

TypeScript
import { defineLibConfig, defineConfig } from '@sigx/vite/lib';

Single Entry#

The simplest config builds one entry to ES modules:

TypeScript
// vite.config.ts
import { defineLibConfig } from '@sigx/vite/lib';

export default defineLibConfig({
    entry: 'src/index.ts',
});

Output files use the format ${entryName}.js (ES format only). Sourcemaps are on by default, and output is minified in place by Oxc unless you set minify: false.

Multiple Entries#

Pass a record (or an array of LibEntry objects) to build multiple entries — useful for packages with subpath exports:

TypeScript
// vite.config.ts
import { defineLibConfig } from '@sigx/vite/lib';

export default defineLibConfig({
    entry: {
        index: 'src/index.ts',
        'server/index': 'src/server/index.ts',
        'client/index': 'src/client/index.ts',
    },
    external: ['sigx', /@sigx\/.*/],
});

The keys become output file names (without extension). The array form is equivalent:

TypeScript
import { defineLibConfig } from '@sigx/vite/lib';

export default defineLibConfig({
    entry: [
        { name: 'index', entry: 'src/index.ts' },
        { name: 'utils', entry: 'src/utils.ts' },
    ],
});

Runtime Externals Are Always Added#

Whatever you pass as external, defineLibConfig always prepends the SignalX runtime tier — sigx, @sigx/reactivity, @sigx/runtime-core, @sigx/runtime-dom, @sigx/server-renderer, and their subpaths — and dedupes the result. This keeps the runtime out of your bundle and preserves singleton reactivity for consumers.

Bundling Sibling Packages with Aliases#

When you need to bundle sibling packages in a monorepo, use alias to map import paths to source files. Pass root: import.meta.url so those relative paths resolve against your package directory:

TypeScript
// vite.config.ts
import { defineLibConfig } from '@sigx/vite/lib';

export default defineLibConfig({
    entry: {
        sigx: 'src/index.ts',
        hydration: 'src/hydration.ts',
    },
    alias: {
        '@sigx/reactivity': '../reactivity/src/index.ts',
        '@sigx/runtime-core': '../runtime-core/src/index.ts',
        '@sigx/runtime-dom': '../runtime-dom/src/index.ts',
    },
    minify: true,
    root: import.meta.url,
});

root accepts a file:// URL (such as import.meta.url) or a directory path. Always set it when you use alias.

JSX Libraries#

Set jsx: true to enable Oxc's automatic JSX transform with import source sigx:

TypeScript
import { defineLibConfig } from '@sigx/vite/lib';

export default defineLibConfig({
    entry: 'src/index.ts',
    jsx: true,
});

Targeting a non-web runtime#

sigx is the web umbrella — it carries @sigx/runtime-dom, and with it the DOM JSX.IntrinsicElements. A component library for another target (terminal, lynx, or a custom renderer) must compile against that target's runtime instead, or every JSX element in the consuming app is typed against the DOM.

importSource is that dial:

TypeScript
import { defineLibConfig } from '@sigx/vite/lib';

export default defineLibConfig({
    entry: 'src/index.ts',
    jsx: true,
    importSource: '@sigx/runtime-core',   // default: 'sigx'
});

It is read only when jsx is enabled, and it defaults to 'sigx' — existing library builds are unaffected.

This replaces per-file pragmas. Before importSource, the only way to retarget the JSX runtime was a /** @jsxImportSource … */ comment at the top of every .tsx source, because oxc honours a pragma over config. One config line now does what a pragma per file used to.

Node and CLI Builds#

For a Node-targeted build, set platform: 'node' (targets node18). For a CLI that needs a shebang, use banner:

TypeScript
import { defineLibConfig } from '@sigx/vite/lib';

export default defineLibConfig({
    entry: 'src/cli.ts',
    platform: 'node',
    banner: '#!/usr/bin/env node',
});

Dual-dist (development + production) builds#

defineLibConfig returns a config function that branches on Vite's --mode. Run it twice to emit a development dist and a parallel production dist into the same outDir:

JSONC
// package.json
{
    "scripts": {
        "build": "vite build && vite build --mode prod-dist"
    }
}
  • vite build — the default (development) dist. Files are ${entryName}.js and emptyOutDir is on, so the directory starts clean.
  • vite build --mode prod-dist — the production dist, written alongside the dev output (it does not empty the directory). process.env.NODE_ENV is defined away to 'production' so dev-only warnings and devtools plumbing are stripped, and every file gets a .prod.js suffix.

Point the package's production export condition at the .prod.js files so consumers building for production pick up the stripped-down runtime automatically:

JSONC
// package.json (sketch)
{
    "exports": {
        ".": {
            "production": "./dist/index.prod.js",
            "default": "./dist/index.js"
        }
    }
}

Defaults Summary#

OptionDefaultEffect
outDir'dist'Output directory; emptyOutDir is on for the default build and off for the prod-dist pass, so the two builds sit side by side.
sourcemaptrueEmit sourcemaps.
external[/@sigx\/.*/]Runtime tier is always added on top.
minifytrueMinify output in place via Oxc (or false).
jsxfalseAutomatic JSX with import source sigx when true.
importSource'sigx'The module the automatic JSX runtime imports from. Read only when jsx is true.
platform'browser''node' targets node18; 'neutral' is also accepted.

Next Steps#