pages235/scripts/buildNpmReact.ts
Vitaly 9b72cdb8f0
feat: migrate to mc-assets & Rsbuild better resource pack support (#164)
The complete migration from `minecraft-assets` to [`mc-assets`](https://npmjs.com/mc-assets).

Now all block states & block models are processed dynamically! So it is now easily possible to implement custom models

- no post-install work anymore: the building is now 3x faster and 4x faster in docker
- drop 10x total deploy size
- display world ~1.5x faster
- fix snow & repeater state parser (they didn't render correctly)

rsbuild pipeline!

- the initial app load is faster ~1.2
- much fewer requests are made & cached
- dev reloads are fast now

Resource pack changes:

- now textures are reloaded much more quickly on the fly
- add hotkey to quickly reload textures (for debugging) assigned to F3+T (open dev widget is now assigned to F3+Y)
- add a way to disable resource pack instead of uninstalling it
- items render from resource pack are now support
- resource pack widgets & icons are now supported
2024-07-26 13:12:28 +03:00

153 lines
6.2 KiB
TypeScript

import fs from 'fs'
import path from 'path'
import { build, transform } from 'esbuild'
import { execSync } from 'child_process'
// import { copy } from 'fs-extra'
import { glob } from 'glob'
const isAbsolute = (path: string) => path.startsWith('/') || /^[A-Z]:/i.test(path)
fs.promises.readdir(path.resolve(__dirname, '../src/react')).then(async (files) => {
const components = files
.filter((file) => {
if (file.startsWith('Concept')) return false
return file.endsWith('.stories.tsx')
})
.map((file) => {
return file.replace('.stories.tsx', '')
})
const content = components.map((component) => {
return `export { default as ${component} } from './${component}'`
}).join('\n')
await fs.promises.writeFile(
path.resolve(__dirname, '../src/react/npmReactComponents.ts'),
content
)
execSync('pnpm tsc -p tsconfig.npm.json', {
cwd: path.resolve(__dirname, '../'),
stdio: 'inherit',
})
const packageJson = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../package.npm.json'), 'utf-8'))
const packageJsonRoot = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../package.json'), 'utf-8'))
const external = Object.keys(packageJson.peerDependencies)
const dependencies = new Set<string>()
let version = process.argv[2] || packageJsonRoot.version
version = version.replace(/^v/, '')
packageJson.version = version
const externalize = ['prismarine-viewer', 'mc-assets']
const { metafile } = await build({
entryPoints: [path.resolve(__dirname, '../src/react/npmReactComponents.ts')],
bundle: true,
outfile: path.resolve(__dirname, '../dist-npm/bundle.esm.js'),
format: 'esm',
platform: 'browser',
target: 'es2020',
external: external,
metafile: true,
minify: true,
write: false, // todo
loader: {
'.png': 'dataurl',
'.jpg': 'dataurl',
'.jpeg': 'dataurl',
'.webp': 'dataurl',
'.css': 'text',
},
plugins: [
// on external module resolve
{
name: 'collect-imports',
setup (build) {
build.onResolve({ filter: /.*/ }, (args) => {
if (args.importer.includes('node_modules') || external.some(x => args.path.startsWith(x)) || isAbsolute(args.path)) {
return undefined
}
if (args.path.startsWith('./') || args.path.startsWith('../')) {
if (args.path.endsWith('.png') || args.path.endsWith('.css') || args.path.endsWith('.jpg') || args.path.endsWith('.jpeg')) {
const absoluteImporting = path.join(path.dirname(args.importer), args.path)
const absoluteRoot = path.resolve(__dirname, '../src')
const relativeToRoot = path.relative(absoluteRoot, absoluteImporting)
fs.copyFileSync(absoluteImporting, path.resolve(__dirname, '../dist-npm/dist-pre', relativeToRoot))
}
// default behavior
return undefined
}
const dep = args.path.startsWith('@') ? args.path.split('/').slice(0, 2).join('/') : args.path.split('/')[0]
if (!dependencies.has(dep)) {
dependencies.add(dep)
console.log('Adding dependency:', dep, 'from', args.importer)
}
// return { external: true }
})
},
},
],
})
for (const dependency of dependencies) {
if (externalize.includes(dependency)) continue
if (!packageJsonRoot.dependencies[dependency]) throw new Error(`Dependency ${dependency} not found in package.json`)
packageJson.dependencies[dependency] = packageJsonRoot.dependencies[dependency]
}
fs.writeFileSync(path.resolve(__dirname, '../dist-npm/package.json'), JSON.stringify(packageJson, null, 2))
// fs.promises.writeFile('./dist-npm/metafile.json', JSON.stringify(metafile, null, 2))
await build({
entryPoints: ['dist-npm/dist-pre/**/*.js'],
outdir: 'dist-npm/dist',
// allowOverwrite: true,
jsx: 'preserve',
bundle: true,
target: 'esnext',
platform: 'browser',
format: 'esm',
loader: {
'.css': 'copy',
'.module.css': 'copy',
'.png': 'copy',
},
minifyWhitespace: false,
logOverride: {
// 'ignored-bare-import': "info"
},
plugins: [
{
name: 'all-external',
setup (build) {
build.onResolve({ filter: /.*/ }, (args) => {
// todo use workspace deps
if (externalize.some(x => args.path.startsWith(x))) {
return undefined // bundle
}
if (args.path.endsWith('.css') || args.path.endsWith('.png') || args.path.endsWith('.jpg') || args.path.endsWith('.jpeg')) {
return undefined // loader action
}
return {
path: args.path,
external: true,
}
})
},
}
],
})
const paths = await glob('dist-npm/dist-pre/**/*.d.ts')
// copy to dist
for (const p of paths) {
const relative = path.relative('dist-npm/dist-pre', p)
const target = path.resolve('dist-npm/dist', relative)
fs.copyFileSync(p, target)
}
// rm dist-pre
fs.rmSync('dist-npm/dist-pre', { recursive: true })
fs.copyFileSync(path.resolve(__dirname, '../README.NPM.MD'), path.resolve(__dirname, '../dist-npm/README.md'))
if (version !== '0.0.0-dev') {
execSync('npm publish', { cwd: path.resolve(__dirname, '../dist-npm') })
}
})