246 lines
No EOL
8.1 KiB
TypeScript
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"),
|
|
},
|
|
],
|
|
},
|
|
}); |