apps/web/vite.config.ts
Rama main · réplica de lectura del repositorio original.
import { readFileSync } from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { defineConfig, loadEnv } from "vite";
import react from "@vitejs/plugin-react";
import tailwindcss from "@tailwindcss/vite";
import istanbul from "vite-plugin-istanbul";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
type DevPortsFile = {
development: {
webHost: string;
webPort: number;
apiHost: string;
apiPort: number;
};
};
const devPortsPath = path.join(
__dirname,
"..",
"..",
"scripts",
"dev-ports.json",
);
const devPorts = JSON.parse(
readFileSync(devPortsPath, "utf-8"),
) as DevPortsFile;
const dev = devPorts.development;
/**
* The build the browser tests (apps/server/tests/Weir.E2E.Tests) measure: every source file the unit coverage counts
* is instrumented (the same files as `test.coverage` below), so the page reports what ran in `window.__coverage__`. Opt-in with WEIR_WEB_COVERAGE=1; a normal
* build carries none of it (docs/coverage/README.md).
*/
function browserCoverage() {
return istanbul({
include: "src/**/*",
exclude: [
"src/**/*.test.{ts,tsx}",
"src/test/**",
"src/**/*.d.ts",
"src/lib/api/generated/**",
],
extension: [".ts", ".tsx"],
requireEnv: false,
forceBuildInstrument: true,
});
}
/** Local-only unless someone deliberately opts into exposing the dev server on the network. */
const devHost = (process.env.VITE_HOST || "").trim() || "127.0.0.1";
/** ``run-dev-stack.mjs`` may bump the port when the default from ``dev-ports.json`` is busy. */
const devWebPort = (() => {
const raw = (process.env.WEIR_DEV_WEB_PORT || "").trim();
if (raw) {
const n = Number(raw);
if (Number.isFinite(n) && n >= 1 && n <= 65535) {
return n;
}
}
return dev.webPort;
})();
function apiProxyTarget(mode: string, envDir: string): string {
// Takes precedence over .env* (loadEnv) so automation can pin /api to a known backend.
const forced = (process.env.WEIR_SCREENSHOT_API_PROXY_TARGET || "").trim();
if (forced) {
return forced;
}
// ``run-dev-stack.mjs`` sets this when the default API port holds an outdated build but a
// fresh API is started on another port (see the stale-route probes).
const devStackProxy = (
process.env.WEIR_DEV_STACK_API_PROXY_TARGET || ""
).trim();
if (devStackProxy) {
return devStackProxy;
}
const fromFiles = loadEnv(mode, envDir, "");
const fallback = `http://${dev.apiHost}:${dev.apiPort}`;
return (
fromFiles.VITE_DEV_API_PROXY_TARGET ||
process.env.VITE_DEV_API_PROXY_TARGET ||
fallback
);
}
export default defineConfig(({ mode }) => {
const apiTarget = apiProxyTarget(mode, __dirname);
const apiProxy = {
"/api": {
target: apiTarget,
changeOrigin: true,
},
"/ready": {
target: apiTarget,
changeOrigin: true,
},
"/health": {
target: apiTarget,
changeOrigin: true,
},
};
return {
plugins: [
react(),
tailwindcss(),
...(process.env.WEIR_WEB_COVERAGE === "1" ? [browserCoverage()] : []),
],
build: {
// Source maps are opt-in for local diagnostics. Production artifacts do not expose
// source paths or ship multi-megabyte maps by default.
sourcemap:
process.env.WEIR_BUILD_SOURCEMAPS === "true" ? "hidden" : false,
// Fonts stay files. A script's font is only fetched when text in that script appears (each
// subset's `unicode-range`), but a font small enough to be inlined was written into every
// visitor's stylesheet whether or not it was ever used: 2.7 KB of the 200 KiB budget.
assetsInlineLimit: (file) =>
file.endsWith(".woff2") ? false : undefined,
},
server: {
// Local-only: binds to 127.0.0.1, not every interface, so the dev server isn't reachable
// from the rest of the network by default. Set VITE_HOST (env) or pass --host to Vite to
// expose it on purpose. Default port from ``dev-ports.json`` unless overridden.
host: devHost,
port: devWebPort,
strictPort: true,
proxy: { ...apiProxy },
},
/** Same-origin cookies in dev/preview: browser hits the Vite port; /api is forwarded. */
preview: {
host: devHost,
port: devWebPort,
strictPort: true,
proxy: { ...apiProxy },
},
test: {
environment: "jsdom",
environmentOptions: {
jsdom: {
url: "http://localhost/",
},
},
setupFiles: "./src/test/setup.ts",
// A test that reads a stylesheet's own text (`?raw`) gets it; every other stylesheet stays empty.
css: { include: /\.css\?raw$/ },
globals: true,
// Longer than the hang guard for a wait in src/test/setup.ts, so a wait that hangs is reported as that wait.
testTimeout: 30_000,
coverage: {
provider: "v8",
// Every source file counts, tested or not: an untested file is a row of zeros in the report.
include: ["src/**/*.{ts,tsx}"],
exclude: [
"src/**/*.test.{ts,tsx}",
"src/test/**",
"src/**/*.d.ts",
"src/lib/api/generated/**",
],
reporter: ["lcov", "json", "json-summary", "text-summary"],
reportsDirectory: "./coverage",
},
},
};
});