Files
2026-09-24 18:06:11 +02:00

75 lines
3.1 KiB
JavaScript

import { defineConfig } from 'vite'
import { resolve } from 'node:path'
const here = (...p) => resolve(import.meta.dirname, ...p)
// Two build targets from one config:
//
// vite build → dist/ the deliverable: tlig.css + fonts,
// no HTML. This is what WordPress
// enqueues.
// vite build --mode demo → demo-dist/ a static demo page that loads that
// stylesheet through a real <link>,
// with the site images beside it.
//
// The second exists because in dev Vite injects CSS through JavaScript, so
// anything with a `transition` animates from its unstyled state on first paint.
// That is a dev artifact, but it makes the demo misrepresent the stylesheet.
// The static build paints once, the way a browser will on the real site.
export default defineConfig(({ mode }) => {
const isDemo = mode === 'demo'
return {
root: 'src',
// Relative asset URLs — a url() in CSS resolves against the stylesheet's
// own location, so the output can be dropped at any path under wp-content
// without rebuilding.
base: './',
// No public directory. It used to point at `site/`, which mirrored the
// live asset tree — but `site/` is now a WordPress install, and a demo
// build would copy the whole of it into demo-dist/. Every image the
// stylesheet needs is a Vite asset under src/images/ instead, which is
// also what makes the bundle resolve at whatever path it is dropped.
publicDir: false,
css: {
devSourcemap: true,
},
build: {
// The build emits straight into the theme, so the theme always runs the
// current stylesheet with no copy step and there is no `dist/` to keep in
// sync. The theme's `assets/` is a build artifact and is not versioned.
outDir: isDemo ? here('demo-dist') : here('site/wp-content/themes/tlig/assets'),
emptyOutDir: true,
sourcemap: true,
cssCodeSplit: false,
rollupOptions: {
// The demo is built from the page; the deliverable from the entry
// module, so no demo markup or demo CSS can reach dist/.
input: isDemo ? here('src/index.html') : here('src/main.js'),
output: {
// Predictable names: WordPress enqueues these paths, so they must not
// change on every build. Fonts keep their own names for the same
// reason — a preload hint in the theme header has to stay valid.
entryFileNames: isDemo ? 'assets/[name]-[hash].js' : 'tlig.js',
assetFileNames: (info) => {
const name = info.names?.[0] ?? info.name ?? ''
if (name.endsWith('.css')) return 'tlig.css'
if (/\.(woff2?|ttf|eot)$/.test(name)) return 'fonts/[name][extname]'
// Stable, unhashed image paths: the theme preloads the parchment,
// so its URL must not change on every build.
if (/\.(webp|png|jpe?g|svg|avif)$/.test(name)) return 'images/[name][extname]'
return 'assets/[name]-[hash][extname]'
},
},
},
},
}
})