Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce lens bundle size #64769

Merged
merged 2 commits into from
May 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions x-pack/plugins/lens/public/app_plugin/mounter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import React from 'react';

import { AppMountParameters, CoreSetup } from 'kibana/public';
import { FormattedMessage, I18nProvider } from '@kbn/i18n/react';
import { HashRouter, Route, RouteComponentProps, Switch } from 'react-router-dom';
import { render, unmountComponentAtNode } from 'react-dom';

import rison from 'rison-node';
import { DashboardConstants } from '../../../../../src/plugins/dashboard/public';
import { Storage } from '../../../../../src/plugins/kibana_utils/public';

import { LensReportManager, setReportManager, trackUiEvent } from '../lens_ui_telemetry';

import { App } from './app';
import { EditorFrameStart } from '../types';
import { addEmbeddableToDashboardUrl, getUrlVars, isRisonObject } from '../helpers';
import { addHelpMenuToAppChrome } from '../help_menu_util';
import { SavedObjectIndexStore } from '../persistence';
import { LensPluginStartDependencies } from '../plugin';

export async function mountApp(
core: CoreSetup<LensPluginStartDependencies, void>,
params: AppMountParameters,
createEditorFrame: EditorFrameStart['createInstance']
) {
const [coreStart, startDependencies] = await core.getStartServices();
const { data: dataStart, navigation } = startDependencies;
const savedObjectsClient = coreStart.savedObjects.client;
addHelpMenuToAppChrome(coreStart.chrome, coreStart.docLinks);

const instance = await createEditorFrame();

setReportManager(
new LensReportManager({
storage: new Storage(localStorage),
http: core.http,
})
);
const updateUrlTime = (urlVars: Record<string, string>): void => {
const decoded = rison.decode(urlVars._g);
if (!isRisonObject(decoded)) {
return;
}
// @ts-ignore
decoded.time = dataStart.query.timefilter.timefilter.getTime();
urlVars._g = rison.encode(decoded);
};
const redirectTo = (
routeProps: RouteComponentProps<{ id?: string }>,
addToDashboardMode: boolean,
id?: string
) => {
if (!id) {
routeProps.history.push('/lens');
} else if (!addToDashboardMode) {
routeProps.history.push(`/lens/edit/${id}`);
} else if (addToDashboardMode && id) {
routeProps.history.push(`/lens/edit/${id}`);
const lastDashboardLink = coreStart.chrome.navLinks.get('kibana:dashboard');
if (!lastDashboardLink || !lastDashboardLink.url) {
throw new Error('Cannot get last dashboard url');
}
const urlVars = getUrlVars(lastDashboardLink.url);
updateUrlTime(urlVars); // we need to pass in timerange in query params directly
const dashboardUrl = addEmbeddableToDashboardUrl(lastDashboardLink.url, id, urlVars);
window.history.pushState({}, '', dashboardUrl);
}
};

const renderEditor = (routeProps: RouteComponentProps<{ id?: string }>) => {
trackUiEvent('loaded');
const addToDashboardMode =
!!routeProps.location.search &&
routeProps.location.search.includes(
DashboardConstants.ADD_VISUALIZATION_TO_DASHBOARD_MODE_PARAM
);
return (
<App
core={coreStart}
data={dataStart}
navigation={navigation}
editorFrame={instance}
storage={new Storage(localStorage)}
docId={routeProps.match.params.id}
docStorage={new SavedObjectIndexStore(savedObjectsClient)}
redirectTo={id => redirectTo(routeProps, addToDashboardMode, id)}
addToDashboardMode={addToDashboardMode}
/>
);
};

function NotFound() {
trackUiEvent('loaded_404');
return <FormattedMessage id="xpack.lens.app404" defaultMessage="404 Not Found" />;
}

render(
<I18nProvider>
<HashRouter>
<Switch>
<Route exact path="/lens/edit/:id" render={renderEditor} />
<Route exact path="/lens" render={renderEditor} />
<Route path="/lens" component={NotFound} />
</Switch>
</HashRouter>
</I18nProvider>,
params.element
);
return () => {
instance.unmount();
unmountComponentAtNode(params.element);
};
}
1 change: 1 addition & 0 deletions x-pack/plugins/lens/public/helpers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
*/

export { addEmbeddableToDashboardUrl, getUrlVars } from './url_helper';
export { isRisonObject } from './is_rison_object';
12 changes: 12 additions & 0 deletions x-pack/plugins/lens/public/helpers/is_rison_object.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { RisonObject, RisonValue } from 'rison-node';
import { isObject } from 'lodash';

export const isRisonObject = (value: RisonValue): value is RisonObject => {
return isObject(value);
};
103 changes: 103 additions & 0 deletions x-pack/plugins/lens/public/plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { AppMountParameters, CoreSetup, CoreStart } from 'kibana/public';
import { DataPublicPluginSetup, DataPublicPluginStart } from 'src/plugins/data/public';
import { EmbeddableSetup, EmbeddableStart } from 'src/plugins/embeddable/public';
import { ExpressionsSetup, ExpressionsStart } from 'src/plugins/expressions/public';
import { VisualizationsSetup } from 'src/plugins/visualizations/public';
import { NavigationPublicPluginStart } from 'src/plugins/navigation/public';
import { KibanaLegacySetup } from 'src/plugins/kibana_legacy/public';
import { EditorFrameService } from './editor_frame_service';
import { IndexPatternDatasource } from './indexpattern_datasource';
import { XyVisualization } from './xy_visualization';
import { MetricVisualization } from './metric_visualization';
import { DatatableVisualization } from './datatable_visualization';
import { stopReportManager } from './lens_ui_telemetry';

import { UiActionsStart } from '../../../../src/plugins/ui_actions/public';
import { NOT_INTERNATIONALIZED_PRODUCT_NAME } from '../common';
import { EditorFrameStart } from './types';
import { getLensAliasConfig } from './vis_type_alias';

import './index.scss';

export interface LensPluginSetupDependencies {
kibanaLegacy: KibanaLegacySetup;
expressions: ExpressionsSetup;
data: DataPublicPluginSetup;
embeddable?: EmbeddableSetup;
visualizations: VisualizationsSetup;
}

export interface LensPluginStartDependencies {
data: DataPublicPluginStart;
embeddable: EmbeddableStart;
expressions: ExpressionsStart;
navigation: NavigationPublicPluginStart;
uiActions: UiActionsStart;
}

export class LensPlugin {
private datatableVisualization: DatatableVisualization;
private editorFrameService: EditorFrameService;
private createEditorFrame: EditorFrameStart['createInstance'] | null = null;
private indexpatternDatasource: IndexPatternDatasource;
private xyVisualization: XyVisualization;
private metricVisualization: MetricVisualization;

constructor() {
this.datatableVisualization = new DatatableVisualization();
this.editorFrameService = new EditorFrameService();
this.indexpatternDatasource = new IndexPatternDatasource();
this.xyVisualization = new XyVisualization();
this.metricVisualization = new MetricVisualization();
}

setup(
core: CoreSetup<LensPluginStartDependencies, void>,
{ kibanaLegacy, expressions, data, embeddable, visualizations }: LensPluginSetupDependencies
) {
const editorFrameSetupInterface = this.editorFrameService.setup(core, {
data,
embeddable,
expressions,
});
const dependencies = {
expressions,
data,
editorFrame: editorFrameSetupInterface,
formatFactory: core
.getStartServices()
.then(([_, { data: dataStart }]) => dataStart.fieldFormats.deserialize),
};
this.indexpatternDatasource.setup(core, dependencies);
this.xyVisualization.setup(core, dependencies);
this.datatableVisualization.setup(core, dependencies);
this.metricVisualization.setup(core, dependencies);

visualizations.registerAlias(getLensAliasConfig());

kibanaLegacy.registerLegacyApp({
id: 'lens',
title: NOT_INTERNATIONALIZED_PRODUCT_NAME,
mount: async (params: AppMountParameters) => {
const { mountApp } = await import('./app_plugin/mounter');
return mountApp(core, params, this.createEditorFrame!);
},
});
}

start(core: CoreStart, startDependencies: LensPluginStartDependencies) {
this.createEditorFrame = this.editorFrameService.start(core, startDependencies).createInstance;
this.xyVisualization.start(core, startDependencies);
this.datatableVisualization.start(core, startDependencies);
}

stop() {
stopReportManager();
}
}
Loading