Client-only edits are sent to the browser right after the hydration build, without re-running server functions; SSR rebuilds afterwards and props are re-fetched only when a .server.ts output changed or after fullRebuild. Page requests wait for an in-flight SSR rebuild. The SSR build no longer runs Tailwind, the PostCSS processor is reused across rebuilds, and the watcher debounce drops from 200ms to 50ms. Co-Authored-By: Claude Opus 5.5 <[email protected]>
63 lines
2.3 KiB
JavaScript
63 lines
2.3 KiB
JavaScript
import * as esbuild from "esbuild";
|
|
import postcss from "postcss";
|
|
import tailwindcss from "@tailwindcss/postcss";
|
|
import { readFile } from "fs/promises";
|
|
import path from "path";
|
|
import { existsSync } from "fs";
|
|
import grabDirNames from "../../../utils/grab-dir-names";
|
|
import { log } from "../../../utils/log";
|
|
const { ROOT_DIR } = grabDirNames();
|
|
let error_logged = false;
|
|
// One processor for the whole process, so the Tailwind plugin's internal
|
|
// state survives across rebuilds instead of being recreated per file load.
|
|
let css_processor;
|
|
function grabCSSProcessor() {
|
|
if (!css_processor) {
|
|
css_processor = postcss([tailwindcss()]);
|
|
}
|
|
return css_processor;
|
|
}
|
|
export function createTailwindEsbuildPlugin({ process_css = true, } = {}) {
|
|
return {
|
|
name: process_css ? "tailwindcss" : "css-stub",
|
|
setup(build) {
|
|
build.onLoad({ filter: /\.css$/ }, async (args) => {
|
|
if (!process_css) {
|
|
return { contents: "", loader: "css" };
|
|
}
|
|
try {
|
|
const source = await readFile(args.path, "utf-8");
|
|
const result = await grabCSSProcessor().process(source, {
|
|
from: args.path,
|
|
});
|
|
error_logged = false;
|
|
return { contents: result.css, loader: "css" };
|
|
}
|
|
catch (error) {
|
|
return { errors: [{ text: error.message }] };
|
|
}
|
|
});
|
|
build.onResolve({ filter: /\.css$/ }, async (args) => {
|
|
const css_path = path.resolve(args.resolveDir, args.path.replace(/\@\//g, ROOT_DIR + "/"));
|
|
const does_path_exist = existsSync(css_path);
|
|
if (!does_path_exist && !error_logged) {
|
|
const err_msg = `CSS Error: ${css_path} file does not exist.`;
|
|
log.error(err_msg);
|
|
error_logged = true;
|
|
}
|
|
return {
|
|
path: css_path,
|
|
};
|
|
});
|
|
},
|
|
};
|
|
}
|
|
/**
|
|
* Resolves `.css` imports like the Tailwind plugin but loads them empty.
|
|
*/
|
|
export const cssStubEsbuildPlugin = createTailwindEsbuildPlugin({
|
|
process_css: false,
|
|
});
|
|
const tailwindEsbuildPlugin = createTailwindEsbuildPlugin();
|
|
export default tailwindEsbuildPlugin;
|