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

Navigate using render #374

Merged
merged 8 commits into from
Aug 27, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions manifest.json
Original file line number Diff line number Diff line change
@@ -1,25 +1,19 @@
{
"vendor": "vtex",
"name": "render-runtime",
"version": "8.50.0",
"version": "8.51.0-beta.2",
"title": "VTEX Render runtime",
"description": "The VTEX Render framework runtime",
"defaultLocale": "pt-BR",
"builders": {
"react": "3.x"
},
"dependencies": {
"vtex.pages-graphql": "2.x"
},
"mustUpdateAt": "2018-09-05",
"categories": [],
"registries": [
"smartcheckout"
],
"settingsSchema": {},
"scripts": {
"prereleasy": "bash lint.sh",
"postreleasy": "vtex publish --verbose"
"prereleasy": "bash lint.sh"
},
"$schema": "https://raw.githubusercontent.com/vtex/node-vtex-api/master/gen/manifest.schema"
}
173 changes: 112 additions & 61 deletions react/components/RenderProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,25 @@ import debounce from 'debounce'
import { canUseDOM } from 'exenv'
import { History, UnregisterCallback } from 'history'
import PropTypes from 'prop-types'
import { merge, mergeWith } from 'ramda'
import { merge, mergeDeepRight, mergeWith } from 'ramda'
import React, { Component, Fragment, ReactElement } from 'react'
import { ApolloProvider } from 'react-apollo'
import { Helmet } from 'react-helmet'
import { IntlProvider } from 'react-intl'

import { fetchAssets, getImplementation, prefetchAssets } from '../utils/assets'
import { generateExtensions } from '../utils/blocks'
import PageCacheControl from '../utils/cacheControl'
import { getClient } from '../utils/client'
import { OperationContext } from '../utils/client/links/uriSwitchLink'
import { traverseComponent } from '../utils/components'
import {
isSiteEditorIframe,
RENDER_CONTAINER_CLASS,
ROUTE_CLASS_PREFIX,
routeClass,
} from '../utils/dom'
import { isEnabled } from '../utils/flags'
import {
goBack as pageGoBack,
mapToQueryString,
Expand All @@ -30,15 +33,17 @@ import {
queryStringToMap,
scrollTo as pageScrollTo,
} from '../utils/pages'
import { fetchDefaultPages, fetchNavigationPage } from '../utils/routes'
import {
fetchDefaultPages,
fetchNavigationPage,
fetchServerPage,
} from '../utils/routes'
import { TreePathContextProvider } from '../utils/treePath'
import BuildStatus from './BuildStatus'
import ExtensionManager from './ExtensionManager'
import ExtensionPoint from './ExtensionPoint'
import { RenderContextProvider } from './RenderContext'
import RenderPage from './RenderPage'
import { generateExtensions } from '../utils/blocks'
import { OperationContext } from '../utils/client/links/uriSwitchLink'

interface Props {
children: ReactElement<any> | null
Expand Down Expand Up @@ -516,14 +521,18 @@ class RenderProvider extends Component<Props, RenderProviderState> {
}

const { navigationRoute, fetchPage } = state
const { id: page, params } = navigationRoute
const { id: maybePage, params } = navigationRoute
const transientRoute = { ...route, ...navigationRoute }
const {
[page]: { allowConditions, declarer },
} = pagesState

// We always have to navigate to a page. If none was found, we
// navigate to the current page with preview
const allowConditions =
pagesState[maybePage] && pagesState[maybePage].allowConditions
const declarer = pagesState[maybePage] && pagesState[maybePage].declarer
const shouldSkipFetchNavigationData =
Copy link
Contributor

Choose a reason for hiding this comment

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

This was a huge improvement when navigating to pages already cached and that don't have conditional content (basically only store routes were declaring allowConditions: true) 😢

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 realized that and added it back

(!allowConditions && loadedPages.has(page)) || !fetchPage
(!allowConditions && loadedPages.has(maybePage)) || !fetchPage
const query = queryStringToMap(location.search) as RenderRuntime['query']
const page = maybePage || route.id

if (shouldSkipFetchNavigationData) {
return this.setState(
Expand Down Expand Up @@ -561,7 +570,9 @@ class RenderProvider extends Component<Props, RenderProviderState> {
page,
preview: true,
query,
route: transientRoute,
route: isEnabled('RENDER_NAVIGATION')
? mergeDeepRight(route, navigationRoute)
: transientRoute,
},
() => {
this.replaceRouteClass(page)
Expand All @@ -577,47 +588,79 @@ class RenderProvider extends Component<Props, RenderProviderState> {
// well as the fields that need to be retrieved, but the logic
// that the new state (extensions and assets) will be derived from
// the results of this query will probably remain the same.
return fetchNavigationPage({
apolloClient,
declarer,
locale,
paramsJSON,
production,
query: JSON.stringify(query),
renderMajor,
routeId,
skipCache: false,
}).then(
({
appsEtag,
cacheHints,
components,
extensions,
matchingPage,
messages,
pages,
settings,
}: ParsedPageQueryResponse) => {
const updatedRoute = { ...transientRoute, ...matchingPage }
this.setState(
{
return isEnabled('RENDER_NAVIGATION')
? fetchServerPage({
path: navigationRoute.path,
query,
}).then(
({
appsEtag,
cacheHints: mergeWith(merge, this.state.cacheHints, cacheHints),
components: { ...this.state.components, ...components },
extensions: { ...this.state.extensions, ...extensions },
loadedPages: loadedPages.add(page),
messages: { ...this.state.messages, ...messages },
page,
components,
extensions,
matchingPage,
messages,
pages,
preview: false,
query,
route: updatedRoute,
settings,
},
() => this.sendInfoFromIframe()
}: ParsedServerPageResponse) => {
this.setState(
{
appsEtag,
components: { ...this.state.components, ...components },
extensions: { ...this.state.extensions, ...extensions },
loadedPages: loadedPages.add(matchingPage.routeId),
messages: { ...this.state.messages, ...messages },
page: matchingPage.routeId,
pages,
preview: false,
query,
route: matchingPage,
settings,
},
() => this.sendInfoFromIframe()
)
}
)
: fetchNavigationPage({
apolloClient,
declarer,
locale,
paramsJSON,
production,
query: JSON.stringify(query),
renderMajor,
routeId,
skipCache: false,
}).then(
({
appsEtag,
cacheHints,
components,
extensions,
matchingPage,
messages,
pages,
settings,
}: ParsedPageQueryResponse) => {
const updatedRoute = { ...transientRoute, ...matchingPage }
this.setState(
{
appsEtag,
cacheHints: mergeWith(merge, this.state.cacheHints, cacheHints),
components: { ...this.state.components, ...components },
extensions: { ...this.state.extensions, ...extensions },
loadedPages: loadedPages.add(page),
messages: { ...this.state.messages, ...messages },
page,
pages,
preview: false,
query,
route: updatedRoute,
settings,
},
() => this.sendInfoFromIframe()
)
}
)
}
)
}

public prefetchPage = (pageName: string) => {
Expand Down Expand Up @@ -723,6 +766,7 @@ class RenderProvider extends Component<Props, RenderProviderState> {
production,
culture: { locale },
route,
query,
} = this.state
const declarer = pagesState[page] && pagesState[page].declarer
const { pathname } = window.location
Expand All @@ -736,25 +780,32 @@ class RenderProvider extends Component<Props, RenderProviderState> {
messages,
pages,
settings,
} = await fetchNavigationPage({
apolloClient: this.apolloClient,
declarer,
locale,
paramsJSON,
path: pathname,
production,
query: '',
renderMajor,
routeId: page,
skipCache: true,
...options,
})
} = isEnabled('RENDER_NAVIGATION')
? await fetchServerPage({
path: route.path,
query,
})
: await fetchNavigationPage({
apolloClient: this.apolloClient,
declarer,
locale,
paramsJSON,
path: pathname,
production,
query: '',
renderMajor,
routeId: page,
skipCache: true,
...options,
})

await new Promise<void>(resolve => {
this.setState(
state => ({
appsEtag,
cacheHints,
cacheHints: isEnabled('RENDER_NAVIGATION')
? state.cacheHints
: cacheHints,
components,
extensions: {
...state.extensions,
Expand Down
32 changes: 32 additions & 0 deletions react/typings/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,33 @@ declare global {
routeId: string
}

interface MatchingServerPage {
blockId: string
canonicalPath?: string
metaTags?: RouteMetaTags
pageContext: PageDataContext
title?: string
routeId: string
params: Record<string, string>
id: string
path: string
domain: string
}

interface ServerPageResponse {
appsEtag: RenderRuntime['appsEtag']
blocks: RenderRuntime['blocks']
blocksTree: RenderRuntime['blocksTree']
cacheHints: RenderRuntime['cacheHints']
contentMap: RenderRuntime['contentMap']
components: RenderRuntime['components']
extensions: RenderRuntime['extensions']
messages: RenderRuntime['messages']
pages: RenderRuntime['pages']
route: MatchingServerPage
settings: RenderRuntime['settings']
}

interface PageQueryResponse {
blocksJSON: string
blocksTreeJSON: string
Expand All @@ -330,6 +357,10 @@ declare global {
message: string
}

interface ParsedServerPageResponse extends ServerPageResponse {
matchingPage: MatchingServerPage
}

interface ParsedPageQueryResponse {
blocks: RenderRuntime['blocks']
blocksTree: RenderRuntime['blocksTree']
Expand Down Expand Up @@ -483,6 +514,7 @@ declare global {
myvtexSSE: any
rendered: Promise<RenderedSuccess> | RenderedFailure
requestIdleCallback: (callback: (...args) => any | void) => number
flags: Record<string, boolean>
}

interface BlockEntry {
Expand Down
Loading