Files
vue-tui/packages/vite
Yunfei He 14d5e5f9ad feat(vite)!: don't bundle @vitejs/plugin-vue; compose it explicitly (0.2.0) (#234)
* feat(vite)!: don't bundle @vitejs/plugin-vue; compose it explicitly

BREAKING: vueTui() no longer includes @vitejs/plugin-vue. Add your own SFC/JSX
compiler alongside it — `[vueTui(), vue()]` for SFCs (JSX was already explicit:
`[vueTui(), vueJsx()]`). This makes SFC and JSX consistent, matches Vite
convention (your framework plugin is visible in the config), removes the "is
plugin-vue already bundled?" ambiguity, and keeps @vue-tui/vite focused on the
terminal dev server (HMR) + build wiring.

The dev plugin already force-client-compiles whichever plugin-vue/plugin-vue-jsx
is present (matched by name in configResolved), so user-provided plugins work
identically to the previously-bundled one.

- index.ts: drop the bundled vue() and the `vue` passthrough option.
- package.json: @vitejs/plugin-vue moves from dependencies to devDependencies +
  an OPTIONAL peerDependency (^6) — optional because JSX (plugin-vue-jsx) and
  h() users don't need it; the version is still validated when present.
  Bump 0.1.2 -> 0.2.0.
- Update all in-repo SFC configs (examples + fixtures) and the dev/build tests
  to `[vueTui(), vue()]`; update basic-template's README.

vp run ready green (vite suite 129 tests, runtime examples 6).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(vite): use the public [vueTui(), vue()] form in dev tests

The decouple migration left the tests on the spread `[...vueTui(), vue()]` while
configs/examples/docs use `[vueTui(), vue()]` (Vite flattens the nested plugin
array — verified it works in createServer too). Align the tests to the
documented consumer form for consistency. Vite suite green (12 files, 28 tests).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(vite): compiler plugin first in order — [vue(), vueTui()]

Convention: list the SFC/JSX compiler first and vueTui() last
([vue(), vueTui()] / [vueJsx(), vueTui()]). Order is functionally irrelevant
(devPlugin force-compiles whichever plugin-vue/vue-jsx is present by name in
configResolved), so this is purely stylistic consistency across configs,
examples, fixtures, tests, and docs.

Also refresh @vue-tui/vite's own README, which still showed the pre-decouple
[vueTui()] form and documented the now-removed `vue` passthrough option.

Vite suite green (28 tests, incl. the JSX path).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 22:41:28 +08:00
..

@vue-tui/vite

Vite plugin for vue-tui: an in-process terminal dev server with HMR, plus a production build, for Vue apps that render to the terminal via @vue-tui/runtime.

Install

npm install -D @vue-tui/vite @vitejs/plugin-vue
# peer deps: vite ^8, @vue-tui/runtime

Usage

vueTui() adds the terminal dev server (HMR) and the production build. Bring your own SFC/JSX compiler alongside it — @vitejs/plugin-vue for SFCs (or @vitejs/plugin-vue-jsx for JSX):

// vite.config.ts
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import { vueTui } from "@vue-tui/vite";

export default defineConfig({
  plugins: [vue(), vueTui()],
});
  • vite (dev) — boots the app in-process through Vite's SSR module runner and renders it to the terminal, with state-preserving HMR.
  • vite build — bundles a single Node entry (dist/main.js).

Options

vueTui({
  entry: "src/main.ts", // default; the app entry (a .ts/.tsx file, not an index.html)
});

For a JSX/TSX entry, use @vitejs/plugin-vue-jsx and point entry at the .tsx file:

import vueJsx from "@vitejs/plugin-vue-jsx";

export default defineConfig({
  plugins: [vueJsx(), vueTui({ entry: "/src/main.tsx" })],
});

Build output

By default the production build externalizes bare dependencies (vue, @vue-tui/runtime, …) — Node resolves them from node_modules at runtime. This is the right shape for a library, or an app shipped alongside its node_modules.

Distribution shape is yours to choose: to produce a self-contained single file (everything bundled but Node builtins — e.g. toward a standalone binary), set your own build options in vite.config.ts and the plugin yields to them:

import vue from "@vitejs/plugin-vue";
import { isBuiltin } from "node:module";

export default defineConfig({
  plugins: [vue(), vueTui()],
  build: {
    // Vite 8 is Rolldown-powered: the field is `rolldownOptions` (`rollupOptions` is the alias).
    rolldownOptions: {
      external: (id) => isBuiltin(id), // only Node builtins stay external
      platform: "node", // real createRequire for any CJS dependency
      output: { inlineDynamicImports: true }, // fold into one file
    },
  },
});

License

MIT