Skip to content
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

Move things around, make the navigation calculation run in seperate thread #955

Merged
merged 6 commits into from
Sep 14, 2020

Conversation

karelhala
Copy link
Contributor

@karelhala karelhala commented Sep 9, 2020

Features

  • Option to have an array of permission functions
  • Reduces chrome bundle size from 3.2 MB to 1.6 MB

Depracated

  • disabled_on_stable - this field should no longer be used as consumers can use permissions function
  • appNav - no longer possible to pass custom application navigation

@karelhala karelhala force-pushed the refactor-navigation branch 3 times, most recently from 5f2323f to e3f0e48 Compare September 9, 2020 15:34
@codecov-commenter
Copy link

codecov-commenter commented Sep 9, 2020

Codecov Report

Merging #955 into master will decrease coverage by 1.45%.
The diff coverage is 50.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #955      +/-   ##
==========================================
- Coverage   52.58%   51.12%   -1.46%     
==========================================
  Files          53       56       +3     
  Lines        1046     1021      -25     
  Branches      212      200      -12     
==========================================
- Hits          550      522      -28     
- Misses        395      396       +1     
- Partials      101      103       +2     
Impacted Files Coverage Δ
src/js/App/Sidenav/AppSwitcher.js 81.81% <ø> (ø)
src/js/App/Sidenav/index.js 0.00% <0.00%> (-83.34%) ⬇️
src/js/chrome.js 0.00% <0.00%> (ø)
src/js/inventory/index.js 9.09% <0.00%> (ø)
src/js/redux/action-types.js 100.00% <ø> (ø)
src/js/redux/actions.js 76.00% <ø> (-2.79%) ⬇️
src/js/entry.js 25.75% <17.64%> (+5.75%) ⬆️
src/js/App/Sidenav/SideNav.js 23.07% <23.07%> (ø)
src/js/App/Header/index.js 28.57% <28.57%> (-71.43%) ⬇️
src/js/App/Sidenav/Loader.js 33.33% <33.33%> (ø)
... and 10 more

@karelhala karelhala force-pushed the refactor-navigation branch 4 times, most recently from 15a35d0 to fc26489 Compare September 10, 2020 14:28
@karelhala karelhala marked this pull request as ready for review September 10, 2020 14:28
@@ -12,172 +12,126 @@ import './Navigation.scss';

const basepath = document.baseURI;

const openshiftLinks = {
supportcases: {
const extraLinks = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make sure the Documentation link is always the last one?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure thing! I've made it to match what was here previously, but I've seen the ticket about matching position of all docs link everywhere.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome. That got merged in with #942 so I just wanted to make sure we didn't revert what we just committed 😄

Copy link
Contributor

@Hyperkid123 Hyperkid123 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a definite improvement. I took a look at the react profiler and these are some of the observations.

Before

We have 3 renders on the initial load. The final render is committed around 3s. The number will never be precise.

After

We now have 4 renders but committed at around 1.6s so the cut on initial render time about 50% on my machine. 🎉

The biggest "bottleneck" I see is the transition from loaders to the actual navigation. That is mostly caused by evaluating the YAML file which seems to be quite an expensive operation. The jump between commits is 0.4s to 1.6s and that is with cached main.yml file.

@karelhala could we just store the nav JSON structure to sessionStorage and give it a couple of hours of timeout? Or use the same cache strategy as for the YAML file? This would further decrease the time to first interactive.

Edit: here is a gif where you can see the time commits. As you can see, it only takes around 20ms to render the whole nav from the JSON. But it takes around 1.2s to actually evaluate the code itself.
chrome-speed


const HeaderLoader = () => <React.Fragment />;

export default HeaderLoader;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can just export React.Fragment. No need for additional node in the VirtualDOM.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to use some fancy loader similiar to navigation, but had hard time doing it. Let's nuke this file and use just Fragment there.

SideNav.propTypes = {
activeTechnology: PropTypes.string,
globalNav: PropTypes.arrayOf(PropTypes.shape({
[PropTypes.string]: PropTypes.any
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should list all used attributes instead of creating a generic object. If you want that just use PropTypes.object.

@@ -10,24 +13,24 @@ export let getNavFromConfig = async (masterConfig) => {
}, {});
};

const isCurrVisible = (permissions) => Promise.all(
flatMap([permissions], ({ method } = {}) => (
// (null, undefined, true) !== false
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

leftover comment?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really, this is to show what is actually evalueted here because the boolean logic is slightly more complex than it could be for new commers.

const isCurrVisible = (permissions) => Promise.all(
flatMap([permissions], ({ method } = {}) => (
// (null, undefined, true) !== false
visibilityFunctions?.[method]?.(...permissions.args || []) !== false || false
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the || false is necessary here. x !== false will always return boolean value. Or am I crazy 😆 I must say this makes me think much harder than it should.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the false is not necessary here, the logic is if visibility function return something else then false return true, otherwise false. But that's correct and doesn't need the || false

const groupedNav = await getNavFromConfig(safeLoad(yamlConfig));

const [active, section] = [getUrl('bundle'), getUrl('app')];
const globalNav = (groupedNav[active] || groupedNav.insights).routes;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has the potential to crash. I would add ?.


const [active, section] = [getUrl('bundle'), getUrl('app')];
const globalNav = (groupedNav[active] || groupedNav.insights).routes;
let activeSection = globalNav.find(({ id }) => id === section);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

activeSection is never re-assigned.

@karelhala
Copy link
Contributor Author

@Hyperkid123 I was thinking about storing the calculated JSON in cache as well, but didn't wanted to bloat this PR even more. But let's do it to improve loads even more!

@Hyperkid123
Copy link
Contributor

Hyperkid123 commented Sep 11, 2020

@Hyperkid123 I was thinking about storing the calculated JSON in cache as well, but didn't wanted to bloat this PR even more. But let's do it to improve loads even more!

@karelhala We can do it in different PR if you want. It will make it easier to review and test.

@karelhala karelhala force-pushed the refactor-navigation branch 2 times, most recently from 3b50bf9 to c4dc7b6 Compare September 11, 2020 13:41
Hyperkid123
Hyperkid123 previously approved these changes Sep 14, 2020
@@ -244,7 +244,7 @@ exports[`Navigation should render corectly 1`] = `
ariaRightScroll="Scroll right"
>
<NavExpandable
className="ins-m-navigation-align"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This css is required to fix the navigation text left alignment. Kan you keep it? (introduced in #958)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure thing!

@karelhala karelhala merged commit b26241a into RedHatInsights:master Sep 14, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants