You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
summary: Anatomy of a Kibana plugin and how to build one
6
6
date: 2021-02-05
7
-
tags: ['kibana','onboarding', 'dev', 'tutorials']
7
+
tags: ['kibana','onboarding', 'dev', 'tutorials']
8
8
---
9
9
10
10
Prereading material:
@@ -14,7 +14,7 @@ Prereading material:
14
14
## The anatomy of a plugin
15
15
16
16
Plugins are defined as classes and present themselves to Kibana through a simple wrapper function. A plugin can have browser-side code, server-side code,
17
-
or both. There is no architectural difference between a plugin in the browser and a plugin on the server. In both places, you describe your plugin similarly,
17
+
or both. There is no architectural difference between a plugin in the browser and a plugin on the server. In both places, you describe your plugin similarly,
18
18
and you interact with Core and other plugins in the same way.
19
19
20
20
The basic file structure of a Kibana plugin named demo that has both client-side and server-side code would be:
@@ -33,7 +33,7 @@ plugins/
33
33
index.ts [6]
34
34
```
35
35
36
-
### [1] kibana.json
36
+
### [1] kibana.json
37
37
38
38
`kibana.json` is a static manifest file that is used to identify the plugin and to specify if this plugin has server-side code, browser-side code, or both:
39
39
@@ -42,14 +42,33 @@ plugins/
42
42
"id": "demo",
43
43
"version": "kibana",
44
44
"server": true,
45
-
"ui": true
45
+
"ui": true,
46
+
"owner": { [1]
47
+
"name": "App Services",
48
+
"githubTeam": "kibana-app-services"
49
+
},
50
+
"description": "This plugin extends Kibana by doing xyz, and allows other plugins to extend Kibana by offering abc functionality. It also exposes some helper utilities that do efg", [2]
51
+
"requiredPlugins": ["data"], [3]
52
+
"optionalPlugins": ["alerting"] [4]
53
+
"requiredBundles": ["anotherPlugin"] [5]
46
54
}
47
55
```
48
56
57
+
[1], [2]: Every internal plugin should fill in the owner and description properties.
58
+
59
+
[3], [4]: Any plugin that you have a dependency on should be listed in `requiredPlugins` or `optionalPlugins`. Doing this will ensure that you have access to that plugin's start and setup contract inside your own plugin's start and setup lifecycle methods. If a plugin you optionally depend on is not installed or disabled, it will be undefined if you try to access it. If a plugin you require is not installed or disabled, kibana will fail to build.
60
+
61
+
[5]: Don't worry too much about getting 5 right. The build optimizer will complain if any of these values are incorrect.
62
+
63
+
64
+
<DocCallOut>
65
+
You don't need to declare a dependency on a plugin if you only wish to access its types.
66
+
</DocCallOut>
67
+
49
68
### [2] public/index.ts
50
69
51
-
`public/index.ts` is the entry point into the client-side code of this plugin. It must export a function named plugin, which will receive a standard set of
52
-
core capabilities as an argument. It should return an instance of its plugin class for Kibana to load.
70
+
`public/index.ts` is the entry point into the client-side code of this plugin. Everything exported from this file will be a part of the plugins <DocLinkid="kibPlatformIntro"section="public-plugin-api"text="public API"/>. If the plugin only exists to export static utilities, consider using a package. Otherwise, this file must export a function named plugin, which will receive a standard set of
71
+
core capabilities as an argument. It should return an instance of its plugin class for Kibana to load.
53
72
54
73
```
55
74
import type { PluginInitializerContext } from 'kibana/server';
@@ -60,13 +79,32 @@ export function plugin(initializerContext: PluginInitializerContext) {
60
79
}
61
80
```
62
81
82
+
<DocCallOuttitle="Best practices for every top level index.ts file">
83
+
84
+
1. When possible, use
85
+
86
+
```
87
+
export type { AType } from '...'`
88
+
```
89
+
90
+
instead of
91
+
92
+
```
93
+
export { AType } from '...'`.
94
+
```
95
+
96
+
Using the non-`type` variation will increase the bundle size unnecessarily and may unwillingly provide access to the implementation of `AType` class.
97
+
98
+
2. Don't use `export *` in these top level index.ts files
99
+
100
+
</DocCallOut>
101
+
63
102
### [3] public/plugin.ts
64
103
65
104
`public/plugin.ts` is the client-side plugin definition itself. Technically speaking, it does not need to be a class or even a separate file from the entry
66
-
point, but all plugins at Elastic should be consistent in this way.
105
+
point, but all plugins at Elastic should be consistent in this way.
@@ -84,10 +122,9 @@ export class DemoPlugin implements Plugin {
84
122
// called when plugin is torn down during Kibana's shutdown sequence
85
123
}
86
124
}
87
-
```
88
-
125
+
```
89
126
90
-
### [4] server/index.ts
127
+
### [4] server/index.ts
91
128
92
129
`server/index.ts` is the entry-point into the server-side code of this plugin. It is identical in almost every way to the client-side entry-point:
93
130
@@ -115,7 +152,7 @@ export class DemoPlugin implements Plugin {
115
152
}
116
153
```
117
154
118
-
Kibana does not impose any technical restrictions on how the the internals of a plugin are architected, though there are certain
155
+
Kibana does not impose any technical restrictions on how the the internals of a plugin are architected, though there are certain
119
156
considerations related to how plugins integrate with core APIs and APIs exposed by other plugins that may greatly impact how they are built.
120
157
121
158
### [6] common/index.ts
@@ -124,8 +161,8 @@ considerations related to how plugins integrate with core APIs and APIs exposed
124
161
125
162
## How plugin's interact with each other, and Core
126
163
127
-
The lifecycle-specific contracts exposed by core services are always passed as the first argument to the equivalent lifecycle function in a plugin.
128
-
For example, the core http service exposes a function createRouter to all plugin setup functions. To use this function to register an HTTP route handler,
164
+
The lifecycle-specific contracts exposed by core services are always passed as the first argument to the equivalent lifecycle function in a plugin.
165
+
For example, the core http service exposes a function createRouter to all plugin setup functions. To use this function to register an HTTP route handler,
129
166
a plugin just accesses it off of the first argument:
130
167
131
168
```ts
@@ -135,14 +172,16 @@ export class DemoPlugin {
135
172
public setup(core:CoreSetup) {
136
173
const router =core.http.createRouter();
137
174
// handler is called when '/path' resource is requested with `GET` method
[1] The interface for plugin’s dependencies must be manually composed. You can do this by importing the appropriate type from the plugin and constructing an interface where the property name is the plugin’s ID.
223
262
224
263
[2] These manually constructed types should then be used to specify the type of the second argument to the plugin.
Copy file name to clipboardExpand all lines: docs/development/plugins/expressions/public/kibana-plugin-plugins-expressions-public.expressionfunctiondefinitions.md
Copy file name to clipboardExpand all lines: docs/development/plugins/expressions/server/kibana-plugin-plugins-expressions-server.expressionfunctiondefinitions.md
0 commit comments