feat(webassets): take advantage of preloadmodule to improve performance

This commit is contained in:
Jack Westbrook
2025-03-03 09:50:30 +01:00
parent 762d9a0801
commit 12b2a63b55
5 changed files with 64 additions and 6 deletions
+3
View File
@@ -234,3 +234,6 @@ public/app/plugins/**/dist/
public/mockServiceWorker.js
/e2e/test-plugins/*/dist
# vite
stats.html
+1
View File
@@ -40,6 +40,7 @@ type IndexViewData struct {
type EntryPointAssets struct {
ContentDeliveryURL string `json:"cdn,omitempty"`
JSFiles []EntryPointAsset `json:"jsFiles"`
PreloadJSFiles []EntryPointAsset `json:"preloadJsFiles"`
// CSSFiles []EntryPointAsset `json:"cssFiles"`
Dark string `json:"dark"`
Light string `json:"light"`
+48 -4
View File
@@ -36,6 +36,8 @@ type ViteManifestEntry struct {
Src string `json:"src"`
}
type Manifest map[string]ViteManifestEntry
type EntryPointInfo struct {
Assets struct {
JS []string `json:"js,omitempty"`
@@ -135,13 +137,14 @@ func readWebAssetsFromCDN(ctx context.Context, baseURL string) (*dtos.EntryPoint
}
func readWebAssets(r io.Reader) (*dtos.EntryPointAssets, error) {
manifest := map[string]ViteManifestEntry{}
manifest := Manifest{}
if err := json.NewDecoder(r).Decode(&manifest); err != nil {
return nil, fmt.Errorf("failed to read assets-manifest.json %w", err)
}
// TODO: This is a temporary hack to get the entrypoints for the vite frontend loading.
var entryPointJSAssets []dtos.EntryPointAsset
var preloadJSAssets []dtos.EntryPointAsset
var darkCSS, lightCSS string
for _, entry := range manifest {
@@ -153,6 +156,7 @@ func readWebAssets(r io.Reader) (*dtos.EntryPointAssets, error) {
}
if strings.HasSuffix(entry.File, ".js") {
entryPointJSAssets = append(entryPointJSAssets, asset)
preloadJSAssets = getPreloadChunks(manifest, entry.Src)
}
if entry.Src == "sass/grafana.dark.scss" && entry.IsEntry {
darkCSS = entry.File
@@ -189,9 +193,11 @@ func readWebAssets(r io.Reader) (*dtos.EntryPointAssets, error) {
// }
rsp := &dtos.EntryPointAssets{
JSFiles: entryPointJSAssets,
Dark: darkCSS,
Light: lightCSS,
JSFiles: entryPointJSAssets,
PreloadJSFiles: preloadJSAssets,
Dark: darkCSS,
Light: lightCSS,
// TODO: Need to figure this out. Ideally the swagger assets are built in a separate build process.
// Swagger: make([]dtos.EntryPointAsset, 0, len(entryPoints.Swagger.Assets.JS)),
// SwaggerCSSFiles: make([]dtos.EntryPointAsset, 0, len(entryPoints.Swagger.Assets.CSS)),
}
@@ -222,3 +228,41 @@ func readWebAssets(r io.Reader) (*dtos.EntryPointAssets, error) {
// }
return rsp, nil
}
// Create a list of all the chunks that need to be preloaded for a given entrypoint.
func getPreloadChunks(manifest Manifest, name string) []dtos.EntryPointAsset {
seen := make(map[string]bool)
var getImportedChunks func(chunk ViteManifestEntry) []dtos.EntryPointAsset
getImportedChunks = func(chunk ViteManifestEntry) []dtos.EntryPointAsset {
var chunks []dtos.EntryPointAsset
for _, file := range chunk.Imports {
importee, exists := manifest[file]
if !exists {
continue
}
if seen[file] {
continue
}
seen[file] = true
chunks = append(chunks, getImportedChunks(importee)...)
chunks = append(chunks, dtos.EntryPointAsset{
FilePath: importee.File,
Integrity: "",
})
}
return chunks
}
entryChunk, exists := manifest[name]
if !exists {
return nil
}
return getImportedChunks(entryChunk)
}
+5 -2
View File
@@ -24,7 +24,8 @@ func TestReadWebassets(t *testing.T) {
}
],
"dark": "public/build/grafana-BwD1GyB5.css",
"light": "public/build/grafana-RC8BVZtE.css"
"light": "public/build/grafana-RC8BVZtE.css",
"preloadJsFiles": null
}`, string(dto))
assets.SetContentDeliveryURL("https://grafana-assets.grafana.net/grafana/10.3.0-64123/")
@@ -42,7 +43,8 @@ func TestReadWebassets(t *testing.T) {
}
],
"dark": "https://grafana-assets.grafana.net/grafana/10.3.0-64123/public/build/grafana-BwD1GyB5.css",
"light": "https://grafana-assets.grafana.net/grafana/10.3.0-64123/public/build/grafana-RC8BVZtE.css"
"light": "https://grafana-assets.grafana.net/grafana/10.3.0-64123/public/build/grafana-RC8BVZtE.css",
"preloadJsFiles": null
}`, string(dto))
}
@@ -86,5 +88,6 @@ func TestReadWebassetsFromCDN(t *testing.T) {
],
"dark": "https://grafana-assets.grafana.net/grafana/10.3.0-64123/public/build/grafana.dark.b44253d019cd9cb46428.css",
"light": "https://grafana-assets.grafana.net/grafana/10.3.0-64123/public/build/grafana.light.e8e11c59b604d62836be.css"
"preloadJsFiles": null
}`, string(dto))
}
+7
View File
@@ -29,6 +29,13 @@
performance.mark('frontend_boot_css_time_seconds');
</script>
[[range $asset := .Assets.PreloadJSFiles]]
<link
rel="modulepreload"
href="[[$asset.FilePath]]"
></script>
[[end]]
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />