Vite Plugin
@gjsify/vite-plugin-gjsify brings GJSify’s build transforms to Vite. Spread one preset
into vite.config.ts and your dev server resolves modules the same way
gjsify build --app browser does, so what you see in dev is what you ship.
You do not need the gjsify CLI for this. The plugin is an ordinary npm package whose
only peer dependency is vite. Install it, add it to your config, and run plain vite /
vite build.
Install
Section titled “Install”npm install -D @gjsify/vite-plugin-gjsify viteyarn add -D @gjsify/vite-plugin-gjsify vitepnpm add -D @gjsify/vite-plugin-gjsify vitebun add --dev @gjsify/vite-plugin-gjsify vitegjsify install @gjsify/vite-plugin-gjsify viteBuild for the browser
Section titled “Build for the browser”import { defineConfig } from 'vite';import { gjsifyBrowser } from '@gjsify/vite-plugin-gjsify';
export default defineConfig({ plugins: [...gjsifyBrowser()],});gjsifyBrowser() returns a plugin array, so spread it. Don’t nest it.
The preset is four pieces:
| Piece | What it does |
|---|---|
gjsImportsEmptyPlugin() | Resolves @girs/* and gi://… to an empty module. They arrive transitively (through @gjsify/unit, for instance) and no browser can resolve them. |
blueprintPlugin() | Compiles .blp to an XML string, so import T from './window.blp' works in dev too. |
deepkitPlugin() | Deepkit runtime types. Off unless you set reflection: true. |
A Vite config() hook | Browser polyfill aliases (process → @gjsify/empty, assert → @gjsify/assert), resolve.conditions: ['import', 'browser'], resolve.mainFields: ['browser', 'module', 'main'], define for global and window → globalThis, build.target: 'esnext', and optimizeDeps.exclude for GJS-shaped deps that Vite’s esbuild pre-bundler cannot crawl. |
Options
Section titled “Options”| Option | Default | What it does |
|---|---|---|
reflection | false | Turn on @deepkit/type runtime reflection. The type compiler stays uninstalled until you ask for it. |
aliases | {} | Extra resolve.alias entries, merged over the defaults. Yours win. |
optimizeDepsExclude | [] | More packages for optimizeDeps.exclude. @gjsify/unit is always excluded. |
cssAsString | false | See below. |
Share one CSS pattern with the native target
Section titled “Share one CSS pattern with the native target”By default the preset leaves CSS to Vite: HMR, <link> extraction, PostCSS. That is what a
browser-only app wants, so leave it alone unless you also ship a GTK build.
Turn on cssAsString: true when the same app builds for both. A GTK app has no stylesheet
link, so gjsify build --app gjs and gjsify build --app browser both hand you the CSS as a
string. With the flag on, Vite dev agrees:
import css from './app.css'; // the CSS string, on both targets
// GJS: Gtk.CssProvider.load_from_string(css)// Browser: document.head.append(Object.assign(document.createElement('style'), { textContent: css }))You author one real .css file and apply it per target. The trade is Vite’s CSS HMR and
<link> extraction.
Build for NativeScript
Section titled “Build for NativeScript”For a NativeScript app, use the one-file composer
@gjsify/nativescript-vite. It
adds the GJSify transforms and repairs several @nativescript/vite incompatibilities with
Vite 8 and Rolldown:
import { defineNativescriptConfig } from '@gjsify/nativescript-vite';
export default defineNativescriptConfig();If you need to compose the plugins yourself, gjsifyNativescript() is the lower-level form:
import { defineConfig } from 'vite';import nativescript from '@nativescript/vite';import { gjsifyNativescript } from '@gjsify/vite-plugin-gjsify';
export default defineConfig({ plugins: [nativescript(), ...gjsifyNativescript()],});It takes the same reflection, aliases and optimizeDepsExclude options as
gjsifyBrowser(), resolves *.android / *.ios / *.native source variants, and registers
the barrel modules your XML references through an xmlns namespace.
When you still want the CLI
Section titled “When you still want the CLI”The plugin covers development. Reach for gjsify when you need:
gjsify build --app gjs, the native GJS/GTK bundle. Vite targets browsers; there is no equivalent.gjsify build --app browser, the production browser bundle this preset mirrors. Plainvite buildalso works; the preset is what keeps the two equivalent.- Everything that is not a build:
gjsify install,tsc,lint,format,storybook,publish.
A browser-only app can live entirely on Vite. A dual-target app uses both.
Related
Section titled “Related”- How it works for the transforms behind the presets
- CLI reference for
gjsify buildand its targets @gjsify/vite-plugin-gjsifyon npm