mirror of
https://github.com/grafana/grafana.git
synced 2025-08-02 23:53:10 +08:00

* do it * set empty child version to parent version * feat(plugins): use pluginId for loader cache keys * feat(plugins): apply caching to all js and css files systemjs loads * remove old code and add comment * test(plugins): update systemjs hooks tests in line with better caching * test(plugins): wip - comment out failing backend loader tests * fix tests and improve comment * Update public/app/features/plugins/loader/cache.test.ts Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com> --------- Co-authored-by: Will Browne <will.browne@grafana.com> Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com>
88 lines
3.3 KiB
TypeScript
88 lines
3.3 KiB
TypeScript
import { config } from '@grafana/runtime';
|
|
|
|
import { transformPluginSourceForCDN } from '../cdn/utils';
|
|
|
|
import { resolveWithCache } from './cache';
|
|
import { LOAD_PLUGIN_CSS_REGEX, JS_CONTENT_TYPE_REGEX, SHARED_DEPENDENCY_PREFIX } from './constants';
|
|
import { SystemJS } from './systemjs';
|
|
import { SystemJSWithLoaderHooks } from './types';
|
|
import { isHostedOnCDN } from './utils';
|
|
|
|
export async function decorateSystemJSFetch(
|
|
systemJSFetch: SystemJSWithLoaderHooks['fetch'],
|
|
url: string,
|
|
options?: Record<string, unknown>
|
|
) {
|
|
const res = await systemJSFetch(url, options);
|
|
const contentType = res.headers.get('content-type') || '';
|
|
|
|
if (JS_CONTENT_TYPE_REGEX.test(contentType)) {
|
|
const source = await res.text();
|
|
let transformedSrc = source;
|
|
|
|
// JS files on the CDN need their asset paths transformed in the source
|
|
if (isHostedOnCDN(res.url)) {
|
|
const cdnTransformedSrc = transformPluginSourceForCDN({ url: res.url, source: transformedSrc });
|
|
return new Response(new Blob([cdnTransformedSrc], { type: 'text/javascript' }));
|
|
}
|
|
|
|
return new Response(new Blob([transformedSrc], { type: 'text/javascript' }));
|
|
}
|
|
return res;
|
|
}
|
|
|
|
export function decorateSystemJSResolve(
|
|
this: SystemJSWithLoaderHooks,
|
|
originalResolve: SystemJSWithLoaderHooks['resolve'],
|
|
id: string,
|
|
parentUrl?: string
|
|
) {
|
|
try {
|
|
const url = originalResolve.apply(this, [id, parentUrl]);
|
|
const cleanedUrl = getBackWardsCompatibleUrl(url);
|
|
const isFileSystemModule =
|
|
(cleanedUrl.endsWith('.js') || cleanedUrl.endsWith('.css')) && !isHostedOnCDN(cleanedUrl);
|
|
// Add a cache query param for filesystem module.js requests
|
|
// CDN hosted plugins contain the version in the path so skip
|
|
return isFileSystemModule ? resolveWithCache(cleanedUrl) : cleanedUrl;
|
|
} catch (err) {
|
|
// Provide fallback for plugins that use `loadPluginCss` to load theme styles
|
|
// Regex only targets plugins on the filesystem.
|
|
if (LOAD_PLUGIN_CSS_REGEX.test(id)) {
|
|
const prefixId = `${config.appSubUrl ?? ''}/public/${id}`;
|
|
const url = originalResolve.apply(this, [prefixId, parentUrl]);
|
|
return resolveWithCache(url);
|
|
}
|
|
console.warn(`SystemJS: failed to resolve '${id}'`);
|
|
return id;
|
|
}
|
|
}
|
|
|
|
export function decorateSystemJsOnload(err: unknown, id: string) {
|
|
// IF the url is relative resolve to current origin, absolute urls passed in will ignore base.
|
|
const url = new URL(id, window.location.origin);
|
|
if (url.pathname.endsWith('.css') && !err) {
|
|
const module = SystemJS.get(id);
|
|
const styles = module?.default;
|
|
if (styles) {
|
|
document.adoptedStyleSheets = [...document.adoptedStyleSheets, styles];
|
|
}
|
|
}
|
|
}
|
|
|
|
// This function handles the following legacy SystemJS functionality:
|
|
// - strips legacy loader wildcard from urls
|
|
// - support config.defaultExtension for System.register deps that lack an extension (e.g. './my_ctrl')
|
|
function getBackWardsCompatibleUrl(url: string) {
|
|
if (url.startsWith(`${SHARED_DEPENDENCY_PREFIX}:`)) {
|
|
return url;
|
|
}
|
|
if (url.endsWith('!')) {
|
|
url = url.slice(0, -1);
|
|
}
|
|
const systemJSFileExtensions = ['css', 'js', 'json', 'wasm'];
|
|
const hasValidFileExtension = systemJSFileExtensions.some((extensionName) => url.endsWith(extensionName));
|
|
|
|
return hasValidFileExtension ? url : url + '.js';
|
|
}
|