ldc-gen-game-web/vite.config.ts
2026-04-15 11:21:52 +02:00

246 lines
No EOL
8.1 KiB
TypeScript

import basicSsl from "@vitejs/plugin-basic-ssl";
import vue from "@vitejs/plugin-vue";
import laravel from "laravel-vite-plugin";
import path from "path";
import postcssDiscard from "postcss-discard-comments";
import copy from "rollup-plugin-copy";
import { defineConfig } from "vite";
import babel from "vite-plugin-babel";
import checker from "vite-plugin-checker";
import eslint from "vite-plugin-eslint";
import stylelint from "vite-plugin-stylelint";
import fs from "fs";
/** @var {string} buildTarget Build front themes (fo) or shared backend (bo). */
const buildTarget = process.env.VITE_BUILD_TARGET ?? null;
/** @var {string} currentTheme Target theme to build. */
const currentTheme = process.env.VITE_CURRENT_THEME ?? null;
/** @var {string} themesDir Path of all front themes. */
const themesDir = path.resolve(__dirname, "resources/theme");
/** @var {string[]} themesToBuild List of themes to build. */
let themesToBuild: string[] = [];
if (buildTarget === "fo") {
if (!currentTheme) throw new Error("A target theme must be set when building front.");
const themePath = path.join(themesDir, currentTheme);
if (!fs.existsSync(themePath)) throw new Error(`Theme folder "${themePath}" does not exist.`);
themesToBuild = [currentTheme];
} else if (buildTarget === "bo") {
themesToBuild = [];
} else {
themesToBuild = fs
.readdirSync(themesDir)
.filter((f) => fs.statSync(path.join(themesDir, f)).isDirectory());
}
/** @var {string} buildDirectory Output build directory. */
const buildDirectory =
buildTarget === "fo" && currentTheme
? `${currentTheme}/build`
: "build";
/** @var {string} buildDirectory Output directory. */
const outDir = path.resolve(__dirname, `public/${buildDirectory}`);
/** @var {string[]} laravelInputs List of files to build. */
const laravelInputs: string[] = [];
if (buildTarget !== "fo") {
laravelInputs.push(
"resources/sass/bo.scss",
"resources/ts/bo.ts"
);
}
if (buildTarget !== "bo") {
themesToBuild.forEach((theme) => {
laravelInputs.push(
`resources/theme/${theme}/sass/mail-theme.scss`,
`resources/theme/${theme}/sass/fo.scss`,
`resources/theme/${theme}/ts/fo.ts`
);
});
}
/** @var {{ src: string[]; dest: string; }[]} copyTargets List of files to copy. */
const copyTargets = [] as { src: string[]; dest: string; }[];
if (buildTarget !== "fo") {
copyTargets.push({
src: [
"resources/favicons/android-chrome-192x192.png",
"resources/favicons/android-chrome-512x512.png",
"resources/favicons/apple-touch-icon.png",
"resources/favicons/browserconfig.xml",
"resources/favicons/favicon-16x16.png",
"resources/favicons/favicon-32x32.png",
"resources/favicons/favicon.ico",
"resources/favicons/mstile-150x150.png",
"resources/favicons/safari-pinned-tab.svg",
"resources/favicons/site.webmanifest",
].map(path.normalize),
dest: path.normalize("public/"),
});
}
if (buildTarget !== "bo") {
themesToBuild.forEach((theme) =>
copyTargets.push({
src: [
`resources/theme/${theme}/favicons/android-chrome-192x192.png`,
`resources/theme/${theme}/favicons/android-chrome-512x512.png`,
`resources/theme/${theme}/favicons/apple-touch-icon.png`,
`resources/theme/${theme}/favicons/browserconfig.xml`,
`resources/theme/${theme}/favicons/favicon-16x16.png`,
`resources/theme/${theme}/favicons/favicon-32x32.png`,
`resources/theme/${theme}/favicons/favicon.ico`,
`resources/theme/${theme}/favicons/mstile-150x150.png`,
`resources/theme/${theme}/favicons/safari-pinned-tab.svg`,
`resources/theme/${theme}/favicons/site.webmanifest`,
].map(path.normalize),
dest: path.normalize(`public/${theme}`),
})
);
}
/** @var {string} eslintThemeGlobs Files to check for eslint validations. */
const eslintThemeGlobs = themesToBuild
.map((theme) => `"./resources/theme/${theme}/ts/*"`)
.join(" ");
/** @var {string} stylelintThemeGlobs Files to check for stylelint validations. */
const stylelintThemeGlobs = themesToBuild
.map((theme) => `./resources/theme/${theme}/sass/**/*.scss`)
.join(" ");
export default defineConfig({
build: {
outDir,
emptyOutDir: true,
sourcemap: process.env.NODE_ENV === "local" ? "inline" : false,
rollupOptions: {
output: {
entryFileNames: `assets/${
process.env.NODE_ENV === "local" ? "[name]-" : ""
}[hash].js`,
chunkFileNames: `assets/${
process.env.NODE_ENV === "local" ? "[name]-" : ""
}[hash].js`,
assetFileNames: (chunk) => {
if (
String(chunk.name).endsWith("mail-theme.scss") ||
chunk.name === "mail-theme.css"
) {
return "vendor/mail/html/themes/default.[ext]";
}
return `assets/${
process.env.NODE_ENV === "local" ? "[name]-" : ""
}[hash].[ext]`;
},
},
},
},
css: {
preprocessorOptions: {
scss: {
quietDeps: true,
},
},
devSourcemap: process.env.NODE_ENV === "local",
postcss: {
map: {
inline: true,
},
plugins: [
postcssDiscard({
removeAll: true,
}),
],
},
},
plugins: [
basicSsl(),
checker({
enableBuild: true,
vueTsc: {
root: ".",
tsconfigPath: "tsconfig.json",
},
typescript: {
root: ".",
tsconfigPath: "tsconfig.json",
},
eslint: {
lintCommand: `eslint --quiet -c .eslintrc.json "./resources/ts/*" ${eslintThemeGlobs}`.trim(),
},
stylelint: {
lintCommand: `stylelint --quiet -c .stylelintrc.json --fix ./resources/sass/**/*.scss ${stylelintThemeGlobs}`.trim(),
},
}),
laravel({
input: laravelInputs,
refresh: true,
buildDirectory,
}),
copy({
targets: copyTargets,
copyOnce: true,
verbose: true,
}),
stylelint({
dev: false,
build: true,
cache: false,
chokidar: true,
include: [
"**/resources/sass/**/*.scss",
"**/resources/sass/**/*.css",
],
exclude: ["node_modules", "vendor"],
lintOnStart: false,
emitError: true,
emitWarning: true,
emitErrorAsWarning: false,
emitWarningAsError: true,
}),
eslint({
cache: false,
extensions: ["js", "ts"],
include: "**/*.ts",
exclude: ["node_modules", "vendor"],
lintOnStart: false,
emitWarning: true,
emitError: true,
failOnWarning: false,
failOnError: false,
}),
babel({
babelConfig: {
targets: "last 3 version, not dead, >0.3%",
},
}),
vue({
isProduction: process.env.NODE_ENV !== "local",
exclude: ["node_modules", "vendor"],
}),
],
resolve: {
preserveSymlinks: true,
extensions: ["*", ".js", ".ts", ".vue"],
alias: [
{
find: "vue",
replacement: "vue/dist/vue.runtime.esm-bundler.js",
},
{
find: "@",
replacement: "/resources/assets",
},
{
find: "~",
replacement: path.resolve(__dirname, "./node_modules"),
},
],
},
});