mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2025-11-24 10:30:07 +08:00
248 lines
7.1 KiB
JavaScript
248 lines
7.1 KiB
JavaScript
import { VitePWA } from "vite-plugin-pwa";
|
|
import replace from "vite-plugin-filter-replace";
|
|
import path from "node:path";
|
|
import childProcess from "child_process";
|
|
import { checker } from "vite-plugin-checker";
|
|
// eslint-disable-next-line import/no-unresolved
|
|
import UnpluginInjectPreload from "unplugin-inject-preload/vite";
|
|
import { ViteMinifyPlugin } from "vite-plugin-minify";
|
|
import { sentryVitePlugin } from "@sentry/vite-plugin";
|
|
import { getFontsConig } from "./vite.config";
|
|
import { fontawesomeSubset } from "./vite-plugins/fontawesome-subset";
|
|
import { fontPreview } from "./vite-plugins/font-preview";
|
|
import { envConfig } from "./vite-plugins/env-config";
|
|
import { languageHashes } from "./vite-plugins/language-hashes";
|
|
import { minifyJson } from "./vite-plugins/minify-json";
|
|
import { versionFile } from "./vite-plugins/version-file";
|
|
|
|
function pad(numbers, maxLength, fillString) {
|
|
return numbers.map((number) =>
|
|
number.toString().padStart(maxLength, fillString)
|
|
);
|
|
}
|
|
|
|
const CLIENT_VERSION = (() => {
|
|
const date = new Date();
|
|
const versionPrefix = pad(
|
|
[date.getFullYear(), date.getMonth() + 1, date.getDate()],
|
|
2,
|
|
"0"
|
|
).join(".");
|
|
const versionSuffix = pad([date.getHours(), date.getMinutes()], 2, "0").join(
|
|
"."
|
|
);
|
|
const version = [versionPrefix, versionSuffix].join("_");
|
|
|
|
try {
|
|
const commitHash = childProcess
|
|
.execSync("git rev-parse --short HEAD")
|
|
.toString();
|
|
|
|
return `${version}_${commitHash}`.replace(/\n/g, "");
|
|
} catch (e) {
|
|
return `${version}_unknown-hash`;
|
|
}
|
|
})();
|
|
|
|
/** Enable for font awesome v6 */
|
|
/*
|
|
function sassList(values) {
|
|
return values.map((it) => `"${it}"`).join(",");
|
|
}
|
|
*/
|
|
|
|
/** @type {import("vite").UserConfig} */
|
|
export default {
|
|
plugins: [
|
|
envConfig({ isDevelopment: false, clientVersion: CLIENT_VERSION }),
|
|
languageHashes(),
|
|
fontawesomeSubset(),
|
|
versionFile({ clientVersion: CLIENT_VERSION }),
|
|
fontPreview(),
|
|
checker({
|
|
typescript: {
|
|
tsconfigPath: path.resolve(__dirname, "./tsconfig.json"),
|
|
},
|
|
}),
|
|
ViteMinifyPlugin({}),
|
|
VitePWA({
|
|
// injectRegister: "networkfirst",
|
|
injectRegister: null,
|
|
registerType: "autoUpdate",
|
|
manifest: {
|
|
short_name: "Monkeytype",
|
|
name: "Monkeytype",
|
|
start_url: "/",
|
|
icons: [
|
|
{
|
|
src: "/images/icons/maskable_icon_x512.png",
|
|
sizes: "512x512",
|
|
type: "image/png",
|
|
purpose: "maskable",
|
|
},
|
|
{
|
|
src: "/images/icons/general_icon_x512.png",
|
|
sizes: "512x512",
|
|
type: "image/png",
|
|
purpose: "any",
|
|
},
|
|
],
|
|
background_color: "#323437",
|
|
display: "standalone",
|
|
theme_color: "#323437",
|
|
},
|
|
manifestFilename: "manifest.json",
|
|
workbox: {
|
|
clientsClaim: true,
|
|
cleanupOutdatedCaches: true,
|
|
globIgnores: ["**/.*"],
|
|
globPatterns: [],
|
|
navigateFallback: "",
|
|
runtimeCaching: [
|
|
{
|
|
urlPattern: (options) => {
|
|
const isApi = options.url.hostname === "api.monkeytype.com";
|
|
return options.sameOrigin && !isApi;
|
|
},
|
|
handler: "NetworkFirst",
|
|
options: {},
|
|
},
|
|
{
|
|
urlPattern: (options) => {
|
|
//disable caching for version.json
|
|
return options.url.pathname === "/version.json";
|
|
},
|
|
handler: "NetworkOnly",
|
|
options: {},
|
|
},
|
|
],
|
|
},
|
|
}),
|
|
process.env.SENTRY
|
|
? sentryVitePlugin({
|
|
authToken: process.env.SENTRY_AUTH_TOKEN,
|
|
org: "monkeytype",
|
|
project: "frontend",
|
|
release: {
|
|
name: CLIENT_VERSION,
|
|
},
|
|
applicationKey: "monkeytype-frontend",
|
|
})
|
|
: null,
|
|
replace([
|
|
{
|
|
filter: ["src/ts/firebase.ts"],
|
|
replace: {
|
|
from: `"./constants/firebase-config.ts"`,
|
|
to: `"./constants/firebase-config-live.ts"`,
|
|
},
|
|
},
|
|
{
|
|
filter: ["src/email-handler.html"],
|
|
replace: {
|
|
from: `"./ts/constants/firebase-config"`,
|
|
to: `"./ts/constants/firebase-config-live"`,
|
|
},
|
|
},
|
|
]),
|
|
UnpluginInjectPreload({
|
|
files: [
|
|
{
|
|
outputMatch: /css\/vendor.*\.css$/,
|
|
attributes: {
|
|
as: "style",
|
|
type: "text/css",
|
|
rel: "preload",
|
|
crossorigin: true,
|
|
},
|
|
},
|
|
{
|
|
outputMatch: /.*\.woff2$/,
|
|
attributes: {
|
|
as: "font",
|
|
type: "font/woff2",
|
|
rel: "preload",
|
|
crossorigin: true,
|
|
},
|
|
},
|
|
],
|
|
injectTo: "head-prepend",
|
|
}),
|
|
minifyJson(),
|
|
],
|
|
build: {
|
|
sourcemap: process.env.SENTRY,
|
|
emptyOutDir: true,
|
|
outDir: "../dist",
|
|
assetsInlineLimit: 0, //dont inline small files as data
|
|
rollupOptions: {
|
|
input: {
|
|
monkeytype: path.resolve(__dirname, "src/index.html"),
|
|
email: path.resolve(__dirname, "src/email-handler.html"),
|
|
privacy: path.resolve(__dirname, "src/privacy-policy.html"),
|
|
security: path.resolve(__dirname, "src/security-policy.html"),
|
|
terms: path.resolve(__dirname, "src/terms-of-service.html"),
|
|
404: path.resolve(__dirname, "src/404.html"),
|
|
},
|
|
output: {
|
|
assetFileNames: (assetInfo) => {
|
|
let extType = assetInfo.name.split(".").at(1);
|
|
if (/png|jpe?g|svg|gif|tiff|bmp|ico/i.test(extType)) {
|
|
extType = "images";
|
|
}
|
|
if (/\.(woff|woff2|eot|ttf|otf)$/.test(assetInfo.name)) {
|
|
return `webfonts/[name]-[hash].${extType}`;
|
|
}
|
|
return `${extType}/[name].[hash][extname]`;
|
|
},
|
|
chunkFileNames: "js/[name].[hash].js",
|
|
entryFileNames: "js/[name].[hash].js",
|
|
manualChunks: (id) => {
|
|
if (id.includes("@sentry")) {
|
|
return "vendor-sentry";
|
|
}
|
|
if (id.includes("jquery")) {
|
|
return "vendor-jquery";
|
|
}
|
|
if (id.includes("@firebase")) {
|
|
return "vendor-firebase";
|
|
}
|
|
if (id.includes("monkeytype/packages")) {
|
|
return "monkeytype-packages";
|
|
}
|
|
if (id.includes("node_modules")) {
|
|
return "vendor";
|
|
}
|
|
},
|
|
},
|
|
},
|
|
},
|
|
css: {
|
|
preprocessorOptions: {
|
|
scss: {
|
|
additionalData(source, fp) {
|
|
if (fp.endsWith("index.scss")) {
|
|
/** Enable for font awesome v6 */
|
|
/*
|
|
const fontawesomeClasses = getFontawesomeConfig();
|
|
|
|
//inject variables into sass context
|
|
$fontawesomeBrands: ${sassList(
|
|
fontawesomeClasses.brands
|
|
)};
|
|
$fontawesomeSolid: ${sassList(fontawesomeClasses.solid)};
|
|
*/
|
|
const fonts = `$fonts: (${getFontsConig()});`;
|
|
return `
|
|
//inject variables into sass context
|
|
${fonts}
|
|
|
|
${source}`;
|
|
} else {
|
|
return source;
|
|
}
|
|
},
|
|
},
|
|
},
|
|
},
|
|
};
|