-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
[SharedUX][PoC] Move to a package architecture #127419
[SharedUX][PoC] Move to a package architecture #127419
Conversation
|
||
import { NoDataViews as NoDataViewsComponent } from './no_data_views.component'; | ||
|
||
export interface Props { | ||
onDataViewCreated: (dataView: DataView) => void; | ||
onDataViewCreated: (dataView: unknown) => void; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want there to be a better type for this. I've asked in the Typescript group.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's wrong with DataView
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@majagrubic DataView is a type from src/plugins/data_views/public
. Packages cannot depend on plugins.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One overall comments / questions:
- Do we need a separate storybook package? Is this to keep
components
as small as possible? Because it feels this should be a part of thecomponents
package - I don't fully understand where are
services
getting their dependencies from. Where isdataViewEditor
being plugged in?
import { NoDataViews } from './no_data_views'; | ||
|
||
describe('<NoDataViewsPageTest />', () => { | ||
let services: SharedUXServices; | ||
let mount: (element: JSX.Element) => ReactWrapper; | ||
|
||
beforeEach(() => { | ||
services = servicesFactory(); | ||
services = mockServiceFactories.servicesFactory(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the module is called somethingServiceFactories
, should the method be called services
rather than servicesFactory
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The singleton is a collection of all of the factories, and the servicesFactory
universal factory for all of them. I think the naming could definitely use some work.
@@ -0,0 +1,126 @@ | |||
load("@npm//@bazel/typescript:index.bzl", "ts_config") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this something auto-generated?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PS. I've never seen an |
The intention is to eventually split the components package into smaller packages. The catch with packages compared to plugins is you can import code async, but like any package from npm, you get the entire package. For now, our component footprint is small and the divides aren't as clear.
Check out |
@elasticmachine merge upstream |
c2d2706
to
757a6c5
Compare
@elasticmachine merge upstream |
978c447
to
8c1b0bd
Compare
@elasticmachine merge upstream |
💚 Build SucceededMetrics [docs]Module Count
Public APIs missing comments
Async chunks
Public APIs missing exports
Page load bundle
Unknown metric groupsAPI count
ESLint disabled line counts
Total ESLint disabled count
History
To update your PR or re-run it, just comment with: |
For ease of review and commit history, this PoC PR has been split into these four stacked pull requests:
Closing out the PR. Thanks all for the feedback and support! |
|
||
import { NoDataViews as NoDataViewsComponent } from './no_data_views.component'; | ||
|
||
export interface Props { | ||
onDataViewCreated: (dataView: DataView) => void; | ||
onDataViewCreated: (dataView: unknown) => void; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we're in the process of migrating to packages, having a types
package is a pretty standard deal. We should really work on getting one for common types, at least the ones from data
and data_view
plugins. We made all this effort to migrate to typescript, only to be taking a step back now. Is this on your radar as well @spalger ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if that would accomplish more than colocating the types today. Technically, Bazel already builds a separate types "package"... and I'd be worried about keeping types too far from the relevant code.
At the same time, I'd be interested in creating a @kbn/shared-ux-types
package for common and public types. I'd just want to keep it curated to truly universal/common types, rather than default to putting all types there.
It's a good point. Let's think on it a bit, see what we'd propose to put in a types
package to see if there'd be value in it. @spalger @stacey-gammon I'd be curious on your input here, as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My opinion is to stick to our '"organize by domain" philosophy and co-locate types with the thing they are describing (meaning DataView
types should be next to DataView
implementation stuff).
Am I understanding the issue here is that packages can't depend on plugins and thats why this had to change from a type to unknown
?
I think we will eventually be able to solve this when each plugin is a package, and there is no separate packages
directory at all (#112886)
cc @mistic
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I feel like shared-ux is just a little ahead of the curve here. The DataView plugin will eventually be a package and @kbn/shared-ux*
will be able to import the DataView
type from it, a @kbn/data-views-types
package, or something similar but co-located with the data views implementation stuff.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd just want to keep it curated to truly universal/common types, rather than default to putting all types there.
My opinion is to stick to our '"organize by domain" philosophy and co-locate types with the thing they are describing
Totally agree +++
Summary
This PR moves portions of the SharedUX plugin out of the plugin and into packages.
Why?
With only a few components, we've run into issues with circular dependencies. The reason being our plugin is consuming code and types from other plugins, and once we do, that plugin can't use our plugin or its components. To mitigate this, we need to keep Shared UX as dependency free as possible.
One of the approaches @majagrubic explored was moving pure components to another plugin to be consumed by dependency plugins. While it worked, we all agreed it wasn't ideal.
Talking with ops, it became clear our assets don't actually need a plugin lifecycle to operate. So I took some time this evening to decouple our components, services and utilities to packages.
Packages
@kbn/sharedux-services
- Our base service abstraction definitions and mocks.@kbn/sharedux-storybook
- All storybook-related code, including a SB-impl of our service layer.@kbn/sharedux-utility
- A home for utility code.@kbn/sharedux-components
- React componentsCode from
src/plugins/shared_ux
was refactored and moved to these packages.Plugin
The Shared UX plugin provides stateful, Kibana-specific implementations of the services in
@kbn/sharedux-services
and a React context provider that wires components from@kbn/sharedux-components
. Any plugin that is not a dependency for our services can makesrc/plugins/shared_ux
a dependency and consume a pre-wired context that will make components from@kbn/sharedux-components
"just work". To make life even easier, the Shared UX plugin re-exports these components, so this becomes an implementation detail.The nice thing is, dependency plugins that still need to use components from Shared UX but need to avoid the circular dependency can either work with us to hoist the dependency, or consume the pure component from
@kbn/sharedux-components
, (as we attempted with #126491). I have no doubt there is a better work-around in the medium term, but we need to start somewhere.I'll flesh out the rest of the details shortly, but I wanted to get this architecture out for feedback before we create more components. I know there's a pressing need to get
NoDataView
decoupled, so this PR becomes pressing, as well.Feedback welcome!