front/vite.config.mjs
Rama master · réplica de lectura del repositorio original.
import { defineConfig, loadEnv, transformWithOxc } from 'vite';
import preact from '@preact/preset-vite';
import { viteStaticCopy } from 'vite-plugin-static-copy';
import { patchCssModules } from 'vite-css-modules';
import { readFileSync } from 'fs';
import { dirname, resolve } from 'path';
import { fileURLToPath } from 'url';
import { preactCliCssModules } from './vite-plugins/preact-cli-css-modules.js';
import { preactAsyncRoutes, getRouteChunkName } from './vite-plugins/preact-async-routes.js';
import { serverCommonjsInterop } from './vite-plugins/server-commonjs-interop.js';
const FRONT_ROOT = dirname(fileURLToPath(import.meta.url));
const SRC_ROOT = resolve(FRONT_ROOT, 'src');
// The released Gladys version, from the same root package.json field the
// server reads at startup (server/lib/system/system.init.js). The hosted
// Gladys Plus front is built from the release tag, so baking it in lets the
// front detect an instance lagging behind (see utils/instanceVersion.js).
const GLADYS_VERSION = JSON.parse(readFileSync(resolve(FRONT_ROOT, '../package.json'), 'utf8')).version;
function treatJsFilesAsJsx() {
return {
name: 'treat-js-files-as-jsx',
enforce: 'pre',
async transform(code, id) {
if (!/\/src\/.*\.js($|\?)/.test(id)) {
return null;
}
return transformWithOxc(code, id, {
lang: 'jsx',
jsx: {
runtime: 'automatic',
importSource: 'preact'
}
});
}
};
}
const ENV_KEYS = [
'GLADYS_GATEWAY_API_URL',
'LOCAL_API_URL',
'DEMO_MODE',
'DEMO_REQUEST_TIME',
'WEBSOCKET_URL',
'GATEWAY_MODE',
'STRIPE_API_KEY',
'ENEDIS_FORCE_USAGE_POINTS'
];
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd(), '');
const processEnvDefine = ENV_KEYS.reduce((definitions, key) => {
// JSON.stringify(undefined) is not a string: replace unset variables with
// the literal `undefined` so `process.env.X` expressions stay valid code.
definitions[`process.env.${key}`] = env[key] === undefined ? 'undefined' : JSON.stringify(env[key]);
return definitions;
}, {});
const plugins = [
serverCommonjsInterop(),
patchCssModules({ exportMode: 'both' }),
preactAsyncRoutes({ srcRoot: SRC_ROOT }),
treatJsFilesAsJsx(),
preactCliCssModules(),
preact(),
viteStaticCopy({
targets: [
// The directory structure is preserved: strip `src/assets/` so files land
// in build/assets/<sub-folder>/ (not build/assets/src/assets/).
{ src: 'src/assets/**/*', dest: 'assets', rename: { stripBase: 2 } },
{ src: 'src/manifest.json', dest: '.', rename: { stripBase: true } }
]
})
];
return {
plugins,
resolve: {
alias: {
react: 'preact/compat',
'react-dom/test-utils': 'preact/test-utils',
'react-dom': 'preact/compat',
'/assets': resolve(FRONT_ROOT, 'src/assets')
}
},
define: {
'process.env.NODE_ENV': JSON.stringify(mode === 'production' ? 'production' : 'development'),
'process.env.GLADYS_FRONT_VERSION': JSON.stringify(GLADYS_VERSION),
...processEnvDefine
},
server: {
port: 1444,
strictPort: true,
// preact-cli exposed the dev server on the network (0.0.0.0): keep that
// behavior so the dev front stays reachable from another device (tablet,
// phone) or through WSL2 port forwarding. Vite only binds localhost by default.
host: true,
// The server advertises a configurable name on the local network with mDNS,
// so any ".local" host must be allowed, not just the default one.
allowedHosts: ['.local'],
fs: {
allow: ['..']
},
// Transform the whole app on startup instead of on first request:
// the app is one large SPA and every page load pulls in most of it.
warmup: {
clientFiles: ['./src/main.jsx']
}
},
preview: {
port: 8080
},
optimizeDeps: {
// Injected by the preact-async-routes plugin: the dependency scanner cannot
// discover it, and a dependency discovered after startup makes the dev server
// reload every open page (breaks Cypress runs).
include: ['@preact/async-loader/async.js'],
rolldownOptions: {
moduleTypes: {
'.js': 'jsx'
}
}
},
build: {
outDir: 'build',
// preact-cli shipped a legacy nomodule bundle next to the modern one.
// Vite only emits one bundle: lower its floor so older wall-mounted
// tablets (Safari 13 / old Chromium webviews) keep working.
target: ['es2019', 'chrome79', 'edge79', 'firefox72', 'safari13'],
sourcemap: true,
cssMinify: 'esbuild',
rolldownOptions: {
output: {
codeSplitting: {
groups: [
{
// Rolldown moves modules shared with lazy routes into their own chunk, whose CSS is
// linked before index.css: keep the theme, the global styles and the dashboard
// overrides together so the dashboard overrides still come after Tabler.
name: 'app-styles',
test: /(@gladysassistant\/theme-optimized\/|\/src\/style\/|\/src\/routes\/dashboard\/style\.css)/
}
]
},
chunkFileNames: chunkInfo => {
// Name route chunks after their route path (like preact-cli did),
// e.g. src/routes/dashboard/index.js -> assets/route-dashboard.chunk.<hash>.js
const facadeModuleId = (chunkInfo.facadeModuleId || '').split('?')[0];
const routeChunkName = facadeModuleId ? getRouteChunkName(facadeModuleId, SRC_ROOT) : null;
if (routeChunkName) {
return `assets/${routeChunkName}.chunk.[hash].js`;
}
return 'assets/[name].chunk.[hash].js';
}
}
}
}
};
});