mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[APM] Reduce initially loaded bundles by 98% (#191658)
## 📓 Summary Closes #191600 Moving on invocation site the dynamic import to instantiate the apm locator and registering the embeddable removed the async import on the biggest APM js chunks. In practice, we passed from loading ~900kb of JS to ~10kb, with a total reduction of about **~16%** of all the code loaded by Kibana for any page. There is also deeper code splitting for the APM routes to only load specific features when required on while using the APM app. | Before | After | |--------|--------| | <img width="622" alt="Screenshot 2024-08-28 at 17 58 59" src="https://github.com/user-attachments/assets/55198b98-0026-41aa-a7aa-d274b854257f"> | <img width="670" alt="Screenshot 2024-08-28 at 17 59 30" src="https://github.com/user-attachments/assets/3c9136ea-4437-45e8-b3e6-3fe8555ec7e1"> | ## Mandatory celebration GIF  --------- Co-authored-by: Marco Antonio Ghiani <marcoantonio.ghiani@elastic.co> Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
parent
5d77095785
commit
b7a909f3e8
11 changed files with 127 additions and 65 deletions
|
@ -38,6 +38,7 @@ describe('Dependencies', () => {
|
|||
describe('top-level dependencies page', () => {
|
||||
it('has a list of dependencies and you can navigate to the page for one', () => {
|
||||
cy.visitKibana(`/app/apm/services?${new URLSearchParams(timeRange)}`);
|
||||
cy.getByTestSubj('superDatePickerstartDatePopoverButton');
|
||||
cy.contains('nav a', 'Dependencies').click();
|
||||
|
||||
// `force: true` because Cypress says the element is 0x0
|
||||
|
|
|
@ -9,24 +9,48 @@ import { toBooleanRt, toNumberRt } from '@kbn/io-ts-utils';
|
|||
import { Outlet } from '@kbn/typed-react-router-config';
|
||||
import * as t from 'io-ts';
|
||||
import React, { ComponentProps } from 'react';
|
||||
import { dynamic } from '@kbn/shared-ux-utility';
|
||||
import { offsetRt } from '../../../../common/comparison_rt';
|
||||
import { ENVIRONMENT_ALL } from '../../../../common/environment_filter_values';
|
||||
import { environmentRt } from '../../../../common/environment_rt';
|
||||
import { TraceSearchType } from '../../../../common/trace_explorer';
|
||||
import { ApmTimeRangeMetadataContextProvider } from '../../../context/time_range_metadata/time_range_metadata_context';
|
||||
import { ServiceInventory } from '../../app/service_inventory';
|
||||
import { ServiceMapHome } from '../../app/service_map';
|
||||
import { TopTracesOverview } from '../../app/top_traces_overview';
|
||||
import { TraceExplorer } from '../../app/trace_explorer';
|
||||
import { TraceExplorerAggregatedCriticalPath } from '../../app/trace_explorer/trace_explorer_aggregated_critical_path';
|
||||
import { TraceExplorerWaterfall } from '../../app/trace_explorer/trace_explorer_waterfall';
|
||||
import { TraceOverview } from '../../app/trace_overview';
|
||||
import { TransactionTab } from '../../app/transaction_details/waterfall_with_summary/transaction_tabs';
|
||||
import { RedirectTo } from '../redirect_to';
|
||||
import { ServiceGroupTemplate } from '../templates/service_group_template';
|
||||
import { dependencies } from './dependencies';
|
||||
import { legacyBackends } from './legacy_backends';
|
||||
import { storageExplorer } from './storage_explorer';
|
||||
import { TransactionTab } from '../../app/transaction_details/waterfall_with_summary/transaction_tabs';
|
||||
|
||||
const ServiceGroupTemplate = dynamic(() =>
|
||||
import('../templates/service_group_template').then((mod) => ({
|
||||
default: mod.ServiceGroupTemplate,
|
||||
}))
|
||||
);
|
||||
const ServiceInventory = dynamic(() =>
|
||||
import('../../app/service_inventory').then((mod) => ({ default: mod.ServiceInventory }))
|
||||
);
|
||||
const ServiceMapHome = dynamic(() =>
|
||||
import('../../app/service_map').then((mod) => ({ default: mod.ServiceMapHome }))
|
||||
);
|
||||
const TopTracesOverview = dynamic(() =>
|
||||
import('../../app/top_traces_overview').then((mod) => ({ default: mod.TopTracesOverview }))
|
||||
);
|
||||
const TraceExplorer = dynamic(() =>
|
||||
import('../../app/trace_explorer').then((mod) => ({ default: mod.TraceExplorer }))
|
||||
);
|
||||
const TraceExplorerAggregatedCriticalPath = dynamic(() =>
|
||||
import('../../app/trace_explorer/trace_explorer_aggregated_critical_path').then((mod) => ({
|
||||
default: mod.TraceExplorerAggregatedCriticalPath,
|
||||
}))
|
||||
);
|
||||
const TraceExplorerWaterfall = dynamic(() =>
|
||||
import('../../app/trace_explorer/trace_explorer_waterfall').then((mod) => ({
|
||||
default: mod.TraceExplorerWaterfall,
|
||||
}))
|
||||
);
|
||||
const TraceOverview = dynamic(() =>
|
||||
import('../../app/trace_overview').then((mod) => ({ default: mod.TraceOverview }))
|
||||
);
|
||||
|
||||
function serviceGroupPage<TPath extends string>({
|
||||
path,
|
||||
|
|
|
@ -9,7 +9,7 @@ import React from 'react';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import * as t from 'io-ts';
|
||||
import { EuiLink } from '@elastic/eui';
|
||||
import { StorageExplorer } from '../../app/storage_explorer';
|
||||
import { dynamic } from '@kbn/shared-ux-utility';
|
||||
import { ApmMainTemplate } from '../templates/apm_main_template';
|
||||
import { Breadcrumb } from '../../app/breadcrumb';
|
||||
import {
|
||||
|
@ -18,6 +18,10 @@ import {
|
|||
} from '../../../../common/storage_explorer_types';
|
||||
import { getStorageExplorerFeedbackHref } from '../../app/storage_explorer/get_storage_explorer_links';
|
||||
|
||||
const StorageExplorer = dynamic(() =>
|
||||
import('../../app/storage_explorer').then((mod) => ({ default: mod.StorageExplorer }))
|
||||
);
|
||||
|
||||
export const storageExplorer = {
|
||||
'/storage-explorer': {
|
||||
element: (
|
||||
|
|
|
@ -7,9 +7,13 @@
|
|||
|
||||
import * as t from 'io-ts';
|
||||
import React from 'react';
|
||||
import { Onboarding } from '../../app/onboarding';
|
||||
import { dynamic } from '@kbn/shared-ux-utility';
|
||||
import { INSTRUCTION_VARIANT } from '../../app/onboarding/instruction_variants';
|
||||
|
||||
const Onboarding = dynamic(() =>
|
||||
import('../../app/onboarding').then((mod) => ({ default: mod.Onboarding }))
|
||||
);
|
||||
|
||||
export const onboarding = {
|
||||
'/onboarding': {
|
||||
element: <Onboarding />,
|
||||
|
|
|
@ -12,6 +12,7 @@ import * as t from 'io-ts';
|
|||
import qs from 'query-string';
|
||||
import React from 'react';
|
||||
import { Redirect } from 'react-router-dom';
|
||||
import { dynamic } from '@kbn/shared-ux-utility';
|
||||
import { offsetRt } from '../../../../common/comparison_rt';
|
||||
import { ENVIRONMENT_ALL } from '../../../../common/environment_filter_values';
|
||||
import { environmentRt } from '../../../../common/environment_rt';
|
||||
|
@ -21,25 +22,47 @@ import {
|
|||
} from '../../../../common/latency_aggregation_types';
|
||||
import { ApmTimeRangeMetadataContextProvider } from '../../../context/time_range_metadata/time_range_metadata_context';
|
||||
import { useApmParams } from '../../../hooks/use_apm_params';
|
||||
import { AlertsOverview, ALERT_STATUS_ALL } from '../../app/alerts_overview';
|
||||
import { ErrorGroupDetails } from '../../app/error_group_details';
|
||||
import { ErrorGroupOverview } from '../../app/error_group_overview';
|
||||
import { InfraOverview } from '../../app/infra_overview';
|
||||
import { ALERT_STATUS_ALL, AlertsOverview } from '../../app/alerts_overview';
|
||||
import { InfraTab } from '../../app/infra_overview/infra_tabs/use_tabs';
|
||||
import { Metrics } from '../../app/metrics';
|
||||
import { MetricsDetails } from '../../app/metrics_details';
|
||||
import { ServiceDependencies } from '../../app/service_dependencies';
|
||||
import { ServiceLogs } from '../../app/service_logs';
|
||||
import { ServiceMapServiceDetail } from '../../app/service_map';
|
||||
import { ServiceOverview } from '../../app/service_overview';
|
||||
import { TransactionDetails } from '../../app/transaction_details';
|
||||
import { TransactionOverview } from '../../app/transaction_overview';
|
||||
import { ApmServiceTemplate } from '../templates/apm_service_template';
|
||||
import { ApmServiceWrapper } from './apm_service_wrapper';
|
||||
import { RedirectToDefaultServiceRouteView } from './redirect_to_default_service_route_view';
|
||||
import { ProfilingOverview } from '../../app/profiling_overview';
|
||||
import { SearchBar } from '../../shared/search_bar/search_bar';
|
||||
import { ServiceDependencies } from '../../app/service_dependencies';
|
||||
import { ServiceDashboards } from '../../app/service_dashboards';
|
||||
import { ErrorGroupDetails } from '../../app/error_group_details';
|
||||
|
||||
const ErrorGroupOverview = dynamic(() =>
|
||||
import('../../app/error_group_overview').then((mod) => ({ default: mod.ErrorGroupOverview }))
|
||||
);
|
||||
const InfraOverview = dynamic(() =>
|
||||
import('../../app/infra_overview').then((mod) => ({ default: mod.InfraOverview }))
|
||||
);
|
||||
const Metrics = dynamic(() =>
|
||||
import('../../app/metrics').then((mod) => ({ default: mod.Metrics }))
|
||||
);
|
||||
const MetricsDetails = dynamic(() =>
|
||||
import('../../app/metrics_details').then((mod) => ({ default: mod.MetricsDetails }))
|
||||
);
|
||||
|
||||
const ServiceLogs = dynamic(() =>
|
||||
import('../../app/service_logs').then((mod) => ({ default: mod.ServiceLogs }))
|
||||
);
|
||||
const ServiceMapServiceDetail = dynamic(() =>
|
||||
import('../../app/service_map').then((mod) => ({ default: mod.ServiceMapServiceDetail }))
|
||||
);
|
||||
const ServiceOverview = dynamic(() =>
|
||||
import('../../app/service_overview').then((mod) => ({ default: mod.ServiceOverview }))
|
||||
);
|
||||
const TransactionDetails = dynamic(() =>
|
||||
import('../../app/transaction_details').then((mod) => ({ default: mod.TransactionDetails }))
|
||||
);
|
||||
const TransactionOverview = dynamic(() =>
|
||||
import('../../app/transaction_overview').then((mod) => ({ default: mod.TransactionOverview }))
|
||||
);
|
||||
const ProfilingOverview = dynamic(() =>
|
||||
import('../../app/profiling_overview').then((mod) => ({ default: mod.ProfilingOverview }))
|
||||
);
|
||||
|
||||
function page({
|
||||
title,
|
||||
|
|
|
@ -13,9 +13,7 @@ import type { EmbeddableApmAlertingVizProps } from '../types';
|
|||
import type { EmbeddableDeps } from '../../types';
|
||||
import { ApmEmbeddableContext } from '../../embeddable_context';
|
||||
import { APMAlertingFailedTransactionsChart } from './chart';
|
||||
|
||||
export const APM_ALERTING_FAILED_TRANSACTIONS_CHART_EMBEDDABLE =
|
||||
'APM_ALERTING_FAILED_TRANSACTIONS_CHART_EMBEDDABLE';
|
||||
import { APM_ALERTING_FAILED_TRANSACTIONS_CHART_EMBEDDABLE } from '../constants';
|
||||
|
||||
export const getApmAlertingFailedTransactionsChartEmbeddableFactory = (deps: EmbeddableDeps) => {
|
||||
const factory: ReactEmbeddableFactory<
|
||||
|
|
|
@ -13,8 +13,7 @@ import type { EmbeddableApmAlertingLatencyVizProps } from '../types';
|
|||
import type { EmbeddableDeps } from '../../types';
|
||||
import { ApmEmbeddableContext } from '../../embeddable_context';
|
||||
import { APMAlertingLatencyChart } from './chart';
|
||||
|
||||
export const APM_ALERTING_LATENCY_CHART_EMBEDDABLE = 'APM_ALERTING_LATENCY_CHART_EMBEDDABLE';
|
||||
import { APM_ALERTING_LATENCY_CHART_EMBEDDABLE } from '../constants';
|
||||
|
||||
export const getApmAlertingLatencyChartEmbeddableFactory = (deps: EmbeddableDeps) => {
|
||||
const factory: ReactEmbeddableFactory<
|
||||
|
|
|
@ -13,8 +13,7 @@ import type { EmbeddableApmAlertingVizProps } from '../types';
|
|||
import type { EmbeddableDeps } from '../../types';
|
||||
import { ApmEmbeddableContext } from '../../embeddable_context';
|
||||
import { APMAlertingThroughputChart } from './chart';
|
||||
|
||||
export const APM_ALERTING_THROUGHPUT_CHART_EMBEDDABLE = 'APM_ALERTING_THROUGHPUT_CHART_EMBEDDABLE';
|
||||
import { APM_ALERTING_THROUGHPUT_CHART_EMBEDDABLE } from '../constants';
|
||||
|
||||
export const getApmAlertingThroughputChartEmbeddableFactory = (deps: EmbeddableDeps) => {
|
||||
const factory: ReactEmbeddableFactory<
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
export const APM_ALERTING_FAILED_TRANSACTIONS_CHART_EMBEDDABLE =
|
||||
'APM_ALERTING_FAILED_TRANSACTIONS_CHART_EMBEDDABLE';
|
||||
export const APM_ALERTING_LATENCY_CHART_EMBEDDABLE = 'APM_ALERTING_LATENCY_CHART_EMBEDDABLE';
|
||||
export const APM_ALERTING_THROUGHPUT_CHART_EMBEDDABLE = 'APM_ALERTING_THROUGHPUT_CHART_EMBEDDABLE';
|
|
@ -8,6 +8,11 @@ import { CoreSetup } from '@kbn/core/public';
|
|||
|
||||
import { ApmPluginStartDeps, ApmPluginStart } from '../plugin';
|
||||
import { EmbeddableDeps } from './types';
|
||||
import {
|
||||
APM_ALERTING_FAILED_TRANSACTIONS_CHART_EMBEDDABLE,
|
||||
APM_ALERTING_LATENCY_CHART_EMBEDDABLE,
|
||||
APM_ALERTING_THROUGHPUT_CHART_EMBEDDABLE,
|
||||
} from './alerting/constants';
|
||||
|
||||
export async function registerEmbeddables(
|
||||
deps: Omit<EmbeddableDeps, 'coreStart' | 'pluginsStart'>
|
||||
|
@ -16,36 +21,32 @@ export async function registerEmbeddables(
|
|||
const pluginsSetup = deps.pluginsSetup;
|
||||
const [coreStart, pluginsStart] = await coreSetup.getStartServices();
|
||||
const registerReactEmbeddableFactory = pluginsSetup.embeddable.registerReactEmbeddableFactory;
|
||||
const registerApmAlertingLatencyChartEmbeddable = async () => {
|
||||
const { getApmAlertingLatencyChartEmbeddableFactory, APM_ALERTING_LATENCY_CHART_EMBEDDABLE } =
|
||||
await import('./alerting/alerting_latency_chart/react_embeddable_factory');
|
||||
registerReactEmbeddableFactory(APM_ALERTING_LATENCY_CHART_EMBEDDABLE, async () => {
|
||||
return getApmAlertingLatencyChartEmbeddableFactory({ ...deps, coreStart, pluginsStart });
|
||||
|
||||
registerReactEmbeddableFactory(APM_ALERTING_LATENCY_CHART_EMBEDDABLE, async () => {
|
||||
const { getApmAlertingLatencyChartEmbeddableFactory } = await import(
|
||||
'./alerting/alerting_latency_chart/react_embeddable_factory'
|
||||
);
|
||||
|
||||
return getApmAlertingLatencyChartEmbeddableFactory({ ...deps, coreStart, pluginsStart });
|
||||
});
|
||||
|
||||
registerReactEmbeddableFactory(APM_ALERTING_THROUGHPUT_CHART_EMBEDDABLE, async () => {
|
||||
const { getApmAlertingThroughputChartEmbeddableFactory } = await import(
|
||||
'./alerting/alerting_throughput_chart/react_embeddable_factory'
|
||||
);
|
||||
|
||||
return getApmAlertingThroughputChartEmbeddableFactory({ ...deps, coreStart, pluginsStart });
|
||||
});
|
||||
|
||||
registerReactEmbeddableFactory(APM_ALERTING_FAILED_TRANSACTIONS_CHART_EMBEDDABLE, async () => {
|
||||
const { getApmAlertingFailedTransactionsChartEmbeddableFactory } = await import(
|
||||
'./alerting/alerting_failed_transactions_chart/react_embeddable_factory'
|
||||
);
|
||||
|
||||
return getApmAlertingFailedTransactionsChartEmbeddableFactory({
|
||||
...deps,
|
||||
coreStart,
|
||||
pluginsStart,
|
||||
});
|
||||
};
|
||||
const registerApmAlertingThroughputChartEmbeddable = async () => {
|
||||
const {
|
||||
getApmAlertingThroughputChartEmbeddableFactory,
|
||||
APM_ALERTING_THROUGHPUT_CHART_EMBEDDABLE,
|
||||
} = await import('./alerting/alerting_throughput_chart/react_embeddable_factory');
|
||||
registerReactEmbeddableFactory(APM_ALERTING_THROUGHPUT_CHART_EMBEDDABLE, async () => {
|
||||
return getApmAlertingThroughputChartEmbeddableFactory({ ...deps, coreStart, pluginsStart });
|
||||
});
|
||||
};
|
||||
const registerApmAlertingFailedTransactionsChartEmbeddable = async () => {
|
||||
const {
|
||||
getApmAlertingFailedTransactionsChartEmbeddableFactory,
|
||||
APM_ALERTING_FAILED_TRANSACTIONS_CHART_EMBEDDABLE,
|
||||
} = await import('./alerting/alerting_failed_transactions_chart/react_embeddable_factory');
|
||||
registerReactEmbeddableFactory(APM_ALERTING_FAILED_TRANSACTIONS_CHART_EMBEDDABLE, async () => {
|
||||
return getApmAlertingFailedTransactionsChartEmbeddableFactory({
|
||||
...deps,
|
||||
coreStart,
|
||||
pluginsStart,
|
||||
});
|
||||
});
|
||||
};
|
||||
registerApmAlertingLatencyChartEmbeddable();
|
||||
registerApmAlertingThroughputChartEmbeddable();
|
||||
registerApmAlertingFailedTransactionsChartEmbeddable();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -15,8 +15,6 @@ import { ENVIRONMENT_ALL } from '../../common/environment_filter_values';
|
|||
import type { TimePickerTimeDefaults } from '../components/shared/date_picker/typings';
|
||||
import type { APMLocatorPayload } from './helpers';
|
||||
|
||||
const helpersModule = import('./helpers');
|
||||
|
||||
export const APM_APP_LOCATOR_ID = 'APM_LOCATOR';
|
||||
|
||||
export class APMServiceDetailLocator implements LocatorDefinition<APMLocatorPayload> {
|
||||
|
@ -28,7 +26,7 @@ export class APMServiceDetailLocator implements LocatorDefinition<APMLocatorPayl
|
|||
}
|
||||
|
||||
async getLocation(payload: APMLocatorPayload) {
|
||||
const { getPathForServiceDetail } = await helpersModule;
|
||||
const { getPathForServiceDetail } = await import('./helpers');
|
||||
|
||||
const defaultTimeRange = this.uiSettings.get<TimePickerTimeDefaults>(
|
||||
UI_SETTINGS.TIMEPICKER_TIME_DEFAULTS
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue