Closed marcelltoth closed 3 years ago
I'm surprised that removing tree list went so smoothly. I was expecting much bigger refactor. At this point the code is way more accessible and considering current requirements that change might be good to have. I got used to tree list usage, also got familiar with it to some extent, but trying to add recent changes made it too painful and unnecessarily complex. In the end it's a matter of picking between virtualization and simplicity. I didn't notice anything breaking with this approach so far, though porting tests might encounter something that was missed. Generally I like this approach as it solves problems that we are struggling with for some time, though I'm curious of the opinion from the void side.
I'm surprised that removing tree list went so smoothly. I was expecting much bigger refactor. At this point the code is way more accessible and considering current requirements that change might be good to have. I got used to tree list usage, also got familiar with it to some extent, but trying to add recent changes made it too painful and unnecessarily complex. In the end it's a matter of picking between virtualization and simplicity.
@mallachari yeah, it's probably because the last time you looked at the component, JSV was strictly tied to tree-list.
Plenty of UI components accessed tree-list
nodes directly (its metadata
), and the whole tree was somewhat built on top of tree-list's tree (we simply created tree-list tree nodes when iterating over schemas, etc.)
It was painful as hell to get rid of that tree-list
usage. I had to spend 2-3 days to do that, but had to do it, so that you all don't hate me :trollface:
Once JSV was set to use JST, the tree-list was actually used in one spot, that was still quite tangled, but there was not much I could do about it, cause we still had to map JST node with a tree-list node and so on.
Speaking of the PR, I'm going to review it soon, probably today or tomorrow.
@mallachari yeah, it's probably because the last time you looked at the component, JSV was strictly tied to tree-list. Plenty of UI components accessed
tree-list
nodes directly (itsmetadata
), and the whole tree was somewhat built on top of tree-list's tree (we simply created tree-list tree nodes when iterating over schemas, etc.) It was painful as hell to get rid of thattree-list
usage. I had to spend 2-3 days to do that, but had to do it, so that you all don't hate me :trollface: Once JSV was set to use JST, the tree-list was actually used in one spot, that was still quite tangled, but there was not much I could do about it, cause we still had to map JST node with a tree-list node and so on.
Oh yeah, I wouldn't have attempted this a few months ago π . The JST-extraction was amazing, it took out most of the core logic without having any UI-related dependencies. This is philosophically meant to be a follow-up to that PR, completing what you started there.
Yeah, to be frank, when working on https://github.com/stoplightio/json-schema-viewer/pull/91 and related PR, I had a moment when I thought it might be easier to simply write a new component.
Speaking of dropping virtualization, I'm totally down for it, as long as it doesn't meaningfully impact performance. I know very well how difficult it was to deal with it, therefore I totally understand your motivation. In any case, I'll take a look at it soon, but I doubt I'll have any major objections unless any of the test models I use for testing turns out to be slow to render, yet hopefully that's not the case.
I'm okay with dropping tree list, therefore I'm also fine with the chosen approach Ping me when this PR is ready and I'll be happy to have a final pass.
The PR looks great! So much more deletions than insertions π€© But I haven't look into detail, I just wanted to say that this PR will automatically close this one:
And I guess we shouldn't do this because we still need to update it in studio π€·ββοΈ
Oh, these magic words always get me, even though I know them π Thanks for the heads-up @domagojk, I'll update it.
I'm okay with dropping tree list, therefore I'm also fine with the chosen approach Ping me when this PR is ready and I'll be happy to have a final pass.
@P0lip I cleaned up the TODOs, addressed your comments and reimplemented the required props with one change: I swapped the custom rowRenderer
feature for a rowAddon
that does pretty much the same and fits the masking use-case just as well. Reasoning being that with SchemaRow
now rendering its own children, writing a correct and good looking rowRenderer
would be tricky I found out when trying it out in the storybook. This narrowed feature-set still serves the same purpose but should be much easier to use.
The only TODO left is the tests, which are being handled by #111 first, otherwise this is ready for a next pass.
Hmm, or maybe not. This is what happens when I try to open one of our reference models. (scroll to the bottom of my comment, it's not an issue caused by your PR, but a relatively minor issue in JST)
Chromium is no different. :cry:
Note - I modified the story to load only a single instance of JSV instead of two.
.add('stress-test schema', () => (
<>
<div style={{ height: '100vh', overflowY: 'scroll' }}>
<JsonSchemaViewer
schema={stressSchema as JSONSchema4}
defaultExpandedDepth={number('defaultExpandedDepth', 2)}
onGoToRef={action('onGoToRef')}
/>
</div>
</>
))
It's likely to be something off with JST meeting some very recursive data, as the model I test it against has plenty of such. I'll look into it now.
I got the fix for that JST issue, but even with that, it's still quite slow. With profiling on and no CPU throttling it takes over a second for render, which is probably too much. With CPU throttling set to 4x, it's over 7s. Do note that I still test it having the above storybook tweak applied.
Now, in the case of current origin/beta
tip the results are ~250ms and ~750ms respectively for CPU 4x throttling.
Whether it's acceptable or not, it's up to Product team, I suppose.
:tada: This PR is included in version 4.0.0-beta.4 :tada:
The release is available on:
Your semantic-release bot :package::rocket:
:tada: This PR is included in version 4.0.0 :tada:
The release is available on:
Your semantic-release bot :package::rocket:
Alright, so this is going to be opinionated. Prep your coffee, tea, monster (π), whatever. Don't read in a bad mood please. π
Background
We've long had an issue, stoplightio/elements#667. If you read the description you can see that while it's a non-trivial problem, it feels reasonable, something that can be done.
Then we tried to implement it. We struggled. Then we invited @P0lip to help us. Then we tried again. Struggled still. Then we held a 4-hour long session together to make something useful. We still struggled, but we built some POC. I tried to build something complete myself based on our POC, but I failed. I was running into all sorts of hard-to-debug state-management-related issues, crashes, etc. Items missing from caches, TypeError-s, etc. I gave up.
TLDR
While the current state management approach JSV is using has some wonderful features, it is unfortunately borderline impossible to comprehend by basic human beings like myself. This poses a huge risk to the Elements project (and possibly the Stoplight ecosystem as a whole) because - as this oneOf/anyOf issue shows - Team Undefined seems to be simply incapable of working on it, in it's current form.
Proposal
I propose to remove most of the state-management complexity from JSV, and fall back to a basic, idiomatic react approach:
The foundation,
json-schema-tree
is kept as-is, JST is an amazing library for abstracting away the bulk of the logic. There wasn't much extra logic actually on top of what JST offers, the most notable one being array element type hoisting. (a.k.a. "flattening") That logic was moved from the SchemaTreeListTree class to custom hooks and functions, see utils.tsThe bulk of the presentation logic is kept intact, except it is now simpler as it:
PrimitiveArrayNode
, etcResults
The good
tree-list
, which is 37KB minifiedmobx
&mobx-react-lite
which are 57 KB and 6 KB respectively.The bad
Initial rendering performance is worse for large schemas, especially if
defaultExpandedDepth > 1
.The stress test which renders a 15-thousand-line json-schema twice with
defaultExpandedDepth: 2
takes a little more than 1 second on my machine vs the virtualized version, which takes about 300ms.I would say this is still definitely the "worth it" category. The results above are without any attempt at performance optimization, but even if we can't improve it much: 30k lines worth of content loading in 1 sec should be acceptable IMO. We'll throw a loading-spinner, animation or anything and it will feel butter-smooth. (Or a progress-bar, right, @wmhilton? π)
TODO