diff --git a/.gitignore b/.gitignore index 611ba66e439..ba113e0e744 100644 --- a/.gitignore +++ b/.gitignore @@ -234,3 +234,6 @@ public/app/plugins/**/dist/ public/mockServiceWorker.js /e2e/test-plugins/*/dist + +# vite +stats.html diff --git a/pkg/api/dtos/index.go b/pkg/api/dtos/index.go index 93d967e3402..f1403c3138e 100644 --- a/pkg/api/dtos/index.go +++ b/pkg/api/dtos/index.go @@ -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"` diff --git a/pkg/api/webassets/webassets.go b/pkg/api/webassets/webassets.go index d78c9ba0ed6..8ebf45ce538 100644 --- a/pkg/api/webassets/webassets.go +++ b/pkg/api/webassets/webassets.go @@ -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) +} diff --git a/pkg/api/webassets/webassets_test.go b/pkg/api/webassets/webassets_test.go index 9d899eec874..60488544f91 100644 --- a/pkg/api/webassets/webassets_test.go +++ b/pkg/api/webassets/webassets_test.go @@ -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)) } diff --git a/public/views/index.html b/public/views/index.html index 9a0d061e5cd..a8c3b81b1de 100644 --- a/public/views/index.html +++ b/public/views/index.html @@ -29,6 +29,13 @@ performance.mark('frontend_boot_css_time_seconds'); + [[range $asset := .Assets.PreloadJSFiles]] + + [[end]] +