build: refactor build script

main
Jad 2025-12-21 00:25:32 +08:00
parent 8d95184abe
commit 607a3c8719
2 changed files with 106 additions and 43 deletions

142
build.js
View File

@ -1,5 +1,30 @@
import * as esbuild from 'esbuild';
import { cp, mkdir } from 'fs/promises';
import { cpSync, rmSync, existsSync, mkdirSync, watch } from 'node:fs';
import { createRequire } from 'node:module';
import { execSync } from 'child_process';
const require = createRequire(import.meta.url);
const pkg = require('./package.json');
const isProd = process.env.NODE_ENV === 'production';
let _commitHash = null;
const getCommitHash = () => {
if (_commitHash) return _commitHash;
try {
_commitHash = execSync('git rev-parse --short HEAD').toString().trim();
} catch {
_commitHash = 'unknown';
}
return _commitHash;
};
const jsBanner = `/*!
* ${pkg.name} v${pkg.version}+${getCommitHash()}
* ${pkg.description}
* (c) ${new Date().getFullYear()} ${pkg.author}
* ${pkg.repository.url?.replace(/\.git$/, '')}
* Released under the ${pkg.license} License.
*/`;
const userscriptBanner = `// ==UserScript==
// @name Gemini NanoBanana Watermark Remover
@ -20,51 +45,82 @@ const userscriptBanner = `// ==UserScript==
// ==/UserScript==
`;
async function build() {
console.log(`Start Build... ${process.env.NODE_ENV === 'production' ? 'production' : 'development'}\r\n`);
const copyAssetsPlugin = {
name: 'copy-assets',
setup(build) {
build.onEnd(() => {
console.log('📂 Syncing static assets...');
try {
if (!existsSync('dist/i18n')) mkdirSync('dist/i18n', { recursive: true });
cpSync('src/i18n', 'dist/i18n', { recursive: true });
cpSync('public', 'dist', { recursive: true });
} catch (err) {
console.error('❌ Asset copy failed:', err);
}
});
},
};
// Build website - app.js
console.log('Building: dist/app.js');
await esbuild.build({
entryPoints: ['src/app.js'],
bundle: true,
format: 'esm',
outfile: 'dist/app.js',
loader: { '.png': 'dataurl' },
publicPath: '/',
minify: process.env.NODE_ENV === 'production'
});
const commonConfig = {
bundle: true,
loader: { '.png': 'dataurl' },
minify: isProd,
logLevel: 'info',
};
// Build website - i18n.js
console.log('Building: dist/i18n.js');
await esbuild.build({
entryPoints: ['src/i18n.js'],
bundle: true,
format: 'esm',
outfile: 'dist/i18n.js',
minify: process.env.NODE_ENV === 'production'
});
// Build website - app.js
const websiteCtx = await esbuild.context({
...commonConfig,
entryPoints: ['src/app.js'],
outfile: 'dist/app.js',
platform: 'browser',
target: ['es2020'],
banner: { js: jsBanner },
sourcemap: !isProd,
plugins: [copyAssetsPlugin],
});
// Build userscript
console.log('Building: dist/userscript/gemini-watermark-remover.user.js');
await mkdir('dist/userscript', { recursive: true });
await esbuild.build({
entryPoints: ['src/userscript/index.js'],
bundle: true,
format: 'iife',
outfile: 'dist/userscript/gemini-watermark-remover.user.js',
banner: { js: userscriptBanner },
loader: { '.png': 'dataurl' },
minify: false
});
// Build userscript
const userscriptCtx = await esbuild.context({
...commonConfig,
entryPoints: ['src/userscript/index.js'],
format: 'iife',
outfile: 'dist/userscript/gemini-watermark-remover.user.js',
banner: { js: userscriptBanner },
minify: false
});
// Copy static files
console.log('Copying: src/i18n -> dist/i18n');
await cp('src/i18n', 'dist/i18n', { recursive: true });
console.log('Copying: public -> dist');
await cp('public', 'dist', { recursive: true });
console.log(`🚀 Starting build process... [${isProd ? 'PRODUCTION' : 'DEVELOPMENT'}]`);
console.log('\r\n✓ Build complete');
if (existsSync('dist')) rmSync('dist', { recursive: true });
mkdirSync('dist/userscript', { recursive: true });
if (isProd) {
await Promise.all([websiteCtx.rebuild(), userscriptCtx.rebuild()]);
console.log('✅ Build complete!');
process.exit(0);
} else {
await Promise.all([websiteCtx.watch(), userscriptCtx.watch()]);
const watchDir = (dir, dest) => {
let debounceTimer = null;
watch(dir, { recursive: true }, (eventType, filename) => {
if (!filename) return;
if (debounceTimer) clearTimeout(debounceTimer);
debounceTimer = setTimeout(() => {
console.log(`📂 Asset changed: ${filename}`);
try {
cpSync(dir, dest, { recursive: true });
} catch (e) {
console.error('Sync failed:', e);
}
}, 100);
});
};
watchDir('src/i18n', 'dist/i18n');
watchDir('public', 'dist');
console.log('👀 Watching for changes...');
}
build().catch(console.error);

View File

@ -1,6 +1,13 @@
{
"name": "gemini-watermark-remover",
"description": "Automatically removes watermarks from Gemini AI generated images",
"version": "1.0.0",
"author": "journey-ad",
"repository": {
"type": "git",
"url": "https://github.com/journey-ad/gemini-watermark-remover.git"
},
"license": "MIT",
"type": "module",
"scripts": {
"dev": "node build.js",