feat(webassets): take advantage of preloadmodule to improve performance
This commit is contained in:
@@ -234,3 +234,6 @@ public/app/plugins/**/dist/
|
||||
public/mockServiceWorker.js
|
||||
|
||||
/e2e/test-plugins/*/dist
|
||||
|
||||
# vite
|
||||
stats.html
|
||||
|
||||
@@ -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"`
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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" />
|
||||
|
||||
Reference in New Issue
Block a user