move building to esbuild

change public to dist
This commit is contained in:
Vitaly 2023-08-28 06:37:57 +03:00
commit fc7869000e
14 changed files with 421 additions and 30 deletions

View file

@ -11,22 +11,25 @@ const filesAlwaysToCopy = [
]
// these files could be copied at build time eg with copy plugin, but copy plugin slows down the config (2x in my testing, sometimes with too many open files error) is slow so we also copy them there
const webpackFilesToCopy = [
{ from: './node_modules/prismarine-viewer2/public/blocksStates/', to: 'public/blocksStates/' },
{ from: './node_modules/prismarine-viewer2/public/textures/', to: 'public/textures/' },
{ from: './node_modules/prismarine-viewer2/public/worker.js', to: 'public/worker.js' },
{ from: './node_modules/prismarine-viewer2/public/supportedVersions.json', to: 'public/supportedVersions.json' },
{ from: './assets/', to: './public/' },
{ from: './config.json', to: 'public/config.json' }
{ from: './node_modules/prismarine-viewer2/public/blocksStates/', to: 'dist/blocksStates/' },
{ from: './node_modules/prismarine-viewer2/public/textures/', to: 'dist/textures/' },
{ from: './node_modules/prismarine-viewer2/public/worker.js', to: 'dist/worker.js' },
{ from: './node_modules/prismarine-viewer2/public/supportedVersions.json', to: 'dist/supportedVersions.json' },
{ from: './assets/', to: './dist/' },
{ from: './config.json', to: 'dist/config.json' }
]
exports.webpackFilesToCopy = webpackFilesToCopy
exports.copyFiles = (isDev = false) => {
console.time('copy files');
[...filesAlwaysToCopy, ...webpackFilesToCopy].forEach(file => {
fsExtra.copySync(file.from, file.to)
})
console.timeEnd('copy files')
}
exports.copyFilesDev = () => {
if (fsExtra.existsSync('public/config.json')) return
if (fsExtra.existsSync('dist/config.json')) return
exports.copyFiles(true)
}
@ -34,6 +37,9 @@ exports.getSwAdditionalEntries = () => {
// need to be careful with this
const singlePlayerVersion = defaultLocalServerOptions.version
const filesToCachePatterns = [
'index.js',
'index.css',
'favicon.ico',
`blocksStates/${singlePlayerVersion}.json`,
'extra-textures/**',
// todo-low copy from assets
@ -59,9 +65,9 @@ exports.getSwAdditionalEntries = () => {
const output = []
console.log('Generating sw additional entries...')
for (const pattern of filesToCachePatterns) {
const files = glob.sync(pattern, { cwd: 'public' })
const files = glob.sync(pattern, { cwd: 'dist' })
for (const file of files) {
const fullPath = path.join('public', file)
const fullPath = path.join('dist', file)
if (!fs.lstatSync(fullPath).isFile()) continue
let revision = null
const url = './' + file.replace(/\\/g, '/')

229
scripts/esbuildPlugins.mjs Normal file
View file

@ -0,0 +1,229 @@
//@ts-check
import { polyfillNode } from 'esbuild-plugin-polyfill-node'
import { join, dirname } from 'path'
import * as fs from 'fs'
import { filesize } from 'filesize'
let clients = []
/** @type {import('esbuild').Plugin[]} */
const plugins = [
{
name: 'strict-aliases',
setup (build) {
build.onResolve({
filter: /^minecraft-protocol$/,
}, async ({ kind, resolveDir }) => {
return {
path: (await build.resolve('minecraft-protocol/src/index.js', { kind, resolveDir })).path,
}
})
// build.onResolve({
// filter: /^\.\/data.js$/,
// }, ({ resolveDir, path }) => {
// if (!resolveDir.endsWith('minecraft-data')) return
// return {
// namespace: 'load-global-minecraft-data',
// path
// }
// })
// build.onLoad({
// filter: /.+/,
// namespace: 'load-global-minecraft-data',
// }, () => {
// return {
// contents: 'module.exports = window.minecraftData',
// loader: 'js',
// }
// })
// build.onResolve({
// filter: /^minecraft-assets$/,
// }, ({ resolveDir, path }) => {
// // if (!resolveDir.endsWith('minecraft-data')) return
// return {
// namespace: 'load-global-minecraft-assets',
// path
// }
// })
// build.onLoad({
// filter: /.+/,
// namespace: 'load-global-minecraft-assets',
// }, async () => {
// const resolvedPath = await build.resolve('minecraft-assets/index.js', { kind: 'require-call', resolveDir: process.cwd() })
// let contents = (await fs.promises.readFile(resolvedPath.path, 'utf8'))
// contents = contents.slice(0, contents.indexOf('const data = ')) + 'const data = window.minecraftAssets;' + contents.slice(contents.indexOf('module.exports.versions'))
// return {
// contents,
// loader: 'js',
// resolveDir: dirname(resolvedPath.path),
// }
// })
}
},
{
name: 'assets-resolve',
setup (build) {
build.onResolve({
filter: /.*/,
}, async ({ path, ...rest }) => {
if (['.woff', '.woff2', '.ttf', '.png', '.jpg', '.jpeg', '.gif', '.svg'].some(ext => path.endsWith(ext))) {
return {
path,
namespace: 'assets',
external: true,
}
}
})
build.onEnd(({ metafile, outputFiles }) => {
// top 5 biggest deps
//@ts-ignore
// const deps = Object.entries(metafile.inputs).sort(([, a], [, b]) => b.bytes - a.bytes).map(([x, { bytes }]) => [x, filesize(bytes)]).slice(0, 5)
// console.log(deps)
})
},
},
{
name: 'prevent-incorrect-linking',
setup (build) {
build.onResolve({
filter: /.+/,
}, ({ resolveDir }) => {
// disallow imports from outside the root directory to ensure modules are resolved from node_modules of this workspace
if (!resolveDir.startsWith(process.cwd())) {
throw new Error(`Restricted import from outside the root directory: ${resolveDir}`)
}
return undefined
})
}
},
{
name: 'watch-notify',
setup (build) {
let count = 0
let time
build.onStart(() => {
time = Date.now()
})
build.onEnd(({ errors, outputFiles, metafile, warnings }) => {
const elapsed = Date.now() - time
console.log(`Done in ${elapsed}ms`)
if (count++ === 0) {
return
}
if (errors.length) {
clients.forEach((res) => {
res.write(`data: ${JSON.stringify({ errors: errors.map(error => error.text) })}\n\n`)
res.flush()
})
return
}
clients.forEach((res) => {
res.write(`data: ${JSON.stringify({ update: { time: elapsed } })}\n\n`)
res.flush()
})
clients.length = 0
})
}
},
{
name: 'esbuild-readdir',
setup (build) {
build.onResolve({
filter: /^esbuild-readdir:.+$/,
}, ({ resolveDir, path }) => {
return {
namespace: 'esbuild-readdir',
path,
pluginData: {
resolveDir: join(resolveDir, path.replace(/^esbuild-readdir:/, ''))
},
}
})
build.onLoad({
filter: /.+/,
namespace: 'esbuild-readdir',
}, async ({ pluginData }) => {
const { resolveDir } = pluginData
const files = await fs.promises.readdir(resolveDir)
return {
contents: `module.exports = ${JSON.stringify(files)}`,
resolveDir,
loader: 'js',
}
})
}
},
{
name: 'esbuild-import-glob',
setup (build) {
build.onResolve({
filter: /^esbuild-import-glob\(path:(.+),skipFiles:(.+)\)+$/,
}, ({ resolveDir, path }) => {
return {
namespace: 'esbuild-import-glob',
path,
pluginData: {
resolveDir
},
}
})
build.onLoad({
filter: /.+/,
namespace: 'esbuild-import-glob',
}, async ({ pluginData, path }) => {
const { resolveDir } = pluginData
const [, userPath, skipFiles] = /^esbuild-import-glob\(path:(.+),skipFiles:(.+)\)+$/g.exec(path)
const files = (await fs.promises.readdir(join(resolveDir, userPath))).filter(f => !skipFiles.includes(f))
return {
contents: `module.exports = { ${files.map(f => `'${f}': require('./${join(userPath, f)}')`).join(',')} }`,
resolveDir,
loader: 'js',
}
})
}
},
{
name: 'fix-dynamic-require',
setup (build) {
build.onResolve({
filter: /1\.14\/chunk/,
}, async ({ resolveDir, path }) => {
if (!resolveDir.includes('prismarine-provider-anvil')) return
return {
namespace: 'fix-dynamic-require',
path,
pluginData: {
resolvedPath: `${join(resolveDir, path)}.js`,
resolveDir
},
}
})
build.onLoad({
filter: /.+/,
namespace: 'fix-dynamic-require',
}, async ({ pluginData: { resolvedPath, resolveDir } }) => {
const resolvedFile = await fs.promises.readFile(resolvedPath, 'utf8')
return {
contents: resolvedFile.replace("require(`prismarine-chunk/src/pc/common/BitArray${noSpan ? 'NoSpan' : ''}`)", "noSpan ? require(`prismarine-chunk/src/pc/common/BitArray`) : require(`prismarine-chunk/src/pc/common/BitArrayNoSpan`)"),
resolveDir,
loader: 'js',
}
})
}
},
polyfillNode({
polyfills: {
fs: false,
crypto: false,
events: false,
http: false,
stream: false,
buffer: false,
perf_hooks: false,
net: false,
},
})
]
export { plugins, clients }

View file

@ -10,11 +10,13 @@ function removeLinesBetween (start, end) {
let startIndex = lines.findIndex(line => line === start)
if (startIndex === -1) return
let endIndex = startIndex + lines.slice(startIndex).findIndex(line => line === end)
const linesToRemove = endIndex - startIndex + 1
lines.splice(startIndex, linesToRemove)
// insert block comments
lines.splice(startIndex, 0, `/*`)
lines.splice(endIndex + 2, 0, `*/`)
}
// todo removing bedrock support for now, will optiimze in future instead
removeLinesBetween(" 'bedrock': {", ' }')
// fs.writeFileSync(path.join(dataPath, '../dataGlobal.js'), newContents, 'utf8')
fs.writeFileSync(dataPath, lines.join('\n'), 'utf8')