From f9b87d5087629363c94008976b6a372429d9d2c9 Mon Sep 17 00:00:00 2001 From: Vitaly Turovsky Date: Wed, 11 Sep 2024 01:07:46 +0300 Subject: [PATCH] move playground to rsbuild! now fast reloads! reload on workers change fix cd --- .github/workflows/next-deploy.yml | 5 +- .github/workflows/preview.yml | 5 +- .github/workflows/publish.yml | 5 +- package.json | 13 ++- prismarine-viewer/buildMesherWorker.mjs | 8 +- prismarine-viewer/esbuild.mjs | 96 ---------------------- prismarine-viewer/playground.html | 2 +- prismarine-viewer/rsbuild.config.ts | 37 +++++++++ prismarine-viewer/rsbuildSharedConfig.ts | 100 +++++++++++++++++++++++ rsbuild.config.ts | 84 +++---------------- 10 files changed, 171 insertions(+), 184 deletions(-) delete mode 100644 prismarine-viewer/esbuild.mjs create mode 100644 prismarine-viewer/rsbuild.config.ts create mode 100644 prismarine-viewer/rsbuildSharedConfig.ts diff --git a/.github/workflows/next-deploy.yml b/.github/workflows/next-deploy.yml index f6915839b..a01e0bb8e 100644 --- a/.github/workflows/next-deploy.yml +++ b/.github/workflows/next-deploy.yml @@ -24,7 +24,10 @@ jobs: run: vercel build --token=${{ secrets.VERCEL_TOKEN }} - run: pnpm build-storybook - name: Copy playground files - run: pnpm build-playground && cp prismarine-viewer/public/index.html .vercel/output/static/playground.html && cp prismarine-viewer/public/playground.js .vercel/output/static/playground.js + run: | + mkdir -p .vercel/output/static/playground + pnpm build-playground + cp -r prismarine-viewer/dist/* .vercel/output/static/playground/ - name: Download Generated Sounds map run: node scripts/downloadSoundsMap.mjs - name: Deploy Project Artifacts to Vercel diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index e0f9736a0..c074d2e5f 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -35,7 +35,10 @@ jobs: run: vercel build --token=${{ secrets.VERCEL_TOKEN }} - run: pnpm build-storybook - name: Copy playground files - run: pnpm build-playground && cp prismarine-viewer/public/index.html .vercel/output/static/playground.html && cp prismarine-viewer/public/playground.js .vercel/output/static/playground.js + run: | + mkdir -p .vercel/output/static/playground + pnpm build-playground + cp -r prismarine-viewer/dist/* .vercel/output/static/playground/ - name: Download Generated Sounds map run: node scripts/downloadSoundsMap.mjs - name: Deploy Project Artifacts to Vercel diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 9472118bc..fa1f02810 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -23,7 +23,10 @@ jobs: - run: vercel build --token=${{ secrets.VERCEL_TOKEN }} --prod - run: pnpm build-storybook - name: Copy playground files - run: pnpm build-playground && cp prismarine-viewer/public/index.html .vercel/output/static/playground.html && cp prismarine-viewer/public/playground.js .vercel/output/static/playground.js + run: | + mkdir -p .vercel/output/static/playground + pnpm build-playground + cp -r prismarine-viewer/dist/* .vercel/output/static/playground/ - name: Download Generated Sounds map run: node scripts/downloadSoundsMap.mjs - name: Deploy Project to Vercel diff --git a/package.json b/package.json index c0ac0cc1a..d715016a3 100644 --- a/package.json +++ b/package.json @@ -6,9 +6,8 @@ "dev-rsbuild": "rsbuild dev", "dev-proxy": "node server.js", "start": "run-p dev-rsbuild dev-proxy watch-mesher", - "start-watch-script": "nodemon -w rsbuild.config.ts --watch", - "build": "rsbuild build", - "build-analyze": "BUNDLE_ANALYZE=true rsbuild build", + "build": "pnpm build-other-workers && rsbuild build", + "build-analyze": "BUNDLE_ANALYZE=true rsbuild build && pnpm build-other-workers", "check-build": "tsx scripts/genShims.ts && tsc && pnpm build", "test:cypress": "cypress run", "test-unit": "vitest", @@ -20,13 +19,13 @@ "build-storybook": "storybook build && node scripts/build.js moveStorybookFiles", "start-experiments": "vite --config experiments/vite.config.ts --host", "watch-other-workers": "echo NOT IMPLEMENTED", + "build-other-workers": "echo NOT IMPLEMENTED", "build-mesher": "node prismarine-viewer/buildMesherWorker.mjs", "watch-mesher": "pnpm build-mesher -w", - "run-playground": "run-p watch-mesher watch-other-workers playground-server watch-playground", + "run-playground": "run-p watch-mesher watch-other-workers watch-playground", "run-all": "run-p start run-playground", - "playground-server": "live-server --port=9090 prismarine-viewer/public", - "build-playground": "node prismarine-viewer/esbuild.mjs", - "watch-playground": "node prismarine-viewer/esbuild.mjs -w" + "build-playground": "rsbuild build --root ./prismarine-viewer", + "watch-playground": "rsbuild dev --root ./prismarine-viewer" }, "keywords": [ "prismarine", diff --git a/prismarine-viewer/buildMesherWorker.mjs b/prismarine-viewer/buildMesherWorker.mjs index f70b81288..03b952b4f 100644 --- a/prismarine-viewer/buildMesherWorker.mjs +++ b/prismarine-viewer/buildMesherWorker.mjs @@ -30,7 +30,7 @@ const buildOptions = { sourcemap: 'linked', write: false, metafile: true, - outdir: path.join(__dirname, './public'), + outdir: path.join(__dirname, './dist'), define: { 'process.env.BROWSER': '"true"', }, @@ -108,9 +108,9 @@ const buildOptions = { }) build.onEnd(({ metafile, outputFiles }) => { if (!metafile) return - fs.mkdirSync(path.join(__dirname, './public'), { recursive: true }) - fs.writeFileSync(path.join(__dirname, './public/metafile.json'), JSON.stringify(metafile)) - for (const outDir of ['../dist/', './public/']) { + fs.mkdirSync(path.join(__dirname, './dist'), { recursive: true }) + fs.writeFileSync(path.join(__dirname, './dist/metafile.json'), JSON.stringify(metafile)) + for (const outDir of ['../dist/', './dist/']) { for (const outputFile of outputFiles) { if (outDir === '../dist/' && outputFile.path.endsWith('.map')) { // skip writing & browser loading sourcemap there, worker debugging should be done in playground diff --git a/prismarine-viewer/esbuild.mjs b/prismarine-viewer/esbuild.mjs deleted file mode 100644 index e410c8b61..000000000 --- a/prismarine-viewer/esbuild.mjs +++ /dev/null @@ -1,96 +0,0 @@ -//@ts-check -import * as fs from 'fs' -import fsExtra from 'fs-extra' - -import * as esbuild from 'esbuild' -import { polyfillNode } from 'esbuild-plugin-polyfill-node' -import path, { dirname, join } from 'path' -import { fileURLToPath } from 'url' -import childProcess from 'child_process' -import supportedVersions from '../src/supportedVersions.mjs' - -const dev = process.argv.includes('-w') - -const __dirname = path.dirname(fileURLToPath(new URL(import.meta.url))) - -const mcDataPath = join(__dirname, '../generated/minecraft-data-optimized.json') -if (!fs.existsSync(mcDataPath)) { - childProcess.execSync('tsx ../scripts/makeOptimizedMcData.mjs', { stdio: 'inherit', cwd: __dirname }) -} - -fs.copyFileSync(join(__dirname, 'playground.html'), join(__dirname, 'public/index.html')) - -/** @type {import('esbuild').BuildOptions} */ -const buildOptions = { - bundle: true, - entryPoints: [join(__dirname, './examples/playground.ts')], - // target: ['es2020'], - // logLevel: 'debug', - logLevel: 'info', - platform: 'browser', - sourcemap: dev ? 'inline' : false, - minify: !dev, - outfile: join(__dirname, 'public/playground.js'), - mainFields: [ - 'browser', 'module', 'main' - ], - keepNames: true, - banner: { - js: `globalThis.global = globalThis;globalThis.includedVersions = ${JSON.stringify(supportedVersions)};`, - }, - alias: { - events: 'events', - buffer: 'buffer', - 'fs': 'browserfs/dist/shims/fs.js', - http: 'http-browserify', - stream: 'stream-browserify', - net: 'net-browserify', - // 'mc-assets': '/Users/vitaly/Documents/mc-assets', - }, - inject: [], - metafile: true, - loader: { - '.png': 'dataurl', - '.obj': 'text', - }, - plugins: [ - { - name: 'minecraft-data', - setup(build) { - build.onLoad({ - filter: /minecraft-data[\/\\]data.js$/, - }, () => { - const defaultVersionsObj = {} - return { - contents: fs.readFileSync(join(__dirname, '../src/shims/minecraftData.ts'), 'utf8'), - loader: 'ts', - resolveDir: join(__dirname, '../src/shims'), - } - }) - 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) { - (await esbuild.context(buildOptions)).watch() -} else { - await esbuild.build(buildOptions) -} - -// await ctx.rebuild() diff --git a/prismarine-viewer/playground.html b/prismarine-viewer/playground.html index f1b360157..92713c1c1 100644 --- a/prismarine-viewer/playground.html +++ b/prismarine-viewer/playground.html @@ -31,6 +31,6 @@ - +
diff --git a/prismarine-viewer/rsbuild.config.ts b/prismarine-viewer/rsbuild.config.ts new file mode 100644 index 000000000..1299670d3 --- /dev/null +++ b/prismarine-viewer/rsbuild.config.ts @@ -0,0 +1,37 @@ +import { defineConfig, mergeRsbuildConfig } from '@rsbuild/core'; +import supportedVersions from '../src/supportedVersions.mjs' +import childProcess from 'child_process' +import path, { dirname, join } from 'path' +import { pluginReact } from '@rsbuild/plugin-react'; +import { pluginNodePolyfill } from '@rsbuild/plugin-node-polyfill'; +import fs from 'fs' +import { appAndRendererSharedConfig, rspackViewerConfig } from './rsbuildSharedConfig'; + +const mcDataPath = join(__dirname, '../generated/minecraft-data-optimized.json') + +if (!fs.existsSync(mcDataPath)) { + childProcess.execSync('tsx ./scripts/makeOptimizedMcData.mjs', { stdio: 'inherit', cwd: path.join(__dirname, '..') }) +} + +export default mergeRsbuildConfig( + appAndRendererSharedConfig(), + defineConfig({ + html: { + template: './playground.html', + }, + output: { + cleanDistPath: false, + }, + server: { + port: 9090, + }, + source: { + entry: { + index: join(__dirname, './examples/playground.ts') + }, + define: { + 'globalThis.includedVersions': JSON.stringify(supportedVersions), + }, + }, + }) +) diff --git a/prismarine-viewer/rsbuildSharedConfig.ts b/prismarine-viewer/rsbuildSharedConfig.ts new file mode 100644 index 000000000..3fba1ef18 --- /dev/null +++ b/prismarine-viewer/rsbuildSharedConfig.ts @@ -0,0 +1,100 @@ +import { defineConfig, ModifyRspackConfigUtils } from '@rsbuild/core'; +import { pluginNodePolyfill } from '@rsbuild/plugin-node-polyfill'; +import { pluginReact } from '@rsbuild/plugin-react'; +import path from 'path' + +export const appAndRendererSharedConfig = () => defineConfig({ + dev: { + progressBar: true, + writeToDisk: true, + watchFiles: { + paths: [ + path.join(__dirname, './dist/webgpuRendererWorker.js'), + path.join(__dirname, './dist/mesher.js'), + ] + }, + }, + output: { + polyfill: 'usage', + // 50kb limit for data uri + dataUriLimit: 50 * 1024 + }, + source: { + alias: { + fs: path.join(__dirname, `../src/shims/fs.js`), + http: 'http-browserify', + stream: 'stream-browserify', + net: 'net-browserify', + 'minecraft-protocol$': 'minecraft-protocol/src/index.js', + 'buffer$': 'buffer', + // avoid bundling, not used on client side + 'prismarine-auth': path.join(__dirname, `../src/shims/prismarineAuthReplacement.ts`), + perf_hooks: path.join(__dirname, `../src/shims/perf_hooks_replacement.js`), + crypto: path.join(__dirname, `../src/shims/crypto.js`), + dns: path.join(__dirname, `../src/shims/dns.js`), + yggdrasil: path.join(__dirname, `../src/shims/yggdrasilReplacement.ts`), + 'three$': 'three/src/Three.js', + 'stats.js$': 'stats.js/src/Stats.js', + }, + define: { + 'process.platform': '"browser"', + }, + decorators: { + version: 'legacy', // default is a lie + }, + }, + server: { + htmlFallback: false, + publicDir: false, + headers: { + // enable shared array buffer + 'Cross-Origin-Opener-Policy': 'same-origin', + 'Cross-Origin-Embedder-Policy': 'require-corp', + }, + open: process.env.OPEN_BROWSER === 'true', + }, + plugins: [ + pluginReact(), + pluginNodePolyfill() + ], + tools: { + rspack (config, helpers) { + rspackViewerConfig(config, helpers) + } + }, +}) + +export const rspackViewerConfig = (config, { appendPlugins, addRules, rspack }: ModifyRspackConfigUtils) => { + appendPlugins(new rspack.NormalModuleReplacementPlugin(/data/, (resource) => { + let absolute: string + const request = resource.request.replaceAll('\\', '/') + absolute = path.join(resource.context, request).replaceAll('\\', '/') + if (request.includes('minecraft-data/data/pc/1.')) { + console.log('Error: incompatible resource', request, resource.contextInfo.issuer) + process.exit(1) + // throw new Error(`${resource.request} was requested by ${resource.contextInfo.issuer}`) + } + if (absolute.endsWith('/minecraft-data/data.js')) { + resource.request = path.join(__dirname, `../src/shims/minecraftData.ts`) + } + })) + addRules([ + { + test: /\.obj$/, + type: 'asset/source', + }, + { + test: /\.wgsl$/, + type: 'asset/source', + }, + { + test: /\.mp3$/, + type: 'asset/source', + } + ]) + config.ignoreWarnings = [ + /the request of a dependency is an expression/, + /Unsupported pseudo class or element: xr-overlay/ + ] + +} diff --git a/rsbuild.config.ts b/rsbuild.config.ts index 588cc35d0..f8a965dc4 100644 --- a/rsbuild.config.ts +++ b/rsbuild.config.ts @@ -1,4 +1,4 @@ -import { defineConfig, RsbuildPluginAPI } from '@rsbuild/core' +import { defineConfig, mergeRsbuildConfig, RsbuildPluginAPI } from '@rsbuild/core' import { pluginReact } from '@rsbuild/plugin-react' import { pluginTypedCSSModules } from '@rsbuild/plugin-typed-css-modules' import { pluginNodePolyfill } from '@rsbuild/plugin-node-polyfill' @@ -10,6 +10,7 @@ import fsExtra from 'fs-extra' import { promisify } from 'util' import { generateSW } from 'workbox-build' import { getSwAdditionalEntries } from './scripts/build' +import { appAndRendererSharedConfig } from './prismarine-viewer/rsbuildSharedConfig' //@ts-ignore try { require('./localSettings.js') } catch { } @@ -20,16 +21,12 @@ const buildingVersion = new Date().toISOString().split(':')[0] const dev = process.env.NODE_ENV === 'development' -export default defineConfig({ - dev: { - progressBar: true, - writeToDisk: true - }, +// base options are in ./prismarine-viewer/rsbuildSharedConfig.ts +const appConfig = defineConfig({ html: { template: './index.html', }, output: { - polyfill: 'usage', externals: [ 'sharp' ], @@ -37,25 +34,8 @@ export default defineConfig({ js: 'source-map', css: true, }, - // 50kb limit for data uri - dataUriLimit: 50 * 1024 }, source: { - alias: { - fs: './src/shims/fs.js', - http: 'http-browserify', - stream: 'stream-browserify', - net: 'net-browserify', - 'minecraft-protocol$': 'minecraft-protocol/src/index.js', - 'buffer$': 'buffer', - // avoid bundling, not used on client side - 'prismarine-auth': './src/shims/prismarineAuthReplacement.ts', - perf_hooks: './src/shims/perf_hooks_replacement.js', - crypto: './src/shims/crypto.js', - dns: './src/shims/dns.js', - yggdrasil: './src/shims/yggdrasilReplacement.ts', - 'three$': 'three/src/Three.js' - }, entry: { index: './src/index.ts', }, @@ -65,36 +45,22 @@ export default defineConfig({ define: { 'process.env.BUILD_VERSION': JSON.stringify(!dev ? buildingVersion : 'undefined'), 'process.env.MAIN_MENU_LINKS': JSON.stringify(process.env.MAIN_MENU_LINKS), - 'process.platform': '"browser"', 'process.env.GITHUB_URL': JSON.stringify(`https://github.com/${process.env.GITHUB_REPOSITORY || `${process.env.VERCEL_GIT_REPO_OWNER}/${process.env.VERCEL_GIT_REPO_SLUG}`}`), 'process.env.DEPS_VERSIONS': JSON.stringify({}) }, - decorators: { - version: 'legacy', // default is a lie - }, }, server: { // strictPort: true, - htmlFallback: false, - publicDir: false, // publicDir: { // name: 'assets', // }, - headers: { - // enable shared array buffer - 'Cross-Origin-Opener-Policy': 'same-origin', - 'Cross-Origin-Embedder-Policy': 'require-corp', - }, - open: process.env.OPEN_BROWSER === 'true', proxy: { '/api': 'http://localhost:8080', }, }, plugins: [ - pluginReact(), pluginTypedCSSModules(), - pluginNodePolyfill(), { name: 'test', setup (build: RsbuildPluginAPI) { @@ -121,9 +87,9 @@ export default defineConfig({ // childProcess.execSync('./scripts/prepareSounds.mjs', { stdio: 'inherit' }) // childProcess.execSync('tsx ./scripts/genMcDataTypes.ts', { stdio: 'inherit' }) // childProcess.execSync('tsx ./scripts/genPixelartTypes.ts', { stdio: 'inherit' }) - if (fs.existsSync('./prismarine-viewer/public/mesher.js') && dev) { + if (fs.existsSync('./prismarine-viewer/dist/mesher.js') && dev) { // copy mesher - fs.copyFileSync('./prismarine-viewer/public/mesher.js', './dist/mesher.js') + fs.copyFileSync('./prismarine-viewer/dist/mesher.js', './dist/mesher.js') } else if (!dev) { await execAsync('pnpm run build-mesher') } @@ -150,39 +116,6 @@ export default defineConfig({ }, }, ], - tools: { - bundlerChain (chain, { CHAIN_ID }) { - }, - rspack (config, { addRules, appendPlugins, rspack }) { - appendPlugins(new rspack.NormalModuleReplacementPlugin(/data/, (resource) => { - let absolute: string - const request = resource.request.replaceAll('\\', '/') - absolute = path.join(resource.context, request).replaceAll('\\', '/') - if (request.includes('minecraft-data/data/pc/1.')) { - console.log('Error: incompatible resource', request, resource.contextInfo.issuer) - process.exit(1) - // throw new Error(`${resource.request} was requested by ${resource.contextInfo.issuer}`) - } - if (absolute.endsWith('/minecraft-data/data.js')) { - resource.request = path.join(__dirname, './src/shims/minecraftData.ts') - } - })) - addRules([ - { - test: /\.obj$/, - type: 'asset/source', - }, - { - test: /\.mp3$/, - type: 'asset/source', - } - ]) - config.ignoreWarnings = [ - /the request of a dependency is an expression/, - /Unsupported pseudo class or element: xr-overlay/ - ] - } - }, // performance: { // bundleAnalyze: { // analyzerMode: 'json', @@ -190,3 +123,8 @@ export default defineConfig({ // }, // }, }) + +export default mergeRsbuildConfig( + appAndRendererSharedConfig(), + appConfig +)