vite.config.js
Rama main · réplica de lectura del repositorio original.
import path from "node:path";
import { fileURLToPath } from "node:url";
import { defineConfig } from "vite";
import { transformSync, types as t } from "@babel/core";
import react from "@vitejs/plugin-react";
import { vitePrerenderPlugin } from "vite-prerender-plugin";
import { PRERENDERABLE_PUBLIC_ROUTES } from "./src/seo-config.js";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
// The crypto WASM URL is derived from the bundled module URL. Give the WASM
// artifact a per-build URL so a CDN/browser cannot reuse stale MIME headers.
const wasmBuildLabel = String(
process.env.VITE_WASM_ASSET_BUILD_ID ||
process.env.GITHUB_SHA ||
process.env.PASSDEPLOYER_GIT_SHA ||
"local",
)
.replace(/[^a-zA-Z0-9_-]/g, "")
.slice(0, 12) || "local";
const wasmBuildId = `${wasmBuildLabel}-${Date.now().toString(36)}`;
function localizeJsxTextPlugin() {
return {
name: "paasdeployer-localize-jsx-text",
enforce: "pre",
transform(source, id) {
const fileId = path.resolve(id.split("?")[0]).replace(/\\/g, "/");
const sourceRoot = path.join(__dirname, "src").replace(/\\/g, "/") + "/";
if (
!fileId.startsWith(sourceRoot) ||
!fileId.endsWith(".jsx") ||
fileId.includes("/i18n/") ||
fileId.includes("/scripts/")
) {
return null;
}
let hasLocalizedText = false;
const result = transformSync(source, {
filename: fileId,
babelrc: false,
configFile: false,
parserOpts: {
sourceType: "module",
plugins: ["jsx"],
},
generatorOpts: {
retainLines: true,
compact: false,
},
plugins: [
function localizeVisibleJsxText() {
return {
visitor: {
JSXText(jsxPath) {
let parent = jsxPath.parentPath;
while (parent && !parent.isJSXElement()) parent = parent.parentPath;
const parentName = parent?.node?.openingElement?.name;
const tagName = parentName?.type === "JSXIdentifier" ? parentName.name.toLowerCase() : "";
if (["code", "pre", "textarea", "script", "style"].includes(tagName)) return;
const value = String(jsxPath.node.value || "").replace(/\s+/g, " ");
if (!value.trim()) return;
hasLocalizedText = true;
const element = t.jsxElement(
t.jsxOpeningElement(
t.jsxIdentifier("LocalizedText"),
[t.jsxAttribute(t.jsxIdentifier("value"), t.jsxExpressionContainer(t.stringLiteral(value)))],
true,
),
null,
[],
true,
);
jsxPath.replaceWith(t.jsxExpressionContainer(element));
jsxPath.skip();
},
Program: {
exit(programPath) {
if (!hasLocalizedText) return;
const declaration = t.importDeclaration(
[
t.importSpecifier(
t.identifier("LocalizedText"),
t.identifier("LocalizedText"),
),
],
t.stringLiteral("/src/i18n/LocalizedText.jsx"),
);
programPath.unshiftContainer("body", declaration);
},
},
},
};
},
],
});
if (!hasLocalizedText || !result) return null;
return { code: result.code, map: result.map };
},
};
}
function emitSpaTemplate() {
return {
name: "paasdeployer-spa-template",
generateBundle(_options, bundle) {
const indexEntry = bundle["index.html"];
if (!indexEntry || indexEntry.type !== "asset") return;
this.emitFile({
type: "asset",
fileName: "_template.html",
source: String(indexEntry.source),
});
},
};
}
export default defineConfig({
resolve: {
alias: {
// vite-prerender-plugin executes the browser bundle in Node. Use
// Emotion's universal ESM build so its SSR path never assumes document.
"@emotion/cache": path.resolve(
__dirname,
"node_modules/@emotion/cache/dist/emotion-cache.esm.js",
),
},
},
plugins: [
localizeJsxTextPlugin(),
react(),
emitSpaTemplate(),
vitePrerenderPlugin({
renderTarget: "#root",
prerenderScript: path.resolve(__dirname, "src/prerender.jsx"),
additionalPrerenderRoutes: PRERENDERABLE_PUBLIC_ROUTES,
previewMiddlewareEnabled: true,
previewMiddlewareFallback: "/index.html",
}),
],
server: {
host: true,
proxy: {
"/ws": {
target: process.env.VITE_API_ORIGIN || "https://api.echonode.website",
ws: true,
changeOrigin: true,
secure: true,
},
},
},
build: {
outDir: "dist",
sourcemap: false,
cssCodeSplit: true,
minify: "esbuild",
rollupOptions: {
output: {
assetFileNames: (assetInfo) =>
String(assetInfo.name || "").toLowerCase().endsWith(".wasm")
? `assets/[name]-[hash]-${wasmBuildId}[extname]`
: "assets/[name]-[hash][extname]",
},
},
modulePreload: {
resolveDependencies: (_filename, deps) =>
deps.filter((dep) => !/(?:^|\/)prerender-[^/]+\.js$/.test(dep)),
},
},
});