mirror of
https://github.com/enso-org/enso.git
synced 2024-12-24 17:01:38 +03:00
165 lines
5.5 KiB
TypeScript
165 lines
5.5 KiB
TypeScript
/**
|
|
* Configuration for the esbuild bundler and build/watch commands.
|
|
*
|
|
* The bundler processes each entry point into a single file, each with no external dependencies and
|
|
* minified. This primarily involves resolving all imports, along with some other transformations
|
|
* (like TypeScript compilation).
|
|
*
|
|
* See the bundlers documentation for more information:
|
|
* https://esbuild.github.io/getting-started/#bundling-for-node
|
|
*/
|
|
|
|
import fs from 'node:fs'
|
|
import path, { dirname } from 'node:path'
|
|
import child_process from 'node:child_process'
|
|
import { fileURLToPath } from 'node:url'
|
|
|
|
import esbuild from 'esbuild'
|
|
import plugin_yaml from 'esbuild-plugin-yaml'
|
|
import { NodeModulesPolyfillPlugin } from '@esbuild-plugins/node-modules-polyfill'
|
|
import { NodeGlobalsPolyfillPlugin } from '@esbuild-plugins/node-globals-polyfill'
|
|
import aliasPlugin from 'esbuild-plugin-alias'
|
|
// @ts-ignore
|
|
import timePlugin from 'esbuild-plugin-time'
|
|
// @ts-ignore
|
|
import * as copy_plugin from 'enso-copy-plugin'
|
|
|
|
import { require_env } from '../../utils.js'
|
|
import * as BUILD_INFO from '../../build.json' assert { type: 'json' }
|
|
|
|
export const thisPath = path.resolve(dirname(fileURLToPath(import.meta.url)))
|
|
|
|
// =============================
|
|
// === Environment variables ===
|
|
// =============================
|
|
|
|
/** List of files to be copied from WASM artifacts. */
|
|
export const wasm_artifacts = require_env('ENSO_BUILD_GUI_WASM_ARTIFACTS')
|
|
|
|
/** Directory with assets. Its contents are to be copied. */
|
|
export const assets_path = require_env('ENSO_BUILD_GUI_ASSETS')
|
|
|
|
/** Path where bundled files are output. */
|
|
export const output_path = path.resolve(require_env('ENSO_BUILD_GUI'), 'assets')
|
|
|
|
/** The main JS bundle to load WASM and JS wasm-pack bundles. */
|
|
export const ensogl_app_path = require_env('ENSO_BUILD_GUI_ENSOGL_APP')
|
|
|
|
// ===================
|
|
// === Git process ===
|
|
// ===================
|
|
|
|
/**
|
|
* Get output of a git command.
|
|
* @param command Command line following the `git` program.
|
|
* @returns Output of the command.
|
|
*/
|
|
function git(command: string): string {
|
|
// TODO [mwu] Eventually this should be removed, data should be provided by the build script through `BUILD_INFO`.
|
|
// The bundler configuration should not invoke git, it is not its responsibility.
|
|
return child_process.execSync(`git ${command}`, { encoding: 'utf8' }).trim()
|
|
}
|
|
|
|
// ==============================
|
|
// === Files to manually copy ===
|
|
// ==============================
|
|
|
|
/**
|
|
* Static set of files that are always copied to the output directory.
|
|
*/
|
|
const always_copied_files = [
|
|
path.resolve(thisPath, 'src', 'index.html'),
|
|
path.resolve(thisPath, 'src', 'run.js'),
|
|
path.resolve(thisPath, 'src', 'style.css'),
|
|
path.resolve(thisPath, 'src', 'docsStyle.css'),
|
|
...wasm_artifacts.split(path.delimiter),
|
|
]
|
|
|
|
/**
|
|
* Generator that yields all files that should be copied to the output directory.
|
|
*/
|
|
async function* files_to_copy_provider() {
|
|
console.log('Preparing a new generator for files to copy.')
|
|
yield* always_copied_files
|
|
for (const file of await fs.promises.readdir(assets_path)) {
|
|
yield path.resolve(assets_path, file)
|
|
}
|
|
console.log('Generator for files to copy finished.')
|
|
}
|
|
|
|
// ================
|
|
// === Bundling ===
|
|
// ================
|
|
|
|
const config: esbuild.BuildOptions = {
|
|
bundle: true,
|
|
entryPoints: ['src/index.ts'],
|
|
outdir: output_path,
|
|
outbase: 'src',
|
|
plugins: [
|
|
plugin_yaml.yamlPlugin({}),
|
|
NodeModulesPolyfillPlugin(),
|
|
NodeGlobalsPolyfillPlugin({ buffer: true, process: true }),
|
|
aliasPlugin({ ensogl_app: ensogl_app_path }),
|
|
timePlugin(),
|
|
copy_plugin.create(files_to_copy_provider),
|
|
],
|
|
define: {
|
|
GIT_HASH: JSON.stringify(git('rev-parse HEAD')),
|
|
GIT_STATUS: JSON.stringify(git('status --short --porcelain')),
|
|
BUILD_INFO: JSON.stringify(BUILD_INFO),
|
|
},
|
|
sourcemap: true,
|
|
minify: true,
|
|
metafile: true,
|
|
format: 'esm',
|
|
publicPath: '/assets',
|
|
platform: 'browser',
|
|
incremental: true,
|
|
color: true,
|
|
logOverride: {
|
|
// Happens in ScalaJS-generated parser (scala-parser.js):
|
|
// 6 │ "fileLevelThis": this
|
|
'this-is-undefined-in-esm': 'silent',
|
|
// Happens in ScalaJS-generated parser (scala-parser.js):
|
|
// 1553 │ } else if ((a === (-0))) {
|
|
'equals-negative-zero': 'silent',
|
|
// Happens in Emscripten-generated MSDF (msdfgen_wasm.js):
|
|
// 1 │ ...typeof module!=="undefined"){module["exports"]=Module}process["o...
|
|
'commonjs-variable-in-esm': 'silent',
|
|
// Happens in Emscripten-generated MSDF (msdfgen_wasm.js):
|
|
// 1 │ ...y{table.grow(1)}catch(err){if(!err instanceof RangeError){throw ...
|
|
'suspicious-boolean-not': 'silent',
|
|
},
|
|
}
|
|
|
|
/**
|
|
* Spawn the esbuild watch process. It continuously runs, rebuilding the package.
|
|
*/
|
|
export async function watch(onRebuild?: () => void, inject?: esbuild.BuildOptions['inject']) {
|
|
return esbuild.build({
|
|
...config,
|
|
inject: [...(config.inject ?? []), ...(inject ?? [])],
|
|
watch: {
|
|
onRebuild(error, result) {
|
|
if (error) console.error('watch build failed:', error)
|
|
else onRebuild?.()
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Bundles the package.
|
|
*/
|
|
export async function bundle() {
|
|
try {
|
|
return esbuild.build({ ...config, watch: false, incremental: false })
|
|
} catch (error) {
|
|
console.error(error)
|
|
throw error
|
|
}
|
|
}
|
|
|
|
export default { watch, bundle, output_path }
|