make docker file a little better for prod builds
This commit is contained in:
@@ -113,12 +113,15 @@ RUN if [ -f dist-clients/BackstageCapture.x64.dll ]; then \
|
|||||||
# Keep production build phases separate so BuildKit reports the exact slow or
|
# Keep production build phases separate so BuildKit reports the exact slow or
|
||||||
# failing phase and can cache each completed phase independently.
|
# failing phase and can cache each completed phase independently.
|
||||||
RUN bun run build:css
|
RUN bun run build:css
|
||||||
|
RUN bun run build:web:prod
|
||||||
RUN bun run vendor
|
RUN bun run vendor
|
||||||
RUN MINIFY_CONCURRENCY=4 bun run minify
|
RUN MINIFY_CONCURRENCY=4 bun run minify
|
||||||
RUN bun run build:bundle
|
RUN bun run build:bundle
|
||||||
|
|
||||||
RUN test "$(wc -l < ./public/index.html)" -lt 20 \
|
RUN test "$(wc -l < ./public/index.html)" -lt 20 \
|
||||||
&& test "$(wc -l < ./public/assets/main.js)" -lt 50 \
|
&& test "$(wc -l < ./public/assets/main.js)" -lt 50 \
|
||||||
|
&& test -s ./public/assets/generated/shared-ui-settings.js \
|
||||||
|
&& test ! -e ./public/assets/generated/shared-ui-settings.js.map \
|
||||||
&& test -s ./public/assets/tailwind.css \
|
&& test -s ./public/assets/tailwind.css \
|
||||||
&& test -d ./public/vendor/fontawesome \
|
&& test -d ./public/vendor/fontawesome \
|
||||||
&& test -s ./dist/index.js \
|
&& test -s ./dist/index.js \
|
||||||
|
|||||||
@@ -11,9 +11,10 @@
|
|||||||
"dev": "bun run scripts/dev.ts",
|
"dev": "bun run scripts/dev.ts",
|
||||||
"start": "bun run build && bun dist/index.js",
|
"start": "bun run build && bun dist/index.js",
|
||||||
"build": "bun run build:css && bun run build:web && bun run vendor && bun run build:bundle",
|
"build": "bun run build:css && bun run build:web && bun run vendor && bun run build:bundle",
|
||||||
"build:public:prod": "bun run build:css && bun run build:web && bun run vendor && bun run minify",
|
"build:public:prod": "bun run build:css && bun run build:web:prod && bun run vendor && bun run minify",
|
||||||
"build:bundle": "bun build --production src/index.ts --target bun --outfile dist/index.js && bun build --production src/server/plugin-runtime/worker-host.ts --target bun --outfile dist/server/plugin-runtime/worker-host.js",
|
"build:bundle": "bun build --production src/index.ts --target bun --outfile dist/index.js && bun build --production src/server/plugin-runtime/worker-host.ts --target bun --outfile dist/server/plugin-runtime/worker-host.js",
|
||||||
"build:web": "bun build src/web/shared-ui-settings.ts --outdir public/assets/generated --target browser --format esm --sourcemap=external",
|
"build:web": "bun build src/web/shared-ui-settings.ts --outdir public/assets/generated --target browser --format esm --sourcemap=external",
|
||||||
|
"build:web:prod": "bun -e \"import { rm } from 'node:fs/promises'; await rm('public/assets/generated', { recursive: true, force: true });\" && bun build --production src/web/shared-ui-settings.ts --outdir public/assets/generated --target browser --format esm",
|
||||||
"watch:web": "bun run build:web --watch",
|
"watch:web": "bun run build:web --watch",
|
||||||
"vendor": "bun run scripts/vendor.ts",
|
"vendor": "bun run scripts/vendor.ts",
|
||||||
"build:prod:win": "bun run build:public:prod && bun build --production src/index.ts --compile --target bun-windows-x64 --outfile dist/overlord-server.exe",
|
"build:prod:win": "bun run build:public:prod && bun build --production src/index.ts --compile --target bun-windows-x64 --outfile dist/overlord-server.exe",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#!/usr/bin/env bun
|
#!/usr/bin/env bun
|
||||||
/**
|
/**
|
||||||
* Minify all public JS, CSS, and HTML assets in-place.
|
* Minify first-party public assets and copied vendor assets that do not
|
||||||
|
* already ship minified.
|
||||||
* Uses terser (JS), clean-css (CSS), html-minifier-terser (HTML).
|
* Uses terser (JS), clean-css (CSS), html-minifier-terser (HTML).
|
||||||
*
|
*
|
||||||
* Usage: bun run scripts/minify-public.ts [--dir public]
|
* Usage: bun run scripts/minify-public.ts [--dir public]
|
||||||
@@ -55,13 +56,13 @@ async function collectFiles(dir: string, exts: Set<string>): Promise<string[]> {
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function minifyJS(filePath: string) {
|
async function minifyJS(filePath: string, isModule = true) {
|
||||||
const src = await Bun.file(filePath).text();
|
const src = await Bun.file(filePath).text();
|
||||||
const result = await terserMinify(src, {
|
const result = await terserMinify(src, {
|
||||||
compress: { passes: 2, drop_console: false, ecma: 2020 },
|
compress: { passes: 2, drop_console: false, ecma: 2020 },
|
||||||
mangle: { toplevel: false },
|
mangle: { toplevel: false },
|
||||||
format: { ecma: 2020 },
|
format: { ecma: 2020 },
|
||||||
module: true,
|
module: isModule,
|
||||||
});
|
});
|
||||||
if (result.code && result.code.length < src.length) {
|
if (result.code && result.code.length < src.length) {
|
||||||
stats.savedBytes += src.length - result.code.length;
|
stats.savedBytes += src.length - result.code.length;
|
||||||
@@ -108,19 +109,60 @@ async function runPool<T>(
|
|||||||
await Promise.all(workers);
|
await Promise.all(workers);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect all files
|
const vendorDir = path.join(publicDir, "vendor");
|
||||||
|
const vendorRoots = [
|
||||||
|
"msgpackr",
|
||||||
|
"codemirror",
|
||||||
|
"chart.js",
|
||||||
|
"gridstack",
|
||||||
|
"hotwired",
|
||||||
|
"xterm",
|
||||||
|
"inter",
|
||||||
|
"jetbrains-mono",
|
||||||
|
];
|
||||||
|
|
||||||
|
async function collectVendorFiles(exts: Set<string>): Promise<string[]> {
|
||||||
|
const results: string[] = [];
|
||||||
|
for (const root of vendorRoots) {
|
||||||
|
const dir = path.join(vendorDir, root);
|
||||||
|
try {
|
||||||
|
results.push(...(await collectFiles(dir, exts)));
|
||||||
|
} catch (error: any) {
|
||||||
|
if (error?.code !== "ENOENT") throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isVendorModule(filePath: string): boolean {
|
||||||
|
const normalized = filePath.replaceAll("\\", "/");
|
||||||
|
return normalized.endsWith(".mjs") ||
|
||||||
|
normalized.includes("/hotwired/") ||
|
||||||
|
normalized.endsWith("/chart.esm.js");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect all files.
|
||||||
const jsFiles = await collectFiles(path.join(publicDir, "assets"), new Set([".js"]));
|
const jsFiles = await collectFiles(path.join(publicDir, "assets"), new Set([".js"]));
|
||||||
const cssFiles = await collectFiles(path.join(publicDir, "assets"), new Set([".css"]));
|
const cssFiles = await collectFiles(path.join(publicDir, "assets"), new Set([".css"]));
|
||||||
const htmlFiles = await collectFiles(publicDir, new Set([".html"]));
|
const htmlFiles = await collectFiles(publicDir, new Set([".html"]));
|
||||||
|
const vendorJsFiles = await collectVendorFiles(new Set([".js", ".mjs"]));
|
||||||
|
const vendorCssFiles = await collectVendorFiles(new Set([".css"]));
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
`Minifying ${jsFiles.length} JS, ${cssFiles.length} CSS, ${htmlFiles.length} HTML files ` +
|
`Minifying ${jsFiles.length + vendorJsFiles.length} JS, ` +
|
||||||
|
`${cssFiles.length + vendorCssFiles.length} CSS, ${htmlFiles.length} HTML files ` +
|
||||||
`(concurrency=${minifyConcurrency})...`,
|
`(concurrency=${minifyConcurrency})...`,
|
||||||
);
|
);
|
||||||
|
|
||||||
const jobs = [
|
const jobs = [
|
||||||
...jsFiles.map((file) => ({ kind: "JS", file, minify: minifyJS })),
|
...jsFiles.map((file) => ({ kind: "JS", file, minify: minifyJS })),
|
||||||
|
...vendorJsFiles.map((file) => ({
|
||||||
|
kind: "JS",
|
||||||
|
file,
|
||||||
|
minify: (filePath: string) => minifyJS(filePath, isVendorModule(filePath)),
|
||||||
|
})),
|
||||||
...cssFiles.map((file) => ({ kind: "CSS", file, minify: minifyCSS })),
|
...cssFiles.map((file) => ({ kind: "CSS", file, minify: minifyCSS })),
|
||||||
|
...vendorCssFiles.map((file) => ({ kind: "CSS", file, minify: minifyCSS })),
|
||||||
...htmlFiles.map((file) => ({ kind: "HTML", file, minify: minifyHTML })),
|
...htmlFiles.map((file) => ({ kind: "HTML", file, minify: minifyHTML })),
|
||||||
];
|
];
|
||||||
await runPool(jobs, minifyConcurrency, async ({ kind, file, minify }) => {
|
await runPool(jobs, minifyConcurrency, async ({ kind, file, minify }) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user