Typescript
Although this is not a requirement, we encourage if all new code is developed in Typescript.
Kibana has crossed the 2m LoC mark. The current situation creates some scaling problems when the default out-of-the-box setup stops working. As a result, developers suffer from slow project compilation and IDE unresponsiveness. As a part of Developer Experience project, we are migrating our tooling to use built-in TypeScript features addressing the scaling problems - project references & incremental builds
In a nutshell - instead of compiling the whole Kibana codebase at once, this setup enforces splitting the code base into independent projects that form a directed acyclic graph (DAG). This allows the TypeScript compiler (tsc) to apply several advanced optimizations:
- Every project emits
publicinterfaces in the form ofd.tstype declarations generated by the TypeScript compiler - These generated
d.tstype declarations are used whenever a referenced project is imported in a depending project - This makes it possible to determine which project needs rebuilding when the source code has changed to use a more aggressive caching strategy.
More details are available in the official docs
This architecture imposes several limitations to which we must comply:
Projects cannot have circular dependencies. Even though the Kibana platform doesn't support circular dependencies between Kibana plugins, TypeScript (and ES6 modules) allows it. So in theory, you can face a problem when migrating to the TS project references, leaving you with a circular dependency to fix. When building with TypeScript project references (using
node scripts/type_checkor./node_modules/.bin/tsc -b), circular dependencies between projects will be detected and reported, which must be resolved before migration can proceed.A project must emit its type declaration. It’s not always possible to generate a type declaration if the compiler cannot infer a type. There are two basic cases:
- Your plugin exports a type inferring an internal type declared in Kibana codebase. In this case, you’ll have to either export an internal type or to declare an exported type explicitly.
- Your plugin exports something inferring a type from a 3rd party library that doesn’t export this type. To fix the problem, you have to declare the exported type manually.
Since project refs rely on generated d.ts files, the migration order does matter. You can migrate your plugin only when all the plugin dependencies already have migrated. It creates a situation where commonly used plugins (such as data or kibana_react) have to migrate first. Run node scripts/find_plugins_without_ts_refs.js --id your_plugin_id to get a list of plugins that should be switched to TS project refs to unblock your plugin migration.
Additionally, in order to migrate into project refs, you also need to make sure your plugin doesn't have circular dependencies with other plugins both on code and type imports. Circular dependencies between plugins are detected at runtime by the Kibana plugin system, which will prevent the application from starting if circular dependencies exist. When building with TypeScript project references using node scripts/type_check or ./node_modules/.bin/tsc -b, circular dependencies between projects will also be caught during the build process and must be resolved.
- Make sure all the plugins listed as dependencies in requiredPlugins, optionalPlugins & requiredBundles properties of
kibana.jsonmanifest file have migrated to TS project references. - Add
tsconfig.jsonin the root folder of your plugin.
{
"extends": "@kbn/tsconfig-base/tsconfig.json",
"compilerOptions": {
"outDir": "./target/types",
"emitDeclarationOnly": true,
"declaration": true,
"declarationMap": true
},
"include": [
// add all the folders containing files to be compiled
],
"references": [
{ "path": "../../core/tsconfig.json" },
// add references to other TypeScript projects your plugin depends on
]
}
If your plugin imports a file not listed in include, the build will fail with the next message File ‘…’ is not listed within the file list of project …’. Projects must list all files or use an 'include' pattern.
- Build your plugin using
./node_modules/.bin/tsc -b src/plugins/my_pluginornode scripts/type_check --project src/plugins/my_plugin/tsconfig.json. Fix errors if the TypeScript compiler cannot generate type declarations for your project. - Add your project reference to
referencesproperty oftsconfig.refs.json - Add your plugin to
referencesproperty and plugin folder toexcludeproperty of thetsconfig.jsonit used to belong to (for example, forsrc/plugins/**it’stsconfig.json; forx-pack/plugins/**it’sx-pack/tsconfig.json). - List the reference to your newly created project in all the Kibana
tsconfig.jsonfiles that could import your project:tsconfig.json,test/tsconfig.json,x-pack/tsconfig.json,x-pack/platform/test/tsconfig.json. And in all the plugin-specifictsconfig.refs.jsonfor dependent plugins. - You can measure how your changes affect
tsccompiler performance withnode --max-old-space-size=4096 ./node_modules/.bin/tsc -p tsconfig.json --extendedDiagnostics --noEmit. Compare withmasterbranch.
You can use https://github.com/elastic/kibana/pull/79446 as an example.