/* eslint-disable */ import { sentryVitePlugin } from "@sentry/vite-plugin"; import react from "@vitejs/plugin-react"; import chalk from "chalk"; import * as child from "child_process"; import { promises as fsPromises } from "fs"; import { createLogger, defineConfig } from "vite"; import { ViteEjsPlugin } from "vite-plugin-ejs"; import eslint from "vite-plugin-eslint"; import { VitePWA } from "vite-plugin-pwa"; import InstanceRenderManager from "./src/utils/instanceRenderMgr"; import browserslist from "browserslist"; import { browserslistToTargets } from "lightningcss"; import { fileURLToPath } from "url"; import { dirname, resolve } from "path"; process.env.VITE_APP_GIT_SHA_DATE = new Date().toLocaleString("en-US", { timeZone: "America/Los_Angeles" }); const commitHash = child.execSync("git rev-parse HEAD").toString().trimEnd(); process.env.VITE_GIT_COMMIT_HASH = commitHash; // Resolve browserslist from package.json and map to Lightning CSS targets const lightningCssTargets = browserslistToTargets( browserslist(undefined, { path: process.cwd(), env: process.env.NODE_ENV === "production" ? "production" : "development" }) ); const pstFormatter = new Intl.DateTimeFormat("en-CA", { timeZone: "America/Los_Angeles", year: "numeric", month: "2-digit", day: "2-digit" }); const currentDatePST = pstFormatter.format(new Date()); const getFormattedTimestamp = () => new Date().toLocaleTimeString("en-US", { hour12: true }).replace("AM", "a.m.").replace("PM", "p.m."); export const logger = createLogger("info", { allowClearScreen: false }); // Read HTTPS certs once (used by both server + preview) const httpsCerts = { key: await fsPromises.readFile("../certs/key.pem"), cert: await fsPromises.readFile("../certs/cert.pem") }; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); export default defineConfig(({ command, mode }) => { // React Compiler is always enabled for production/test builds // In dev mode, it's enabled by default but can be disabled with VITE_DISABLE_COMPILER_IN_DEV=true const isBuild = command === "build"; const isTestBuild = mode === "test" || process.env.VITE_APP_IS_TEST === "true" || process.env.VITE_APP_IS_TEST === "1"; const enableReactCompiler = (isBuild && (mode === "production" || isTestBuild)) || // Always enable for prod/test builds process.env?.VITE_DISABLE_COMPILER_IN_DEV !== "true"; // In dev, enable unless explicitly disabled logger.info( enableReactCompiler ? chalk.green.bold("React Compiler enabled") : chalk.yellow.bold("React Compiler disabled") ); return { base: "/", resolve: { dedupe: ["styled-components", "react", "react-dom"], alias: { // Force all styled-components imports to resolve to the same location (absolute path) "styled-components": resolve(__dirname, "node_modules/styled-components/dist/styled-components.browser.esm.js") } }, plugins: [ ViteEjsPlugin((viteConfig) => ({ env: viteConfig.env })), // PWA only for production builds (faster dev) VitePWA({ apply: "build", injectRegister: "auto", registerType: "prompt", workbox: { navigateFallbackDenylist: [/^\/api\//] // prevent caching API routes }, manifest: { short_name: InstanceRenderManager({ instance: process.env.VITE_APP_INSTANCE, imex: "ImEX Online", rome: "Rome Online" }), name: InstanceRenderManager({ instance: process.env.VITE_APP_INSTANCE, imex: "ImEX Online", rome: "Rome Online" }), description: "The ultimate bodyshop management system.", icons: [ { src: InstanceRenderManager({ instance: process.env.VITE_APP_INSTANCE, imex: "favicon.png", rome: "ro-favicon.png" }), sizes: "64x64 32x32 24x24 16x16", type: "image/x-icon" }, { src: InstanceRenderManager({ instance: process.env.VITE_APP_INSTANCE, imex: "logo192.png", rome: "logo192.png" }), type: "image/png", sizes: "192x192" }, { src: InstanceRenderManager({ instance: process.env.VITE_APP_INSTANCE, imex: "logo512.png", rome: "ro-favicon.png" }), type: "image/png", sizes: "512x512" } ], theme_color: InstanceRenderManager({ instance: process.env.VITE_APP_INSTANCE, imex: "#1890ff", rome: "#fff" }), background_color: "#fff", gcm_sender_id: "103953800507" } }), react( enableReactCompiler ? { babel: { plugins: [["babel-plugin-react-compiler"]] } } : undefined ), eslint(), // Sentry only for production builds (no dev overhead) sentryVitePlugin({ apply: "build", org: "imex", reactComponentAnnotation: { enabled: true }, release: { name: `${process.env.VITE_APP_IS_TEST ? "test" : "production"}-${currentDatePST}-${commitHash}`.trim() }, project: InstanceRenderManager({ instance: process.env.VITE_APP_INSTANCE, imex: "imexonline", rome: "rome-online" }) }) ], define: { APP_VERSION: JSON.stringify(process.env.npm_package_version), __COMMIT_HASH__: JSON.stringify(commitHash) }, server: { host: true, port: 3000, open: true, proxy: { "/ws": { target: "http://localhost:4000", secure: false, ws: true }, "/wss": { target: "http://localhost:4000", secure: false, ws: true }, "/api": { target: "http://localhost:4000", changeOrigin: true, secure: false, ws: false, rewrite: (path) => { const replacedValue = path.replace(/^\/api/, ""); logger.info( `${chalk.grey.bold(getFormattedTimestamp())} ${chalk.cyan.bold("[vite]")} ${chalk.green.bold("[API]")} ${chalk.blue(replacedValue)}` ); return replacedValue; } } }, https: httpsCerts }, preview: { port: 6000, host: true, open: true, https: httpsCerts, proxy: { "/ws": { target: "http://localhost:4000", rewriteWsOrigin: true, secure: false, ws: true }, "/wss": { target: "http://localhost:4000", rewriteWsOrigin: true, secure: false, ws: true }, "/api": { target: "http://localhost:4000", changeOrigin: true, secure: false, ws: false } } }, build: { sourcemap: true, rollupOptions: { output: { manualChunks: { antd: ["antd"], "react-redux": ["react-redux"], redux: ["redux"], lodash: ["lodash"], "@sentry/react": ["@sentry/react"], "@splitsoftware/splitio-react": ["@splitsoftware/splitio-react"], logrocket: ["logrocket"], firebase: [ "@firebase/analytics", "@firebase/app", "@firebase/firestore", "@firebase/auth", "@firebase/messaging" ], markerjs2: ["markerjs2"], "@apollo/client": ["@apollo/client"], "libphonenumber-js": ["libphonenumber-js"], recharts: ["recharts"] } } }, cssMinify: "lightningcss" }, // Strip console/debugger in prod to shrink bundles esbuild: { // drop: mode === "production" ? ["console", "debugger"] : [], legalComments: "none" // Remove license comments in production }, optimizeDeps: { include: [ "react", "react-dom", "antd", "lodash", "@sentry/react", "@apollo/client", "@reduxjs/toolkit", "axios", "react-router-dom", "dayjs", "redux", "react-redux", "@firebase/app", "@firebase/analytics", "@firebase/firestore", "@firebase/auth", "@firebase/messaging", "@firebase/util", "styled-components" ], esbuildOptions: { loader: { ".jsx": "jsx", ".tsx": "tsx" } }, // Force styled-components to be pre-bundled and deduplicated force: mode === "development" }, css: { transformer: "lightningcss", lightningcss: { targets: lightningCssTargets }, preprocessorOptions: { scss: { quietDeps: true } } } }; });