Files
Jack Westbrook 892a50a3b7 Performance: Load shared frontend plugin dependencies on demand (#87644)
* feat(plugins): only load shared plugin dependencies when needed

* feat(plugins): add react-redux and fix up comments

* feat(plugins): attempt to load async deps in fe sandbox

* feat(frontend): defer script execution to prevent systemjs from loading app.js
2024-08-27 15:10:26 +02:00

69 lines
1.9 KiB
TypeScript

import { config } from '@grafana/runtime';
import { sandboxPluginDependencies } from '../sandbox/plugin_dependencies';
import { SHARED_DEPENDENCY_PREFIX } from './constants';
import { SystemJS } from './systemjs';
export function buildImportMap(importMap: Record<string, System.Module>) {
return Object.keys(importMap).reduce<Record<string, string>>((acc, key) => {
// Use the 'package:' prefix to act as a URL instead of a bare specifier
const module_name = `${SHARED_DEPENDENCY_PREFIX}:${key}`;
// expose dependency to loaders
addPreload(module_name, importMap[key]);
sandboxPluginDependencies.set(key, importMap[key]);
acc[key] = module_name;
return acc;
}, {});
}
function addPreload(id: string, preload: (() => Promise<System.Module>) | System.Module) {
if (SystemJS.has(id)) {
return;
}
let resolvedId;
try {
resolvedId = SystemJS.resolve(id);
} catch (e) {
console.log(e);
}
if (resolvedId && SystemJS.has(resolvedId)) {
return;
}
const moduleId = resolvedId || id;
if (typeof preload === 'function') {
SystemJS.register(id, [], (_export) => {
return {
execute: async function () {
const module = await preload();
_export(module);
},
};
});
} else {
SystemJS.set(moduleId, preload);
}
}
export function isHostedOnCDN(path: string) {
return Boolean(config.pluginsCDNBaseURL) && path.startsWith(config.pluginsCDNBaseURL);
}
// This function is used to dynamically prepend the appSubUrl in the frontend.
// This is required because if serve_from_sub_path is false the Image Renderer sets the subpath
// to an empty string and sets appurl to localhost which causes plugins to fail to load.
// https://github.com/grafana/grafana/issues/76180
export function resolveModulePath(path: string) {
if (path.startsWith('http') || path.startsWith('/')) {
return path;
}
return `${config.appSubUrl ?? ''}/${path}`;
}