frontend/vite.config.ts

246 lines
6.7 KiB
TypeScript
Raw Normal View History

2022-01-01 14:24:06 +01:00
/// <reference types="vitest" />
import {defineConfig, type PluginOption, loadEnv} from 'vite'
import vue from '@vitejs/plugin-vue'
2021-10-07 13:59:10 +02:00
import legacyFn from '@vitejs/plugin-legacy'
import {URL, fileURLToPath} from 'node:url'
import {dirname, resolve} from 'node:path'
import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite'
import {VitePWA} from 'vite-plugin-pwa'
import VitePluginInjectPreload from 'vite-plugin-inject-preload'
import {visualizer} from 'rollup-plugin-visualizer'
2022-05-22 16:20:06 +02:00
import viteSentry, {type ViteSentryPluginOptions} from 'vite-plugin-sentry'
import svgLoader from 'vite-svg-loader'
import postcssPresetEnv from 'postcss-preset-env'
import postcssEasings from 'postcss-easings'
import postcssEasingGradients from 'postcss-easing-gradients'
2022-04-10 02:40:15 +02:00
const pathSrc = fileURLToPath(new URL('./src', import.meta.url))
2022-05-22 16:20:06 +02:00
import {VERSION} from './src/version.json'
// the @use rules have to be the first in the compiled stylesheets
const PREFIXED_SCSS_STYLES = `@use "sass:math";
@import "${pathSrc}/styles/common-imports";`
2021-10-07 13:59:10 +02:00
const isModernBuild = Boolean(process.env.BUILD_MODERN_ONLY)
const legacy = isModernBuild
? undefined
2022-05-22 16:20:06 +02:00
: legacyFn()
2021-10-07 13:59:10 +02:00
2022-04-10 02:40:15 +02:00
console.log(isModernBuild
? 'Building "modern-only" build'
: 'Building "legacy" build with "@vitejs/plugin-legacy"',
2022-04-10 02:40:15 +02:00
)
2021-10-07 13:59:10 +02:00
2022-05-22 16:20:06 +02:00
/*
** Configure sentry plugin
*/
function getSentryConfig(env: ImportMetaEnv): ViteSentryPluginOptions {
return {
skipEnvironmentCheck: true,
url: 'https://sentry.io',
authToken: env.SENTRY_AUTH_TOKEN,
org: env.SENTRY_ORG,
project: env.SENTRY_PROJECT,
release: VERSION,
cleanSourcemapsAfterUpload: true,
legacyErrorHandlingMode: true,
2022-05-22 16:20:06 +02:00
deploy: {
env: env.MODE,
2022-05-22 16:20:06 +02:00
},
setCommits: {
auto: true,
2023-06-18 16:04:42 +02:00
ignoreMissing: true,
2022-05-22 16:20:06 +02:00
},
sourceMaps: {
include: ['./dist/assets'],
ignore: ['node_modules'],
urlPrefix: '~/assets',
},
}
}
/**
* @param fontNames Array of the file names of the fonts without axis and hash suffixes
*/
function createFontMatcher(fontNames: string[]) {
// The `match` option for the files of VitePluginInjectPreload
// matches the _output_ files.
// Since we only want to mach variable fonts, we exploit here the fact
2023-02-02 18:17:19 +01:00
// that we added the `wght` term to indicate the variable weight axis.
// The format is something like:
// `/assets/OpenSans-Italic_wght__c9a8fe68-5f21f1e7.woff2`
// see: https://regex101.com/r/UgUWr1/1
return new RegExp(`^.+\\/(${fontNames.join('|')})_wght__[a-z1-9]{8}-[a-z1-9]{8}\\.woff2$`)
}
2022-04-10 02:40:15 +02:00
// https://vitejs.dev/config/
export default defineConfig(({mode}) => {
// Load env file based on `mode` in the current working directory.
// Set the third parameter to '' to load all env regardless of the `VITE_` prefix.
// https://vitejs.dev/config/#environment-variables
const env = loadEnv(mode, process.cwd(), '')
return {
base: env.VIKUNJA_FRONTEND_BASE,
// https://vitest.dev/config/
test: {
environment: 'happy-dom',
2023-04-12 16:14:10 +02:00
'vitest.commandLine': 'pnpm test:unit',
},
css: {
preprocessorOptions: {
scss: {
additionalData: PREFIXED_SCSS_STYLES,
charset: false, // fixes "@charset" must be the first rule in the file" warnings
},
},
postcss: {
plugins: [
postcssEasings(),
postcssEasingGradients(),
postcssPresetEnv({
// Since postcss-preset-env v8.0.0 the 'enableClientSidePolyfills' option is disabled by default.
// This is the list of features that require a client side library:
// https://github.com/csstools/postcss-plugins/tree/main/plugin-packs/postcss-preset-env#plugins-that-need-client-library
// Since we only use 'focus-within-pseudo-class' we have to force enable
// that plugin now manually in order to keep the browser support as it was.
// See also './src/polyfills.ts'
features: {
'focus-within-pseudo-class': true,
2023-03-29 13:31:20 +02:00
'has-pseudo-class': true,
},
}),
],
},
2023-02-02 18:17:19 +01:00
},
plugins: [
vue({
reactivityTransform: true,
script: {
propsDestructure: true,
},
}),
legacy,
svgLoader({
// Since the svgs are already manually optimized via https://jakearchibald.github.io/svgomg/
// we don't need to optimize them again.
svgo: false,
}),
VueI18nPlugin({
// TODO: only install needed stuff
// Whether to install the full set of APIs, components, etc. provided by Vue I18n.
// By default, all of them will be installed.
fullInstall: true,
include: resolve(dirname(pathSrc), './src/i18n/lang/**'),
}),
// https://github.com/Applelo/vite-plugin-inject-preload
VitePluginInjectPreload({
files: [{
match: createFontMatcher(['Quicksand', 'OpenSans', 'OpenSans-Italic']),
attributes: {crossorigin: 'anonymous'},
}],
injectTo: 'custom',
}),
VitePWA({
srcDir: 'src',
filename: 'sw.ts',
strategies: 'injectManifest',
injectRegister: false,
manifest: {
name: 'Vikunja',
short_name: 'Vikunja',
theme_color: '#1973ff',
icons: [
{
src: './images/icons/android-chrome-192x192.png',
sizes: '192x192',
type: 'image/png',
},
{
src: './images/icons/android-chrome-512x512.png',
sizes: '512x512',
type: 'image/png',
},
{
src: './images/icons/icon-maskable.png',
sizes: '1024x1024',
type: 'image/png',
purpose: 'maskable',
},
],
start_url: '.',
display: 'standalone',
background_color: '#000000',
shortcuts: [
{
name: 'Overview',
url: '/',
},
{
name: 'Namespaces And Projects Overview',
short_name: 'Namespaces & Projects',
url: '/namespaces',
},
{
name: 'Tasks Next Week',
short_name: 'Next Week',
url: '/tasks/by/week',
},
{
name: 'Tasks Next Month',
short_name: 'Next Month',
url: '/tasks/by/month',
},
{
name: 'Teams Overview',
short_name: 'Teams',
url: '/teams',
},
],
},
}),
2022-05-22 16:20:06 +02:00
viteSentry(getSentryConfig(env)),
],
resolve: {
alias: [
{
find: '@',
replacement: pathSrc,
},
2021-07-25 16:02:49 +02:00
],
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'],
2023-02-02 18:17:19 +01:00
},
server: {
host: '127.0.0.1', // see: https://github.com/vitejs/vite/pull/8543
port: 4173,
strictPort: true,
},
output: {
manualChunks: {
// by putting tracking related stuff in a separated file we try to prevent unwanted blocking from ad-blockers
sentry: ['./src/sentry.ts', '@sentry/vue', '@sentry/tracing'],
},
},
build: {
target: 'esnext',
2022-05-22 16:20:06 +02:00
// required for sentry debugging: tells vite to create source maps
sourcemap: true,
rollupOptions: {
plugins: [
visualizer({
filename: 'stats.html',
gzipSize: true,
// template: 'sunburst',
// brotliSize: true,
}) as PluginOption,
2023-02-02 18:17:19 +01:00
],
},
},
}
})