Migrate Webpack to Vite
Deploy Spot / deploy (push) Successful in 22s

This commit is contained in:
2026-07-26 15:33:07 +02:00
parent fb500f3c34
commit 7da504ca6b
10 changed files with 943 additions and 3809 deletions
+127
View File
@@ -0,0 +1,127 @@
import vue from '@vitejs/plugin-vue';
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { defineConfig } from 'vite';
const ROOT = fileURLToPath(new URL('.', import.meta.url));
const SRC = path.resolve(ROOT, 'src');
const PUBLIC = path.resolve(ROOT, 'public');
export default defineConfig(({ mode }) => {
const isDev = (mode === 'development');
return {
base: './',
publicDir: false,
plugins: [
spotPublicAssets(),
vue()
],
build: {
outDir: PUBLIC,
assetsDir: 'assets',
emptyOutDir: false,
manifest: true,
sourcemap: isDev,
minify: !isDev,
cssMinify: !isDev,
assetsInlineLimit: 1 * 1024,
chunkSizeWarningLimit: 1500,
rolldownOptions: {
input: {
app: path.resolve(SRC, 'app.js')
},
output: {
entryFileNames: isDev ? 'assets/[name].js' : 'assets/[name].[hash].js',
chunkFileNames: isDev ? 'assets/[name].js' : 'assets/[name].[hash].js',
assetFileNames: (assetInfo) => {
const sourceName = assetInfo.names?.[0] || assetInfo.name || 'asset';
const extension = path.extname(sourceName).toLowerCase();
const isImage = ['.png', '.svg', '.jpg', '.jpeg', '.gif', '.webp'].includes(extension);
const folder = isImage ? 'assets/images' : 'assets';
return isDev ? `${folder}/[name][extname]` : `${folder}/[name].[hash][extname]`;
}
}
}
},
resolve: {
extensions: ['.mjs', '.js', '.vue', '.scss', '.json'],
alias: {
'@components': path.resolve(SRC, 'components'),
'@images': path.resolve(SRC, 'images'),
'@scripts': path.resolve(SRC, 'scripts'),
'@styles': path.resolve(SRC, 'styles')
}
},
define: {
__VUE_OPTIONS_API__: 'true',
__VUE_PROD_DEVTOOLS__: 'false',
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: 'false'
}
};
});
function spotPublicAssets() {
return {
name: 'spot-public-assets',
apply: 'build',
buildStart() {
cleanGeneratedAssets();
ensurePublicSymlinks();
}
};
}
function cleanGeneratedAssets() {
fs.rmSync(path.resolve(PUBLIC, '.vite'), { recursive: true, force: true });
fs.rmSync(path.resolve(PUBLIC, 'maplibre'), { recursive: true, force: true });
const assetsDir = path.resolve(PUBLIC, 'assets');
if (fs.existsSync(assetsDir)) {
for (const entry of fs.readdirSync(assetsDir, { withFileTypes: true })) {
const entryPath = path.resolve(assetsDir, entry.name);
if (entry.name === 'images' && entry.isDirectory()) {
cleanImagesDir(entryPath);
}
else {
fs.rmSync(entryPath, { recursive: true, force: true });
}
}
}
fs.mkdirSync(path.resolve(PUBLIC, 'assets', 'images'), { recursive: true });
}
function cleanImagesDir(imagesDir) {
for (const entry of fs.readdirSync(imagesDir, { withFileTypes: true })) {
if (entry.name === 'icons') continue;
fs.rmSync(path.resolve(imagesDir, entry.name), { recursive: true, force: true });
}
}
function ensurePublicSymlinks() {
ensureSymlink('../files', path.resolve(PUBLIC, 'files'));
ensureSymlink('../resources/geo', path.resolve(PUBLIC, 'geo'));
ensureSymlink('../../../src/images/icons', path.resolve(PUBLIC, 'assets', 'images', 'icons'));
}
function ensureSymlink(target, linkPath) {
fs.mkdirSync(path.dirname(linkPath), { recursive: true });
try {
const stats = fs.lstatSync(linkPath);
if (stats.isSymbolicLink()) {
if (fs.readlinkSync(linkPath) === target) return;
fs.unlinkSync(linkPath);
}
else {
throw new Error(`Refusing to replace non-symlink public path: ${linkPath}`);
}
}
catch (error) {
if (error.code !== 'ENOENT') throw error;
}
fs.symlinkSync(target, linkPath);
}