• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

jlfwong / speedscope / 12798388985

15 Jan 2025 10:47PM UTC coverage: 43.366% (-0.3%) from 43.693%
12798388985

push

github

web-flow
Switch from parcel to esbuild (#432)

1189 of 2825 branches covered (42.09%)

Branch coverage included in aggregate %.

0 of 64 new or added lines in 4 files covered. (0.0%)

1 existing line in 1 file now uncovered.

2707 of 6159 relevant lines covered (43.95%)

4013.5 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/scripts/esbuild-shared.ts
NEW
1
import * as fs from 'fs'
×
NEW
2
import * as path from 'path'
×
3
import * as esbuild from 'esbuild'
4

NEW
5
const entryPoint = 'src/speedscope.tsx'
×
6

NEW
7
export const buildOptions: esbuild.BuildOptions = {
×
8
  entryPoints: [
9
    entryPoint,
10

11
    // This is a kind of silly way to ensure that all of these files end up being
12
    // discovered by esbuild and copied into the output directory
13
    'assets/favicon-16x16.png',
14
    'assets/favicon-32x32.png',
15
    'assets/favicon.ico',
16
  ],
17
  entryNames: '[name]-[hash]',
18
  chunkNames: '[name]-[hash]',
19
  assetNames: '[name]-[hash]',
20
  sourcemap: true,
21
  bundle: true,
22
  format: 'esm',
23
  splitting: true,
24
  loader: {
25
    '.txt': 'file',
26
    '.woff2': 'file',
27
    '.png': 'file',
28
    '.ico': 'file',
29
  },
30
}
31

32
interface GenerateIndexHtmlOptions {
33
  buildResult: esbuild.BuildResult
34
  outdir: string
35
  servingProtocol: 'file' | 'http'
36
}
37

NEW
38
export const generateIndexHtml = ({
×
39
  buildResult,
40
  outdir,
41
  servingProtocol,
42
}: GenerateIndexHtmlOptions) => {
NEW
43
  const outputs = buildResult.metafile!.outputs
×
44

45
  function getOutput(entryPoint: string): [string, esbuild.Metafile['outputs'][string]] {
NEW
46
    const key = Object.keys(outputs).find(key => outputs[key].entryPoint === entryPoint)!
×
NEW
47
    return [key, outputs[key]]
×
48
  }
49

50
  function getHashedFilePath(name: string) {
NEW
51
    return path.basename(getOutput(name)[1].imports.find(i => i.kind === 'file-loader')!.path)
×
52
  }
53

NEW
54
  const [mainChunkPath, mainChunk] = getOutput(entryPoint)
×
NEW
55
  const mainChunkName = path.basename(mainChunkPath)
×
56

NEW
57
  const mainChunkCssPath = mainChunk.cssBundle!
×
NEW
58
  const cssChunk = outputs[mainChunkCssPath]
×
59

NEW
60
  const fontPath = cssChunk.imports.find(i => i.path.endsWith('.woff2'))!.path
×
NEW
61
  const fontName = path.basename(fontPath)
×
62

NEW
63
  const syncDependencyNames = mainChunk.imports
×
NEW
64
    .filter(i => i.kind === 'import-statement')
×
NEW
65
    .map(i => path.basename(i.path))
×
NEW
66
  const asyncDependencyNames = mainChunk.imports
×
NEW
67
    .filter(i => i.kind === 'dynamic-import')
×
NEW
68
    .map(i => path.basename(i.path))
×
69

70
  // If we're serving from a file protocol, we can't use module
71
  // scripts
NEW
72
  const scriptType = servingProtocol === 'file' ? '' : ' type="module"'
×
73

NEW
74
  const favicon16x16Path = getHashedFilePath('assets/favicon-16x16.png')
×
NEW
75
  const favicon32x32Path = getHashedFilePath('assets/favicon-32x32.png')
×
NEW
76
  const faviconIcoPath = getHashedFilePath('assets/favicon.ico')
×
77

NEW
78
  const html = `<!DOCTYPE html>
×
79
<html>
80
  <head>
81
    <meta charset="UTF-8">
82
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
83
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
84
    <title>speedscope</title>
85
    <link rel="stylesheet" href="${path.basename(mainChunk.cssBundle!)}">
86
    <link rel="icon" type="image/png" sizes="32x32" href="${favicon32x32Path}">
87
    <link rel="icon" type="image/png" sizes="16x16" href="${favicon16x16Path}">
88
    <link rel="icon" type="image/x-icon" href="${faviconIcoPath}">
89
  </head>
90
  <body>
91
    <script src="${mainChunkName}"${scriptType}></script>
NEW
92
    ${syncDependencyNames.map(dep => `<script src="${dep}"${scriptType}></script>`).join('\n    ')}
×
93
    ${asyncDependencyNames
94
      .map(
95
        dep =>
NEW
96
          `<script src="${dep}"${scriptType}${
×
97
            servingProtocol === 'file' ? '' : ' async'
×
98
          }></script>`,
99
      )
100
      .join('\n    ')}
101
    ${
102
      /* Preload is blocked by CORS, so we can't use it with file:/// URLs */
103
      servingProtocol === 'file'
104
        ? ''
×
105
        : `<link rel="preload" href="${fontName}" as="font" type="font/woff2" crossorigin>`
106
    }
107
  </body>
108
</html>
109
`
110

NEW
111
  fs.writeFileSync(`${outdir}/index.html`, html)
×
112
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc