vite.config.ts
Rama main · réplica de lectura del repositorio original.
// "vitest/config" re-exports vite's defineConfig and additionally accepts the
// `test` block below, so the dev/build config and the test config share one
// source of truth (notably the "@" alias).
import { defineConfig, type PluginOption } from "vitest/config";
import react from "@vitejs/plugin-react";
import tailwindcss from "@tailwindcss/vite";
import { readFileSync } from "node:fs";
import { Agent } from "node:http";
import { fileURLToPath, URL } from "node:url";
// @ts-expect-error process is a nodejs global
const host = process.env.TAURI_DEV_HOST;
const packageVersion = (JSON.parse(readFileSync(new URL("./package.json", import.meta.url), "utf8")) as { version: string })
.version;
/**
* The server edition builds the web client once and ships it in one Docker
* image, but every installation may run under its own path prefix
* (SCRIBEDOG_BASE_PATH). Vite bakes `base` into asset URLs at build time,
* so the web build uses a relative base and the page itself learns its
* prefix from this meta tag, which the server fills in when it serves
* index.html (server/src/web/staticSite.ts). The placeholder must look like a
* path so nothing else in the build ever matches it; it also has to stay in
* step with BASE_PATH_PLACEHOLDER on the server side.
*/
const BASE_PATH_PLACEHOLDER = "/__SCRIBEDOG_BASE_PATH__";
function webIndexHtml(): PluginOption {
return {
name: "scribedog-web-index-html",
transformIndexHtml: {
order: "pre",
handler: (html) =>
html.replace(
"<title>",
`<meta name="scribedog-base-path" content="${BASE_PATH_PLACEHOLDER}" />\n <title>`
)
}
};
}
// https://vite.dev/config/
export default defineConfig(async ({ mode }) => {
// Two build targets from one project: the Tauri desktop app (default) and
// the web client of the server edition (`--mode web`). They differ only in
// which platform implementation the `@platform-impl` alias resolves to,
// the asset base and the output directory; the application code is shared.
const isWeb = mode === "web";
return {
base: isWeb ? "./" : "/",
plugins: [react(), tailwindcss(), ...(isWeb ? [webIndexHtml()] : [])],
resolve: {
alias: {
"@": fileURLToPath(new URL("./src", import.meta.url)),
"@platform-impl": fileURLToPath(
new URL(isWeb ? "./src/platform/web/index.ts" : "./src/platform/desktop/index.ts", import.meta.url)
)
},
},
define: {
__SCRIBEDOG_VERSION__: JSON.stringify(packageVersion)
},
build: {
outDir: isWeb ? "dist-web" : "dist",
emptyOutDir: true
},
// The page map worker (src/lib/export/pageMapWorker.ts) loads pdfmake on
// demand, and only ES workers can split code.
worker: {
format: "es" as const
},
// Only pure logic is covered (no component rendering), so node is the right
// default; the few suites that parse markdown through a DOM opt into jsdom
// per file with a "@vitest-environment jsdom" comment.
test: {
environment: "node",
include: ["src/**/*.test.ts"],
},
// Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
//
// 1. prevent Vite from obscuring rust errors
clearScreen: false,
// 2. tauri expects a fixed port, fail if that port is not available
server: isWeb
? {
// `npm run dev:web` against a locally running server
// (`npm run dev` in server/), which answers the API on port 3000.
port: 5173,
strictPort: true,
proxy: {
"/api": {
target: "http://127.0.0.1:3000",
// /api/events is a WebSocket (the live-update channel). Without
// `ws` the upgrade is not forwarded, and without the error
// handler a client that drops the socket hard (a closed tab, a
// browser test ending) takes the whole dev server down with an
// unhandled ECONNRESET.
ws: true,
// Without an agent the proxy opens a fresh connection per
// request and asks the server to close it afterwards. Node on
// Windows then resets the socket before the send buffer has
// drained on larger responses, so about one image in six
// arrived truncated and the editor waited forever for it.
// Keep-alive connections are closed by nobody mid-response.
agent: new Agent({ keepAlive: true }),
configure: (proxy) => {
proxy.on("error", (error) => {
console.warn(`[dev:web] proxy: ${error.message}`);
});
}
}
}
}
: {
port: 1420,
strictPort: true,
host: host || false,
hmr: host
? {
protocol: "ws",
host,
port: 1421,
}
: undefined,
watch: {
// 3. tell Vite to ignore watching `src-tauri`
ignored: ["**/src-tauri/**"],
},
},
};
});