osmosis-frontend
                                
                                
                                
                                    osmosis-frontend copied to clipboard
                            
                            
                            
                        Server side load non-user store data
Problem
We're using nextjs for the refactor code, thus making it really easy to optimize our frontend through code splitting, server side rendering, assets-over-CDN, etc. Currently, next.js is rendering the small amount of html contained on each page, but none of the actual data. It's slightly faster than pre-refactor, but we could do better. Each time the user loads the page, we still need to kick off API requests to get all data. This causes users to have to wait to load data when they first visit the site.
Proposed Solution
As discussed in PR #343, we should kick off API requests for non-user data on the server on page request (we could tweak the cache as well to only do this for certain time intervals). We could create a single interface that non-user-data stores could implement that contains two methods; one would trigger an Axios request for their data and return it, the other would accept their API data and save it.
On each next.js page, we would trigger the first method mentioned above to get the data from all relevant stores and return them in the getServerSideProps method. Then initially in each page component we could call the second method above to pass the server-fetched data from the components props and save it in the stores. Then, react will run one render cycle with the store data already there and ready to be memoized and returned. With the right cache settings many users would be able to load the pools page instantly with all pool data already there! This has the potential to make our frontend incredibly performant.
Implementation idea
- Extend 
ObservableChainQuery<T>asObservableSSRChainQuery<T>for non-account query objects - Create an interface, 
SSRStore, that generically describes the ability to fetch and accept API data - Extend 
RootStorewith a class that implementsSSRStorecontaining all SSR observable chain queries. It will contain the logic of fetching and returning data from all SSR stores as well as accepting the same type of data and setting them into the store.- With Next.js we will call the 
SSRStore.fetch()method in thegetServerSidePropsfunction for each relevant page. Then in the render function we will use theSSRStore.setResponse(r)method to populate the stores in time for the jsx to be rendered. We can set the cache headers in thegetServerSidePropsmethod to let Next.js cache store data. This is how we will efficiently achieve near instant load times on the pools page. 
 - With Next.js we will call the 
 
To research: should we load all store data? Or just for the NextPage being requested? If we change pages, will SSR stores be redundantly overwritten with the new NextPage's SSR props? Is there a way to reuse the store for subsequent pages? If  the store can't be reused, we should look into allowing SSRStore to only fetch from stores grouped by NextPage.
Re Research: when second+ page is fetched via 'next/link' or 'next/router', getServerSideProps is run on the new page.
We now have 2 options:
- We should avoid loading data on the server that is not relevant to that page
 - We should figure out if we can pass a flag into the 
ctxforgetServerSideProps(ctx)to indicate that this isn't the firstNextPagebeing loaded (TODO: research if this is possible) 
Re Research: for second bullet:
Currently, our js bundle for every page is quite large at 1.7mb. We should investigate splitting the root store for stores on each page. Then, as users navigate the pages the store object can increase in size. Two approaches.
- Simple: root store contains stores common across all pages. When a user navigates pages, specific stores could then be appended to the root store. We would add logic to each 
NextPageto see if the root store needs to be expanded, and if so (AKA the user hasn't needed these queries yet as they navigate the app), we will expand it by constructing the page-specific stores. - Aggressive: the root store contains nearly no stores besides those needed to load the sidebar. When a user visits a page, it will check for the needed stores and init them if not present (perhaps along with SSR props). We should do this in such a way that Next.js will also code split some store logic with each page.
 
May be semantically more correct to refer to store population as "hydration" as Next.js does.
Seems webpack tree shaking is unable to drop @ethereumjs/common & @ensdomains/resolver
Perhaps a change to @keplr-wallet would help. We need these properties to allow for tree shaking.
In response to "Implementation idea" bullets:
ObservableChainQueryexposesasync waitFreshResponse()andsetResponse(), so an*SSR*interface/class would not provide functionality, and would just add complexity- ""
 
Iceboxing as we decided to optimize performance of pools page w/ React alone. If the Osmosis all pools query is fast, the page will also be fairly fast.
We should reimplement approaches seen in PR #488 should nodes be slow / change our mind.