/**
* Build config for the v0.5.0 FSE migration (@wordpress/scripts + webpack).
*
* This is now the theme's only build — it fully replaced the old gulp pipeline
* (copy/mixin/build/cssf/js/jsf). It compiles the site-wide stylesheet and both
* JS bundles from npm packages + the bespoke source in src/ (see
* _claude/notes/upgrade-plan.md).
*
* Output layout (output.path = theme root so nothing escapes it):
* - front → js/v4-front.min.js (homepage bundle, overwrites the enqueued path)
* - main → js/v4-script.min.js (site-wide bundle, overwrites the enqueued path)
* - v4-style → v4-style.min.css (theme root — keeps the `style-min` enqueue + font url()s valid)
* - index / other → build/[name].{js,css} (seed + future block view scripts)
*/
const path = require('path');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const BrowserSyncPlugin = require('browser-sync-webpack-plugin');
module.exports = {
entry: {
index: './src/index.js',
// Reproduces gulp `build` → v4-style.min.css (concat of the 5 CSS sources, in order).
'v4-style': './src/legacy-style.js',
// Reproduces gulp `jsf` → homepage JS (jquery + svg-morpheus + front-page.js).
front: './src/front.js',
// Reproduces gulp `js` → site-wide JS (jquery/bootstrap/plugins).
main: './src/main.js',
},
output: {
path: path.resolve(__dirname), // theme root
// The two bundles overwrite their committed, enqueued paths in place (like
// v4-style.min.css does) so nothing needs re-pointing and they ship via git.
// Everything else (the seed, future block scripts) goes under the gitignored build/.
filename: (pathData) => {
const n = pathData.chunk.name;
if (n === 'front') return 'js/v4-front.min.js';
if (n === 'main') return 'js/v4-script.min.js';
return 'build/[name].js';
},
clean: false, // NEVER clean — output.path is the theme root
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: { loader: 'babel-loader' },
},
{
// svg-morpheus ships a bare global `var SVGMorpheus` (no export) — surface it as a
// module export so src/front.js can re-expose it on window for front-page.js.
test: require.resolve('svg-morpheus/compile/minified/svg-morpheus.js'),
loader: 'exports-loader',
options: { type: 'commonjs', exports: 'single SVGMorpheus' },
},
{
// Both css/styles.css (hand-rolled, was styles.scss until Bootstrap was
// removed) and style.css. url:false / import:false → leave url() + @import
// untouched (gulp-concat parity, so relative `fonts/…` paths resolve from
// the theme root). No sass step anymore — the theme has no .scss files.
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
{ loader: 'css-loader', options: { url: false, import: false } },
],
},
],
},
optimization: {
// '...' keeps webpack's default JS minifier (terser); add CSS minification.
minimizer: [
'...',
// discardComments.removeAll matches the old gulp clean-css (specialComments:0).
new CssMinimizerPlugin({
minimizerOptions: { preset: ['default', { discardComments: { removeAll: true } }] },
}),
],
},
plugins: [
// jQuery globals for the bundled source that assumes a global $ (front-page.js
// IIFEs, and the npm jQuery plugins validation/backstretch/lazyload in the main bundle).
new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery' }),
new MiniCssExtractPlugin({
filename: ({ chunk }) =>
chunk.name === 'v4-style' ? 'v4-style.min.css' : 'build/[name].css',
}),
new BrowserSyncPlugin({
host: 'daw.stu',
port: 81,
proxy: 'https://daw.stu',
https: {
key: '/opt/homebrew/etc/httpd/ssl/daw.stu-key.pem',
cert: '/opt/homebrew/etc/httpd/ssl/daw.stu-cert.pem',
},
// Bounce /photo (Lychee) off the proxy and onto the real vhost. The proxy
// rewrites absolute URLs to protocol-relative so navigation stays on :81,
// which turns Lychee's into
// "//daw.stu:81/photo". vue-router strips the origin off with
// /^\w+:\/\/[^\/]+/ -- that needs a scheme, so protocol-relative slips
// through and becomes the router base, doubling every route into
// /photo/photo/. Nothing below watches /photo (it's a separate app with its
// own Vite build), so there's nothing to gain by proxying it.
middleware: [
function bypassLychee(req, res, next) {
if (req.url === '/photo' || req.url.startsWith('/photo/')) {
res.writeHead(302, { Location: 'https://daw.stu' + req.url });
return res.end();
}
return next();
},
],
files: [
'./**/*.php',
'./src/**/*.js',
'./src/**/*.css',
'./templates/**/*.html',
'./parts/**/*.html',
'./patterns/**/*.php',
'./theme.json',
],
ignore: ['node_modules', 'build', 'js/v4-*', '*.min.*'],
open: 'external',
reloadDelay: 50,
injectChanges: true,
notify: false,
// Serve dev responses uncached so a reload always reflects the latest edit
// (no stale browser cache while iterating). Pairs with the `files` watch above,
// which already auto-reloads on .php / template / src changes.
middleware: function (req, res, next) {
res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0');
res.setHeader('Pragma', 'no-cache');
res.setHeader('Expires', '0');
next();
},
}),
],
};