diff --git a/.gitignore b/.gitignore index 85dafe0..66ccee7 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,4 @@ node_modules dist .idea coverage -.vscode -assets/dist \ No newline at end of file +.vscode \ No newline at end of file diff --git a/scripts/dev-server.ts b/scripts/dev-server.ts index 6ae68da..ee79fd7 100644 --- a/scripts/dev-server.ts +++ b/scripts/dev-server.ts @@ -2,7 +2,7 @@ import * as esbuild from 'esbuild' import {buildOptions, generateIndexHtml} from './esbuild-shared' async function main() { - const outdir = 'assets/dist' + const outdir = 'dist' let ctx = await esbuild.context({ ...buildOptions, outdir, diff --git a/scripts/esbuild-shared.ts b/scripts/esbuild-shared.ts index c1fc7d8..77e88c2 100644 --- a/scripts/esbuild-shared.ts +++ b/scripts/esbuild-shared.ts @@ -5,24 +5,51 @@ import * as esbuild from 'esbuild' const entryPoint = 'src/speedscope.tsx' export const buildOptions: esbuild.BuildOptions = { - entryPoints: [entryPoint], + entryPoints: [ + entryPoint, + + // This is a kind of silly way to ensure that all of these files end up being + // discovered by esbuild and copied into the output directory + 'assets/favicon-16x16.png', + 'assets/favicon-32x32.png', + 'assets/favicon.ico', + ], entryNames: '[name]-[hash]', chunkNames: '[name]-[hash]', + assetNames: '[name]-[hash]', bundle: true, format: 'esm', splitting: true, loader: { '.txt': 'file', + '.woff2': 'file', + '.png': 'file', + '.ico': 'file', }, } export const generateIndexHtml = (buildResult: esbuild.BuildResult, outdir: string) => { const outputs = buildResult.metafile!.outputs - const mainChunkPath = Object.keys(outputs).find(key => outputs[key].entryPoint === entryPoint)! + function getOutput(entryPoint: string): [string, esbuild.Metafile['outputs'][string]] { + const key = Object.keys(outputs).find(key => outputs[key].entryPoint === entryPoint)! + return [key, outputs[key]] + } + + function getHashedFilePath(name: string) { + return path.basename(getOutput(name)[1].imports.find(i => i.kind === 'file-loader')!.path) + } + + const [mainChunkPath, mainChunk] = getOutput(entryPoint) const mainChunkName = path.basename(mainChunkPath) - const mainChunk = outputs[mainChunkPath] + const mainChunkCssPath = mainChunk.cssBundle! + + const cssChunk = outputs[mainChunkCssPath] + + const fontPath = cssChunk.imports.find(i => i.path.endsWith('.woff2'))!.path + const fontName = path.basename(fontPath) + const syncDependencyNames = mainChunk.imports .filter(i => i.kind === 'import-statement') .map(i => path.basename(i.path)) @@ -30,6 +57,10 @@ export const generateIndexHtml = (buildResult: esbuild.BuildResult, outdir: stri .filter(i => i.kind === 'dynamic-import') .map(i => path.basename(i.path)) + const favicon16x16Path = getHashedFilePath('assets/favicon-16x16.png') + const favicon32x32Path = getHashedFilePath('assets/favicon-32x32.png') + const faviconIcoPath = getHashedFilePath('assets/favicon.ico') + const html = `
@@ -37,10 +68,10 @@ export const generateIndexHtml = (buildResult: esbuild.BuildResult, outdir: stri