diff --git a/esbuild.mjs b/esbuild.mjs index 2d18ae3a..30480e0c 100644 --- a/esbuild.mjs +++ b/esbuild.mjs @@ -3,7 +3,7 @@ import * as esbuild from 'esbuild' import fs from 'fs' // import htmlPlugin from '@chialab/esbuild-plugin-html' import server from './server.js' -import { clients, plugins } from './scripts/esbuildPlugins.mjs' +import { clients, plugins, setSingleFileBuild } from './scripts/esbuildPlugins.mjs' import { generateSW } from 'workbox-build' import { getSwAdditionalEntries } from './scripts/build.js' import { build } from 'esbuild' @@ -11,7 +11,11 @@ import { build } from 'esbuild' //@ts-ignore try { await import('./localSettings.mjs') } catch { } -fs.writeFileSync('dist/index.html', fs.readFileSync('index.html', 'utf8').replace('', ''), 'utf8') +const singleFileBuild = false + +setSingleFileBuild(singleFileBuild) + +fs.writeFileSync('./dist/index.html', fs.readFileSync('index.html', 'utf8').replace('', ''), 'utf8') const watch = process.argv.includes('--watch') || process.argv.includes('-w') const prod = process.argv.includes('--prod') diff --git a/prismarine-viewer/esbuild.mjs b/prismarine-viewer/esbuild.mjs index 91b787db..900895ad 100644 --- a/prismarine-viewer/esbuild.mjs +++ b/prismarine-viewer/esbuild.mjs @@ -6,6 +6,7 @@ import * as esbuild from 'esbuild' import { polyfillNode } from 'esbuild-plugin-polyfill-node' import path, { dirname, join } from 'path' import { fileURLToPath } from 'url' +import { spawn } from 'child_process' const dev = process.argv.includes('-w') @@ -22,17 +23,20 @@ fs.copyFileSync(join(__dirname, 'playground.html'), join(__dirname, 'public/inde fsExtra.copySync(mcDataPath, join(__dirname, 'public/mc-data')) const availableVersions = fs.readdirSync(mcDataPath).map(ver => ver.replace('.js', '')) +const headlessBuild = process.argv.includes('--headless') +let prevExec + /** @type {import('esbuild').BuildOptions} */ const buildOptions = { bundle: true, - entryPoints: [join(__dirname, './examples/playground.ts')], + entryPoints: [join(__dirname, headlessBuild ? './examples/headless.js' : './examples/playground.ts')], // target: ['es2020'], // logLevel: 'debug', logLevel: 'info', - platform: 'browser', + platform: headlessBuild ? 'node' : 'browser', sourcemap: dev ? 'inline' : false, minify: !dev, - outfile: join(__dirname, 'public/playground.js'), + outfile: join(__dirname, headlessBuild ? 'public/headless.js' : 'public/playground.js'), mainFields: [ 'browser', 'module', 'main' ], @@ -48,42 +52,53 @@ const buildOptions = { stream: 'stream-browserify', net: 'net-browserify', }, + external: headlessBuild ? ['minecraft-data'] : [], inject: [], metafile: true, loader: { '.png': 'dataurl', }, plugins: [ - { - name: 'minecraft-data', + ...headlessBuild ? [{ + name: 'starter', setup (build) { - build.onLoad({ - filter: /minecraft-data[\/\\]data.js$/, - }, () => { - const defaultVersionsObj = {} - return { - contents: `window.mcData ??= ${JSON.stringify(defaultVersionsObj)};module.exports = { pc: window.mcData }`, - loader: 'js', - } - }) - build.onEnd((e) => { - if (e.errors.length) return - fs.writeFileSync(join(__dirname, 'public/metafile.json'), JSON.stringify(e.metafile), 'utf8') + prevExec?.kill() + prevExec = spawn(`node`, [join(__dirname, 'public/headless.js')], { + stdio: 'inherit' }) } - }, - polyfillNode({ - polyfills: { - fs: false, - crypto: false, - events: false, - http: false, - stream: false, - buffer: false, - perf_hooks: false, - net: false, + }] : [ + { + name: 'minecraft-data', + setup (build) { + build.onLoad({ + filter: /minecraft-data[\/\\]data.js$/, + }, () => { + const defaultVersionsObj = {} + return { + contents: `window.mcData ??= ${JSON.stringify(defaultVersionsObj)};module.exports = { pc: window.mcData }`, + loader: 'js', + } + }) + build.onEnd((e) => { + if (e.errors.length) return + fs.writeFileSync(join(__dirname, 'public/metafile.json'), JSON.stringify(e.metafile), 'utf8') + }) + } }, - }) + polyfillNode({ + polyfills: { + fs: false, + crypto: false, + events: false, + http: false, + stream: false, + buffer: false, + perf_hooks: false, + net: false, + }, + }) + ] ], } if (dev) { diff --git a/scripts/esbuildPlugins.mjs b/scripts/esbuildPlugins.mjs index 07938c6e..978157ff 100644 --- a/scripts/esbuildPlugins.mjs +++ b/scripts/esbuildPlugins.mjs @@ -12,6 +12,9 @@ const { supportedVersions } = MCProtocol const prod = process.argv.includes('--prod') let connectedClients = [] +let singleFileBuild = false +export const setSingleFileBuild = (v) => singleFileBuild = v + /** @type {import('esbuild').Plugin[]} */ const plugins = [ { @@ -64,11 +67,26 @@ const plugins = [ } }) - build.onEnd(async ({ metafile, outputFiles }) => { + build.onEnd(async ({ metafile, outputFiles = [], errors }) => { + if (errors.length) return // write outputFiles - //@ts-ignore - for (const file of outputFiles) { - await fs.promises.writeFile(file.path, file.contents) + if (singleFileBuild) { + const jsFile = outputFiles.find(outputFile => outputFile.path.endsWith('.js'))?.contents + const cssFile = outputFiles.find(outputFile => outputFile.path.endsWith('.css'))?.contents + let html = fs.readFileSync('./index.html', 'utf8') + html = html.replace('', ``) + html = html.replace('', ``) + + const favicon = fs.readFileSync('./assets/favicon.png', 'base64') + html = html.replace(``, ``) + html = html.replace('', '') + html = html.replace('', '') + fs.writeFileSync('./dist/minecraft.html', html) + outputFiles + } else { + for (const file of outputFiles) { + await fs.promises.writeFile(file.path, file.contents) + } } if (!prod) return // const deps = Object.entries(metafile.inputs).sort(([, a], [, b]) => b.bytes - a.bytes).map(([x, { bytes }]) => [x, filesize(bytes)]).slice(0, 5) @@ -133,7 +151,7 @@ const plugins = [ } // write metafile to disk if needed to analyze - // fs.writeFileSync('dist/meta.json', JSON.stringify(metafile, null, 2)) + fs.writeFileSync('dist/meta.json', JSON.stringify(metafile, null, 2)) /** @type {import('esbuild').OutputFile} */ //@ts-ignore diff --git a/src/react/Slider.tsx b/src/react/Slider.tsx index bc6c5890..73468fe6 100644 --- a/src/react/Slider.tsx +++ b/src/react/Slider.tsx @@ -55,6 +55,9 @@ const Slider: React.FC = ({ max={max} value={value} disabled={!!disabledReason} + onPointerDown={(e) => { + (e.target as HTMLElement).setPointerCapture(e.pointerId) + }} onChange={(e) => { const newValue = Number(e.target.value) setValue(newValue)