If t helps, here is is my own Esbuild setup, but i do use SCSS. you can sinplify it a bit if you roll with vanilla css. This iconfig is bascially my starting point for any project. Note that you can have multiple entry points in the css and js blocks. I would normally do that based on template names so they get auto load it, but in the case of blocks, you can multiple entry points for the JS / CSS needed for each block instead.
import * as dotenv from "dotenv";
dotenv.config();
import * as esbuild from "esbuild";
import postcss from "postcss";
import autoprefixer from "autoprefixer";
import { sassPlugin } from "esbuild-sass-plugin";
import browserSync from "browser-sync";
import copyStaticFiles from "esbuild-copy-static-files";
// ======================================================================
// Configuration
// ======================================================================
// Local domain name fro browserSync
const domain = process.env.LOCAL;
// Common esbuild options
let commonOptions = {
outdir: "public/assets",
bundle: process.env.NODE_ENV === "development" ? false : true,
minify: process.env.NODE_ENV === "development" ? false : true,
sourcemap: process.env.NODE_ENV === "development" ? false : true,
plugins: [
sassPlugin({
async transform(source) {
const { css } = await postcss([autoprefixer]).process(source, {
from: undefined, // This is needed to prevent postcss from trying to resolve the file path
});
return css;
},
}),
copyStaticFiles({
src: "./src/static",
dest: "./public/assets/",
preserveTimestamps: true,
recursive: true,
}),
],
};
// CSS esbuild options
let cssOptions = {
entryPoints: {
"css/site": "./src/scss/site.scss",
},
...commonOptions,
};
// JS esbuild options
let jsOptions = {
entryPoints: {
"js/site": "./src/js/site.js",
},
...commonOptions,
};
// ======================================================================
// Development Build
// ======================================================================
if (process.env.NODE_ENV === "development") {
let js = await esbuild.context(jsOptions);
let css = await esbuild.context(cssOptions);
await js.watch();
await css.watch();
const browserSyncInstance = browserSync.create();
browserSyncInstance.init({
proxy: domain, // Set the proxy to the valet domain
open: "local", // Automatically open the valet domain in the browser
reloadOnRestart: true, // Reload the browser when we restart the server
notify: true, // I don't want to see the BrowserSync notification in the browser
ui: false, // Disable the BrowserSync UI
snippetOptions: {
// This solves https://github.com/BrowserSync/browser-sync/issues/1600
rule: {
match: /<\/head>/u,
fn(snippet, match) {
const {
groups: { src },
} = /src='(?<src>[^']+)'/u.exec(snippet);
return `<script src="${src}" async></script>${match}`;
},
},
},
});
browserSyncInstance
.watch([
"public/assets/js/**/*.js",
"public/assets/css/**/*.css",
"public/site/**/*.php",
"public/content/**/*.txt",
])
.on("change", browserSyncInstance.reload);
console.log("Watching assets...");
}
// ======================================================================
// Production Build
// ======================================================================
if (process.env.NODE_ENV === "production") {
await esbuild.build(jsOptions);
await esbuild.build(cssOptions);
console.log("Assets built!");
}
I use dot env to trigger whether stuff gets minified or not. The .env file just has this in it
LOCAL = "yourlocaldomain.test"
I use Herd for local development.