Skip to content
This repository has been archived by the owner on Mar 31, 2024. It is now read-only.

Commit

Permalink
[kbn/optimizer] link to kibanaReact/kibanaUtils plugins (elastic#62720)
Browse files Browse the repository at this point in the history
* [kbn/optimizer] link to data/kibanaReact/kibanaUtils plugins

* depend on normalize-path package

* typos

* avoid loading kibanaUtils and kibanaReact from urls

* update types and tests, now that whole plugin is exported to window

* update snapshot, removed export of `plugins` property

* fix condition, ignore things NOT in data/react/utils

* make es_ui_shared a "static bundle" too

* move kibana_utils/common usage to /public

* convert some more /common usage to /public

* use async-download/ordered-execution for bootstrap script

* fix typo

* remove kibanaUtils bundle

* remove kibanaReact bundle

* Revert "remove kibanaReact bundle"

This reverts commit f14e9ee.

* Revert "remove kibanaUtils bundle"

This reverts commit a64b2a7.

* stop linking to the data plugin

* add comment pointing to async-download info

Co-authored-by: spalger <spalger@users.noreply.github.com>
Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
  • Loading branch information
3 people committed Apr 8, 2020
1 parent b545619 commit 8d3bced
Show file tree
Hide file tree
Showing 29 changed files with 182 additions and 78 deletions.
1 change: 1 addition & 0 deletions packages/kbn-optimizer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"json-stable-stringify": "^1.0.1",
"loader-utils": "^1.2.3",
"node-sass": "^4.13.0",
"normalize-path": "^3.0.0",
"postcss-loader": "^3.0.0",
"raw-loader": "^3.1.0",
"resolve-url-loader": "^3.1.1",
Expand Down

Large diffs are not rendered by default.

68 changes: 64 additions & 4 deletions packages/kbn-optimizer/src/worker/webpack.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import Path from 'path';

import normalizePath from 'normalize-path';
import { stringifyRequest } from 'loader-utils';
import webpack from 'webpack';
// @ts-ignore
Expand All @@ -34,6 +35,59 @@ import { Bundle, WorkerConfig, parseDirPath, DisallowedSyntaxPlugin } from '../c
const PUBLIC_PATH_PLACEHOLDER = '__REPLACE_WITH_PUBLIC_PATH__';
const BABEL_PRESET_PATH = require.resolve('@kbn/babel-preset/webpack_preset');

const STATIC_BUNDLE_PLUGINS = [
// { id: 'data', dirname: 'data' },
{ id: 'kibanaReact', dirname: 'kibana_react' },
{ id: 'kibanaUtils', dirname: 'kibana_utils' },
{ id: 'esUiShared', dirname: 'es_ui_shared' },
];

/**
* Determine externals statements for require/import statements by looking
* for requests resolving to the primary public export of the data, kibanaReact,
* amd kibanaUtils plugins. If this module is being imported then rewrite
* the import to access the global `__kbnBundles__` variables and access
* the relavent properties from that global object.
*
* @param bundle
* @param context the directory containing the module which made `request`
* @param request the request for a module from a commonjs require() call or import statement
*/
function dynamicExternals(bundle: Bundle, context: string, request: string) {
// ignore imports that have loaders defined
if (request.includes('!')) {
return;
}

// don't allow any static bundle to rely on other static bundles
if (STATIC_BUNDLE_PLUGINS.some(p => bundle.id === p.id)) {
return;
}

// ignore requests that don't include a /data/public, /kibana_react/public, or
// /kibana_utils/public segment as a cheap way to avoid doing path resolution
// for paths that couldn't possibly resolve to what we're looking for
const reqToStaticBundle = STATIC_BUNDLE_PLUGINS.some(p =>
request.includes(`/${p.dirname}/public`)
);
if (!reqToStaticBundle) {
return;
}

// determine the most acurate resolution string we can without running full resolution
const rootRelative = normalizePath(
Path.relative(bundle.sourceRoot, Path.resolve(context, request))
);
for (const { id, dirname } of STATIC_BUNDLE_PLUGINS) {
if (rootRelative === `src/plugins/${dirname}/public`) {
return `__kbnBundles__['plugin/${id}']`;
}
}

// import doesn't match a root public import
return undefined;
}

export function getWebpackConfig(bundle: Bundle, worker: WorkerConfig) {
const commonConfig: webpack.Configuration = {
node: { fs: 'empty' },
Expand Down Expand Up @@ -61,7 +115,6 @@ export function getWebpackConfig(bundle: Bundle, worker: WorkerConfig) {
// When the entry point is loaded, assign it's exported `plugin`
// value to a key on the global `__kbnBundles__` object.
library: ['__kbnBundles__', `plugin/${bundle.id}`],
libraryExport: 'plugin',
}
: {}),
},
Expand All @@ -70,9 +123,16 @@ export function getWebpackConfig(bundle: Bundle, worker: WorkerConfig) {
noEmitOnErrors: true,
},

externals: {
...UiSharedDeps.externals,
},
externals: [
UiSharedDeps.externals,
function(context, request, cb) {
try {
cb(undefined, dynamicExternals(bundle, context, request));
} catch (error) {
cb(error, undefined);
}
},
],

plugins: [new CleanWebpackPlugin(), new DisallowedSyntaxPlugin()],

Expand Down
7 changes: 7 additions & 0 deletions packages/kbn-ui-shared-deps/polyfills.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@
require('core-js/stable');
require('regenerator-runtime/runtime');
require('custom-event-polyfill');

if (typeof window.Event === 'object') {
// IE11 doesn't support unknown event types, required by react-use
// https://github.com/streamich/react-use/issues/73
window.Event = CustomEvent;
}

require('whatwg-fetch');
require('abortcontroller-polyfill/dist/polyfill-patch-fetch');
require('./vendor/childnode_remove_polyfill');
Expand Down
2 changes: 1 addition & 1 deletion src/core/public/plugins/plugin_loader.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ test('`loadPluginBundles` creates a script tag and loads initializer', async ()

// Setup a fake initializer as if a plugin bundle had actually been loaded.
const fakeInitializer = jest.fn();
coreWindow.__kbnBundles__['plugin/plugin-a'] = fakeInitializer;
coreWindow.__kbnBundles__['plugin/plugin-a'] = { plugin: fakeInitializer };
// Call the onload callback
fakeScriptTag.onload();
await expect(loadPromise).resolves.toEqual(fakeInitializer);
Expand Down
33 changes: 22 additions & 11 deletions src/core/public/plugins/plugin_loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export type UnknownPluginInitializer = PluginInitializer<unknown, Record<string,
*/
export interface CoreWindow {
__kbnBundles__: {
[pluginBundleName: string]: UnknownPluginInitializer | undefined;
[pluginBundleName: string]: { plugin: UnknownPluginInitializer } | undefined;
};
}

Expand Down Expand Up @@ -70,9 +70,28 @@ export const loadPluginBundle: LoadPluginBundle = <
) =>
new Promise<PluginInitializer<TSetup, TStart, TPluginsSetup, TPluginsStart>>(
(resolve, reject) => {
const script = document.createElement('script');
const coreWindow = (window as unknown) as CoreWindow;
const exportId = `plugin/${pluginName}`;

const readPluginExport = () => {
const PluginExport: any = coreWindow.__kbnBundles__[exportId];
if (typeof PluginExport?.plugin !== 'function') {
reject(
new Error(`Definition of plugin "${pluginName}" should be a function (${bundlePath}).`)
);
} else {
resolve(
PluginExport.plugin as PluginInitializer<TSetup, TStart, TPluginsSetup, TPluginsStart>
);
}
};

if (coreWindow.__kbnBundles__[exportId]) {
readPluginExport();
return;
}

const script = document.createElement('script');
// Assumes that all plugin bundles get put into the bundles/plugins subdirectory
const bundlePath = addBasePath(`/bundles/plugin/${pluginName}/${pluginName}.plugin.js`);
script.setAttribute('src', bundlePath);
Expand All @@ -89,15 +108,7 @@ export const loadPluginBundle: LoadPluginBundle = <
// Wire up resolve and reject
script.onload = () => {
cleanupTag();

const initializer = coreWindow.__kbnBundles__[`plugin/${pluginName}`];
if (!initializer || typeof initializer !== 'function') {
reject(
new Error(`Definition of plugin "${pluginName}" should be a function (${bundlePath}).`)
);
} else {
resolve(initializer as PluginInitializer<TSetup, TStart, TPluginsSetup, TPluginsStart>);
}
readPluginExport();
};

script.onerror = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { createInputControlVisController } from './vis_controller';
import { getControlsTab } from './components/editor/controls_tab';
import { OptionsTab } from './components/editor/options_tab';
import { InputControlVisDependencies } from './plugin';
import { defaultFeedbackMessage } from '../../../../plugins/kibana_utils/common';
import { defaultFeedbackMessage } from '../../../../plugins/kibana_utils/public';

export function createInputControlVisTypeDefinition(deps: InputControlVisDependencies) {
const InputControlVisController = createInputControlVisController(deps);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
* under the License.
*/
import { DiscoverServices } from './build_services';
import { createGetterSetter } from '../../../../../plugins/kibana_utils/public';
import { search } from '../../../../../plugins/data/public';

let angularModule: any = null;
let services: DiscoverServices | null = null;
Expand Down Expand Up @@ -50,8 +52,6 @@ export const [getUrlTracker, setUrlTracker] = createGetterSetter<{
setTrackedUrl: (url: string) => void;
}>('urlTracker');

import { search } from '../../../../../plugins/data/public';
import { createGetterSetter } from '../../../../../plugins/kibana_utils/common';
export const { getRequestInspectorStats, getResponseInspectorStats, tabifyAggResponse } = search;
export {
unhashUrl,
Expand Down
2 changes: 1 addition & 1 deletion src/legacy/core_plugins/vis_type_metric/public/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* under the License.
*/

import { createGetterSetter } from '../../../../plugins/kibana_utils/common';
import { createGetterSetter } from '../../../../plugins/kibana_utils/public';
import { DataPublicPluginStart } from '../../../../plugins/data/public';

export const [getFormatService, setFormatService] = createGetterSetter<
Expand Down
2 changes: 1 addition & 1 deletion src/legacy/core_plugins/vis_type_table/public/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* under the License.
*/

import { createGetterSetter } from '../../../../plugins/kibana_utils/common';
import { createGetterSetter } from '../../../../plugins/kibana_utils/public';
import { DataPublicPluginStart } from '../../../../plugins/data/public';

export const [getFormatService, setFormatService] = createGetterSetter<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* under the License.
*/

import { createGetterSetter } from '../../../../plugins/kibana_utils/common';
import { createGetterSetter } from '../../../../plugins/kibana_utils/public';
import { DataPublicPluginStart } from '../../../../plugins/data/public';

export const [getFormatService, setFormatService] = createGetterSetter<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { metricsRequestHandler } from './request_handler';
import { EditorController } from './editor_controller';
// @ts-ignore
import { PANEL_TYPES } from '../../../../plugins/vis_type_timeseries/common/panel_types';
import { defaultFeedbackMessage } from '../../../../plugins/kibana_utils/common';
import { defaultFeedbackMessage } from '../../../../plugins/kibana_utils/public';

export const metricsVisDefinition = {
name: 'metrics',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* under the License.
*/

import { createGetterSetter } from '../../../../../plugins/kibana_utils/common';
import { createGetterSetter } from '../../../../../plugins/kibana_utils/public';
import { DataPublicPluginStart } from '../../../../../plugins/data/public';
import { IUiSettingsClient, NotificationsStart, SavedObjectsStart } from 'kibana/public';
import { dataPluginMock } from '../../../../../plugins/data/public/mocks';
Expand Down
2 changes: 1 addition & 1 deletion src/legacy/core_plugins/vis_type_vega/public/vega_type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { i18n } from '@kbn/i18n';
import { DefaultEditorSize } from '../../../../plugins/vis_default_editor/public';
import { VegaVisualizationDependencies } from './plugin';
import { VegaVisEditor } from './components';
import { defaultFeedbackMessage } from '../../../../plugins/kibana_utils/common';
import { defaultFeedbackMessage } from '../../../../plugins/kibana_utils/public';

import { createVegaRequestHandler } from './vega_request_handler';
// @ts-ignore
Expand Down
2 changes: 1 addition & 1 deletion src/legacy/core_plugins/vis_type_vislib/public/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* under the License.
*/

import { createGetterSetter } from '../../../../plugins/kibana_utils/common';
import { createGetterSetter } from '../../../../plugins/kibana_utils/public';
import { DataPublicPluginStart } from '../../../../plugins/data/public';

export const [getDataActions, setDataActions] = createGetterSetter<
Expand Down
69 changes: 27 additions & 42 deletions src/legacy/ui/ui_render/bootstrap/template.js.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -30,33 +30,27 @@ if (window.__kbnStrictCsp__ && window.__kbnCspNotEnforced__) {

function loadStyleSheet(url, cb) {
var dom = document.createElement('link');
dom.rel = 'stylesheet';
dom.type = 'text/css';
dom.href = url;
dom.addEventListener('error', failure);
dom.setAttribute('rel', 'stylesheet');
dom.setAttribute('type', 'text/css');
dom.setAttribute('href', url);
dom.addEventListener('load', cb);
document.head.appendChild(dom);
}

function loadScript(url, cb) {
var dom = document.createElement('script');
dom.setAttribute('async', '');
{{!-- NOTE: async = false is used to trigger async-download/ordered-execution as outlined here: https://www.html5rocks.com/en/tutorials/speed/script-loading/ --}}
dom.async = false;
dom.src = url;
dom.addEventListener('error', failure);
dom.setAttribute('src', url);
dom.addEventListener('load', cb);
document.head.appendChild(dom);
}

function load(urlSet, cb) {
if (urlSet.deps) {
load({ urls: urlSet.deps }, function () {
load({ urls: urlSet.urls }, cb);
});
return;
}

var pending = urlSet.urls.length;
urlSet.urls.forEach(function (url) {
function load(urls, cb) {
var pending = urls.length;
urls.forEach(function (url) {
var innerCb = function () {
pending = pending - 1;
if (pending === 0 && typeof cb === 'function') {
Expand All @@ -74,36 +68,27 @@ if (window.__kbnStrictCsp__ && window.__kbnCspNotEnforced__) {
});
}

load({
deps: [
load([
{{#each sharedJsDepFilenames}}
'{{../regularBundlePath}}/kbn-ui-shared-deps/{{this}}',
{{/each}}
],
urls: [
{
deps: [
'{{regularBundlePath}}/kbn-ui-shared-deps/{{sharedJsFilename}}',
{
deps: [
'{{dllBundlePath}}/vendors_runtime.bundle.dll.js'
],
urls: [
{{#each dllJsChunks}}
'{{this}}',
{{/each}}
]
},
'{{regularBundlePath}}/commons.bundle.js',
],
urls: [
'{{regularBundlePath}}/{{appId}}.bundle.js',
{{#each styleSheetPaths}}
'{{this}}',
{{/each}}
]
}
]
'{{regularBundlePath}}/kbn-ui-shared-deps/{{sharedJsFilename}}',
'{{dllBundlePath}}/vendors_runtime.bundle.dll.js',
{{#each dllJsChunks}}
'{{this}}',
{{/each}}
'{{regularBundlePath}}/commons.bundle.js',
{{!-- '{{regularBundlePath}}/plugin/data/data.plugin.js', --}}
'{{regularBundlePath}}/plugin/kibanaUtils/kibanaUtils.plugin.js',
'{{regularBundlePath}}/plugin/esUiShared/esUiShared.plugin.js',
'{{regularBundlePath}}/plugin/kibanaReact/kibanaReact.plugin.js'
], function () {
load([
'{{regularBundlePath}}/{{appId}}.bundle.js',
{{#each styleSheetPaths}}
'{{this}}',
{{/each}}
])
});
};
}
2 changes: 1 addition & 1 deletion src/plugins/discover/public/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* under the License.
*/

import { createGetterSetter } from '../../kibana_utils/common';
import { createGetterSetter } from '../../kibana_utils/public';
import { DocViewsRegistry } from './doc_views/doc_views_registry';

export const [getDocViewsRegistry, setDocViewsRegistry] = createGetterSetter<DocViewsRegistry>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { Embeddable } from './embeddable';
import { EmbeddableInput } from './i_embeddable';
import { ViewMode } from '../types';
import { EmbeddableActionStorage, SerializedEvent } from './embeddable_action_storage';
import { of } from '../../../../kibana_utils/common';
import { of } from '../../../../kibana_utils/public';

class TestEmbeddable extends Embeddable<EmbeddableInput> {
public readonly type = 'test';
Expand Down
5 changes: 5 additions & 0 deletions src/plugins/es_ui_shared/kibana.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"id": "esUiShared",
"version": "kibana",
"ui": true
}
Loading

0 comments on commit 8d3bced

Please sign in to comment.