From b6a74494e1e40131fe755ee065283ca8fa1f58b9 Mon Sep 17 00:00:00 2001 From: spalger Date: Sat, 9 Jan 2016 17:27:41 -0700 Subject: [PATCH] [autoloading] implement autoloading via modules Currently there is a long list of modules that is autoloaded for every app. This is because a number of angular directives/filters/services are not properly required by the code that needs them and rather than attempt to track down the relationships between every part of the app and the rest autoloading just makes sure that all of the defined modules are included. Since this was implicit it caused new apps which didn't need anything but chrome styles to be really heavy. This change makes autoloading something you opt into by requiring a ui/autoload/* module. The options include: - `ui/autoload/styles` - include the base styles used by Kibana. This includes all of the styles listed in the ui/styles directory. - `ui/autoload/directives` - `ui/autoload/filters` - `ui/autoload/modules` - include angular and several ui modules that one might expect to be loaded by default. This list is hard coded into this file. - `ui/autoload/all` - includes all of the above lists In order to support this change all plugins will likely need to update and include a `ui/autoload/*` module in their public/index.js file. --- src/plugins/kibana/index.js | 14 ---- src/plugins/kibana/public/kibana.js | 12 ++- src/plugins/statusPage/index.js | 8 +- src/plugins/statusPage/public/statusPage.js | 1 + src/server/plugins/PluginApi.js | 16 +++- src/ui/UiApp.js | 10 ++- src/ui/appEntryTemplate.js | 2 +- src/ui/autoload.js | 82 --------------------- src/ui/public/autoload/all.js | 4 + src/ui/public/autoload/directives.js | 2 + src/ui/public/autoload/filters.js | 2 + src/ui/public/autoload/modules.js | 34 +++++++++ src/ui/public/autoload/styles.js | 2 + 13 files changed, 79 insertions(+), 110 deletions(-) delete mode 100644 src/ui/autoload.js create mode 100644 src/ui/public/autoload/all.js create mode 100644 src/ui/public/autoload/directives.js create mode 100644 src/ui/public/autoload/filters.js create mode 100644 src/ui/public/autoload/modules.js create mode 100644 src/ui/public/autoload/styles.js diff --git a/src/plugins/kibana/index.js b/src/plugins/kibana/index.js index 1d8d45addf033f..afc9de83de9bd2 100644 --- a/src/plugins/kibana/index.js +++ b/src/plugins/kibana/index.js @@ -21,20 +21,6 @@ module.exports = function (kibana) { 'fieldFormats' ], - autoload: kibana.autoload.require.concat( - 'plugins/kibana/discover', - 'plugins/kibana/visualize', - 'plugins/kibana/dashboard', - 'plugins/kibana/settings', - 'plugins/kibana/settings/sections', - 'plugins/kibana/doc', - 'plugins/kibana/settings/sections', - 'ui/vislib', - 'ui/agg_response', - 'ui/agg_types', - 'leaflet' - ), - injectVars: function (server, options) { let config = server.config(); diff --git a/src/plugins/kibana/public/kibana.js b/src/plugins/kibana/public/kibana.js index 98572723bf6545..2d059cc972c810 100644 --- a/src/plugins/kibana/public/kibana.js +++ b/src/plugins/kibana/public/kibana.js @@ -1,12 +1,20 @@ +// autoloading +require('ui/autoload/all'); + +// preloading (for faster webpack builds) require('plugins/kibana/discover/index'); require('plugins/kibana/visualize/index'); require('plugins/kibana/dashboard/index'); require('plugins/kibana/settings/index'); -require('plugins/kibana/doc/index'); +require('plugins/kibana/settings/sections'); +require('plugins/kibana/doc'); +require('ui/vislib'); +require('ui/agg_response'); +require('ui/agg_types'); require('ui/timepicker'); +require('leaflet'); var moment = require('moment-timezone'); - var chrome = require('ui/chrome'); var routes = require('ui/routes'); var modules = require('ui/modules'); diff --git a/src/plugins/statusPage/index.js b/src/plugins/statusPage/index.js index 49f139afd46b0f..1807813438ab99 100644 --- a/src/plugins/statusPage/index.js +++ b/src/plugins/statusPage/index.js @@ -5,13 +5,7 @@ module.exports = function (kibana) { title: 'Server Status', main: 'plugins/statusPage/statusPage', hidden: true, - url: '/status', - - autoload: [].concat( - kibana.autoload.styles, - 'ui/chrome', - 'angular' - ) + url: '/status' } } }); diff --git a/src/plugins/statusPage/public/statusPage.js b/src/plugins/statusPage/public/statusPage.js index 6189ec0832581b..38fc86a24a80a4 100644 --- a/src/plugins/statusPage/public/statusPage.js +++ b/src/plugins/statusPage/public/statusPage.js @@ -2,6 +2,7 @@ var $ = require('jquery'); var _ = require('lodash'); var notify = require('ui/notify'); +require('ui/autoload/styles'); require('plugins/statusPage/statusPageMetric'); require('plugins/statusPage/statusPage.less'); diff --git a/src/server/plugins/PluginApi.js b/src/server/plugins/PluginApi.js index 068f0deca190f0..68dd0524fe860d 100644 --- a/src/server/plugins/PluginApi.js +++ b/src/server/plugins/PluginApi.js @@ -7,11 +7,25 @@ module.exports = class PluginApi { this.config = kibana.config; this.rootDir = kibana.rootDir; this.package = require(join(pluginPath, 'package.json')); - this.autoload = require('../../ui/autoload'); this.Plugin = Plugin.scoped(kibana, pluginPath, this.package); } get uiExports() { throw new Error('plugin.uiExports is not defined until initialize phase'); } + + get autoload() { + console.warn( + `${this.package.id} accessed the autoload lists which are no longer available via the Plugin API.` + + 'Use the `ui/autoload/*` modules instead.' + ); + + return { + directives: [], + filters: [], + styles: [], + modules: [], + require: [] + }; + } }; diff --git a/src/ui/UiApp.js b/src/ui/UiApp.js index 4e6fcaa36ef80f..cd5ffce9fedd37 100644 --- a/src/ui/UiApp.js +++ b/src/ui/UiApp.js @@ -1,6 +1,5 @@ var _ = require('lodash'); var { join } = require('path'); -var autoload = require('./autoload'); class UiApp { constructor(uiExports, spec) { @@ -17,10 +16,16 @@ class UiApp { this.description = this.spec.description; this.icon = this.spec.icon; this.hidden = this.spec.hidden; - this.autoloadOverrides = this.spec.autoload; this.templateName = this.spec.templateName || 'ui_app'; this.url = `${spec.urlBasePath || ''}${this.spec.url || `/app/${this.id}`}`; + if (this.spec.autoload) { + console.warn( + `"autoload" (used by ${this.id} app) is no longer a valid app configuration directive.` + + 'Use the \`ui/autoload/*\` modules instead.' + ); + } + // once this resolves, no reason to run it again this.getModules = _.once(this.getModules); @@ -30,7 +35,6 @@ class UiApp { getModules() { return _.chain([ - this.autoloadOverrides || autoload.require, this.uiExports.find(_.get(this, 'spec.uses', [])), this.uiExports.find(['chromeNavControls']), ]) diff --git a/src/ui/appEntryTemplate.js b/src/ui/appEntryTemplate.js index 714de7ba07fce6..3900409eb65646 100644 --- a/src/ui/appEntryTemplate.js +++ b/src/ui/appEntryTemplate.js @@ -20,7 +20,7 @@ ${pluginSlug} * */ -require('ui/chrome') +require('ui/chrome'); ${requires} require('ui/chrome').bootstrap(/* xoxo */); diff --git a/src/ui/autoload.js b/src/ui/autoload.js deleted file mode 100644 index 79ee476fd67b12..00000000000000 --- a/src/ui/autoload.js +++ /dev/null @@ -1,82 +0,0 @@ -var _ = require('lodash'); -var resolve = require('path').resolve; -var basename = require('path').basename; -var readdir = require('fs').readdirSync; - -var utils = require('requirefrom')('src/utils'); -var fromRoot = utils('fromRoot'); - -function scan(type) { - var dir = fromRoot('src/ui/public', type); - - return _.chain(readdir(dir)) - .reject(function (name) { - return name[0] === '.' || name[0] === '_'; - }) - .map(function (filename) { - var path = resolve(dir, filename); - var name = basename(filename, '.js'); - return `ui/${type}/${name}`; - }) - .value(); -} - -function findStyles() { - var base = ['ui/styles/theme.less', 'ui/styles/base.less']; - var exclude = ['ui/styles/mixins.less', 'ui/styles/variables.less']; - var found = scan('styles', true); - - return _.difference(_.union(base, found), exclude); -} - -exports.reload = function () { - exports.directives = scan('directives'); - exports.filters = scan('filters'); - exports.styles = findStyles(); - exports.modules = [ - 'angular', - 'ui/chrome', - 'ui/chrome/context', - 'ui/bind', - 'ui/bound_to_config_obj', - 'ui/config', - 'ui/courier', - 'ui/debounce', - 'ui/doc_title', - 'ui/elastic_textarea', - 'ui/es', - 'ui/events', - 'ui/fancy_forms', - 'ui/filter_bar', - 'ui/filter_manager', - 'ui/index_patterns', - 'ui/listen', - 'ui/notify', - 'ui/parse_query', - 'ui/persisted_log', - 'ui/private', - 'ui/promises', - 'ui/safe_confirm', - 'ui/state_management/app_state', - 'ui/state_management/global_state', - 'ui/storage', - 'ui/stringify/register', - 'ui/styleCompile', - 'ui/timefilter', - 'ui/timepicker', // TODO: remove this for 5.0 - 'ui/tooltip', - 'ui/typeahead', - 'ui/url', - 'ui/validateDateInterval', - 'ui/watch_multi' - ]; - - exports.require = _.flatten([ - exports.directives, - exports.filters, - exports.styles, - exports.modules - ]); -}; - -exports.reload(); diff --git a/src/ui/public/autoload/all.js b/src/ui/public/autoload/all.js new file mode 100644 index 00000000000000..c5a906d63aabff --- /dev/null +++ b/src/ui/public/autoload/all.js @@ -0,0 +1,4 @@ +require('./modules'); +require('./directives'); +require('./filters'); +require('./styles'); diff --git a/src/ui/public/autoload/directives.js b/src/ui/public/autoload/directives.js new file mode 100644 index 00000000000000..3908c3e116de1f --- /dev/null +++ b/src/ui/public/autoload/directives.js @@ -0,0 +1,2 @@ +const context = require.context('../directives', false, /[\/\\](?!\.|_)[^\/\\]+\.js/); +context.keys().forEach(key => context(key)); diff --git a/src/ui/public/autoload/filters.js b/src/ui/public/autoload/filters.js new file mode 100644 index 00000000000000..583d1dcead0721 --- /dev/null +++ b/src/ui/public/autoload/filters.js @@ -0,0 +1,2 @@ +const context = require.context('../filters', false, /[\/\\](?!\.|_)[^\/\\]+\.js/); +context.keys().forEach(key => context(key)); diff --git a/src/ui/public/autoload/modules.js b/src/ui/public/autoload/modules.js new file mode 100644 index 00000000000000..533f05236d2c98 --- /dev/null +++ b/src/ui/public/autoload/modules.js @@ -0,0 +1,34 @@ +require('angular'); +require('ui/chrome'); +require('ui/chrome/context'); +require('ui/bind'); +require('ui/bound_to_config_obj'); +require('ui/config'); +require('ui/courier'); +require('ui/debounce'); +require('ui/doc_title'); +require('ui/elastic_textarea'); +require('ui/es'); +require('ui/events'); +require('ui/fancy_forms'); +require('ui/filter_bar'); +require('ui/filter_manager'); +require('ui/index_patterns'); +require('ui/listen'); +require('ui/notify'); +require('ui/parse_query'); +require('ui/persisted_log'); +require('ui/private'); +require('ui/promises'); +require('ui/safe_confirm'); +require('ui/state_management/app_state'); +require('ui/state_management/global_state'); +require('ui/storage'); +require('ui/stringify/register'); +require('ui/styleCompile'); +require('ui/timefilter'); +require('ui/tooltip'); +require('ui/typeahead'); +require('ui/url'); +require('ui/validateDateInterval'); +require('ui/watch_multi'); diff --git a/src/ui/public/autoload/styles.js b/src/ui/public/autoload/styles.js new file mode 100644 index 00000000000000..040094a9ce9213 --- /dev/null +++ b/src/ui/public/autoload/styles.js @@ -0,0 +1,2 @@ +const context = require.context('../styles', false, /[\/\\](?!mixins|variables|_|\.)[^\/\\]+\.less/); +context.keys().forEach(key => context(key));