mirror of https://github.com/grafana/grafana
Plugins: Improve frontend loader cache (#87488)
* 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>pull/88895/head
parent
897b81e566
commit
036c878843
@ -1,54 +1,64 @@ |
||||
import * as pluginSettings from '../pluginSettings'; |
||||
import { registerPluginInCache, invalidatePluginInCache, resolveWithCache, getPluginFromCache } from './cache'; |
||||
|
||||
import { invalidatePluginInCache, resolveWithCache, registerPluginInCache } from './cache'; |
||||
jest.mock('./constants', () => ({ |
||||
CACHE_INITIALISED_AT: 123456, |
||||
})); |
||||
|
||||
describe('Plugin Cache', () => { |
||||
const now = 12345; |
||||
describe('Cache Functions', () => { |
||||
describe('registerPluginInCache', () => { |
||||
it('should register a plugin in the cache', () => { |
||||
const plugin = { pluginId: 'plugin1', version: '1.0.0', isAngular: false }; |
||||
registerPluginInCache(plugin); |
||||
expect(getPluginFromCache('plugin1')).toEqual(plugin); |
||||
}); |
||||
|
||||
it('should append plugin version as cache flag if plugin is registered in buster', () => { |
||||
const slug = 'bubble-chart-1'; |
||||
const version = 'v1.0.0'; |
||||
const path = `/public/plugins/${slug}/module.js`; |
||||
const address = `http://localhost:3000/public/${path}.js`; |
||||
|
||||
registerPluginInCache({ path, version }); |
||||
|
||||
const url = `${address}?_cache=${encodeURI(version)}`; |
||||
expect(resolveWithCache(address, now)).toBe(url); |
||||
it('should not register a plugin if it already exists in the cache', () => { |
||||
const pluginId = 'plugin2'; |
||||
const plugin = { pluginId, version: '2.0.0' }; |
||||
registerPluginInCache(plugin); |
||||
const plugin2 = { pluginId, version: '2.5.0' }; |
||||
registerPluginInCache(plugin2); |
||||
expect(getPluginFromCache(pluginId)?.version).toBe('2.0.0'); |
||||
}); |
||||
}); |
||||
|
||||
it('should append Date.now as cache flag if plugin is not registered in buster', () => { |
||||
const slug = 'bubble-chart-2'; |
||||
const address = `http://localhost:3000/public/plugins/${slug}/module.js`; |
||||
describe('invalidatePluginInCache', () => { |
||||
it('should invalidate a plugin in the cache', () => { |
||||
const pluginId = 'plugin3'; |
||||
const plugin = { pluginId, version: '3.0.0' }; |
||||
registerPluginInCache(plugin); |
||||
invalidatePluginInCache(pluginId); |
||||
expect(getPluginFromCache(pluginId)).toBeUndefined(); |
||||
}); |
||||
|
||||
const url = `${address}?_cache=${encodeURI(String(now))}`; |
||||
expect(resolveWithCache(address, now)).toBe(url); |
||||
it('should not throw an error if the plugin does not exist in the cache', () => { |
||||
expect(() => invalidatePluginInCache('nonExistentPlugin')).not.toThrow(); |
||||
}); |
||||
}); |
||||
|
||||
it('should append Date.now as cache flag if plugin is invalidated in buster', () => { |
||||
const slug = 'bubble-chart-3'; |
||||
const version = 'v1.0.0'; |
||||
const path = `/public/plugins/${slug}/module.js`; |
||||
const address = `http://localhost:3000/public/${path}.js`; |
||||
|
||||
registerPluginInCache({ path, version }); |
||||
invalidatePluginInCache(slug); |
||||
describe('resolveWithCache', () => { |
||||
it('should resolve URL with timestamp cache bust parameter if plugin is not available in the cache', () => { |
||||
const url = 'http://localhost:3000/public/plugins/plugin4/module.js'; |
||||
expect(resolveWithCache(url)).toContain('_cache=123456'); |
||||
}); |
||||
|
||||
const url = `${address}?_cache=${encodeURI(String(now))}`; |
||||
expect(resolveWithCache(address, now)).toBe(url); |
||||
it('should resolve URL with plugin version as cache bust parameter if available', () => { |
||||
const plugin = { pluginId: 'plugin5', version: '5.0.0' }; |
||||
registerPluginInCache(plugin); |
||||
const url = 'http://localhost:3000/public/plugins/plugin5/module.js'; |
||||
expect(resolveWithCache(url)).toContain('_cache=5.0.0'); |
||||
}); |
||||
}); |
||||
|
||||
it('should also clear plugin settings cache', () => { |
||||
const slug = 'bubble-chart-3'; |
||||
const version = 'v1.0.0'; |
||||
const path = `/public/plugins/${slug}/module.js`; |
||||
|
||||
const clearPluginSettingsCacheSpy = jest.spyOn(pluginSettings, 'clearPluginSettingsCache'); |
||||
|
||||
registerPluginInCache({ path, version }); |
||||
invalidatePluginInCache(slug); |
||||
describe('getPluginFromCache', () => { |
||||
it('should return plugin from cache if exists', () => { |
||||
const plugin = { pluginId: 'plugin6', version: '6.0.0' }; |
||||
registerPluginInCache(plugin); |
||||
expect(getPluginFromCache('plugin6')).toEqual(plugin); |
||||
}); |
||||
|
||||
expect(clearPluginSettingsCacheSpy).toBeCalledTimes(1); |
||||
expect(clearPluginSettingsCacheSpy).toBeCalledWith('bubble-chart-3'); |
||||
it('should return undefined if plugin does not exist in cache', () => { |
||||
expect(getPluginFromCache('nonExistentPlugin')).toBeUndefined(); |
||||
}); |
||||
}); |
||||
}); |
||||
|
@ -1,3 +1,4 @@ |
||||
export const SHARED_DEPENDENCY_PREFIX = 'package'; |
||||
export const LOAD_PLUGIN_CSS_REGEX = /^plugins.+\.css$/i; |
||||
export const JS_CONTENT_TYPE_REGEX = /^(text|application)\/(x-)?javascript(;|$)/; |
||||
export const CACHE_INITIALISED_AT = Date.now(); |
||||
|
Loading…
Reference in new issue