diff --git a/.esbuild/build.ts b/.esbuild/build.ts index 39ac2978a..2b8734ad8 100644 --- a/.esbuild/build.ts +++ b/.esbuild/build.ts @@ -1,40 +1,47 @@ import { build } from 'esbuild'; import { mkdir, writeFile } from 'node:fs/promises'; -import { getBuildConfig } from './util.js'; +import { MermaidBuildOptions, defaultConfig, getBuildConfig } from './util.js'; import { packageOptions } from '../.build/common.js'; const shouldVisualize = process.argv.includes('--visualize'); const buildPackage = async (entryName: keyof typeof packageOptions) => { - // package.mjs - await build(getBuildConfig({ entryName, minify: false })); - // package.min.mjs - const { metafile } = await build( - getBuildConfig({ entryName, minify: true, metafile: shouldVisualize }) - ); - if (metafile) { - // Upload metafile into https://esbuild.github.io/analyze/ - await writeFile(`stats/meta-${entryName}.json`, JSON.stringify(metafile)); - } - // package.core.mjs - await build(getBuildConfig({ entryName, minify: false, core: true })); + const commonConfig = { ...defaultConfig, entryName }; + const configs = [ + { ...commonConfig }, + { + ...commonConfig, + minify: true, + metafile: shouldVisualize, + }, + { ...commonConfig, core: true }, + ]; + if (entryName === 'mermaid') { - // mermaid.js - await build(getBuildConfig({ entryName, minify: false, format: 'iife' })); - // mermaid.min.js - await build(getBuildConfig({ entryName, minify: true, format: 'iife' })); - // mermaid.tiny.min.js - const { metafile } = await build( - getBuildConfig({ - entryName, + const iifeConfig: MermaidBuildOptions = { ...commonConfig, format: 'iife' }; + configs.push( + { ...iifeConfig }, + { ...iifeConfig, minify: true }, + { + ...iifeConfig, minify: true, includeLargeDiagrams: false, metafile: shouldVisualize, - format: 'iife', - }) + } ); - if (metafile) { - await writeFile(`stats/meta-${entryName}-tiny.json`, JSON.stringify(metafile)); + } + + const results = await Promise.all(configs.map((config) => build(getBuildConfig(config)))); + + if (shouldVisualize) { + for (const { metafile } of results) { + if (!metafile) { + continue; + } + const fileName = Object.keys(metafile.outputs) + .filter((key) => key.includes('.min') && key.endsWith('js'))[0] + .replace('dist/', ''); + await writeFile(`stats/${fileName}.meta.json`, JSON.stringify(metafile)); } } }; @@ -47,9 +54,7 @@ const handler = (e) => { const main = async () => { await mkdir('stats').catch(() => {}); const packageNames = Object.keys(packageOptions) as (keyof typeof packageOptions)[]; - for (const pkg of packageNames) { - await buildPackage(pkg).catch(handler); - } + await Promise.allSettled(packageNames.map((pkg) => buildPackage(pkg).catch(handler))); }; void main(); diff --git a/.esbuild/util.ts b/.esbuild/util.ts index 12ccc5807..f80368a06 100644 --- a/.esbuild/util.ts +++ b/.esbuild/util.ts @@ -8,15 +8,23 @@ import { jisonPlugin } from './jisonPlugin.js'; const __dirname = fileURLToPath(new URL('.', import.meta.url)); -interface MermaidBuildOptions { +export interface MermaidBuildOptions { minify: boolean; - core?: boolean; - metafile?: boolean; - format?: 'esm' | 'iife'; + core: boolean; + metafile: boolean; + format: 'esm' | 'iife'; entryName: keyof typeof packageOptions; - includeLargeDiagrams?: boolean; + includeLargeDiagrams: boolean; } +export const defaultConfig: Omit = { + minify: false, + metafile: false, + core: false, + format: 'esm', + includeLargeDiagrams: true, +} as const; + const buildOptions = (override: BuildOptions): BuildOptions => { return { bundle: true, @@ -33,25 +41,38 @@ const buildOptions = (override: BuildOptions): BuildOptions => { }; }; -export const getBuildConfig = ({ - minify, - core, - entryName, - metafile, - format = 'esm', - includeLargeDiagrams = true, -}: MermaidBuildOptions): BuildOptions => { +const getFileName = ( + fileName: string, + { core, format, includeLargeDiagrams, minify, entryName }: MermaidBuildOptions +) => { + if (core) { + fileName += '.core'; + } + if (format === 'esm') { + fileName += '.esm'; + } + if (!includeLargeDiagrams) { + fileName += '.tiny'; + } + if (minify) { + fileName += '.min'; + } + return fileName; +}; + +export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => { + const { core, entryName, metafile, format, includeLargeDiagrams } = options; const external: string[] = ['require', 'fs', 'path']; const { name, file, packageName } = packageOptions[entryName]; + const outFileName = getFileName(name, options); let output: BuildOptions = buildOptions({ absWorkingDir: resolve(__dirname, `../packages/${packageName}`), entryPoints: { - [`${name}${core ? '.core' : format === 'iife' ? '' : '.esm'}${ - includeLargeDiagrams ? '' : '.tiny' - }${minify ? '.min' : ''}`]: `src/${file}`, + [outFileName]: `src/${file}`, }, metafile, logLevel: 'info', + chunkNames: `chunks/${outFileName}/[name]-[hash]`, define: { // This needs to be stringified for esbuild includeLargeDiagrams: `${includeLargeDiagrams}`,