-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Themes: Bootstrap theme-details store for theme sheets #3279
Conversation
8595df2
to
8b809d7
Compare
@@ -97,7 +97,7 @@ jsLoader = { | |||
}; | |||
|
|||
if ( CALYPSO_ENV === 'development' ) { | |||
webpackConfig.plugins.push( new PragmaCheckPlugin() ); | |||
// webpackConfig.plugins.push( new PragmaCheckPlugin() ); |
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.
Problem: state/themes/actions.js
is replaced with noop in webpack.config.node.js
but the pragma checker doesn't know this, so we still get the not /** @ssr-ready **/
error. @ehg: any idea how we should handle this?
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.
Hmm, we can add analytics to the ignore array, but I think state/themes/actions.js
should be ssr-ready from the start. Will take a look.
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.
Pushed acc169f
if ( config.isEnabled( 'server-side-rendering' ) ) { | ||
let themeData = themeDetails.get( req.params.theme_slug ); | ||
if ( ! themeData ) { | ||
wpcom.undocumented().themeDetails( req.params.theme_slug, ( error, data ) => { |
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 wonder if we could get away without having to use memcache by:
- Checking the published date of the theme details response
- If it's greater than the one in the cache,
renderToString
using the new data. - If it's not, just serve the cached
renderToString
markup
We could also avoid blocking the request by always serving the data from the cache, and fire off API calls that will invalidate/update the cache when necessary.
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 like that idea :-)
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.
We could also avoid blocking the request by always serving the data from the cache, and fire off API calls that will invalidate/update the cache when necessary.
This PR was actually working like that a few commits back and can easily be tweaked to do that again. I wasn't quite sure which way was best. It strikes me now that never rendering async is less complex overall.
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 wonder if we could get away without having to use memcache by...
Yeah, was thinking about this, or maybe even using the api response header, which may let us leverage some existing libraries to handle it?
Once we receive new api data, how do we clear the renderToString cache?
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, was thinking about this, or maybe even using the api response header, which may let us leverage some existing libraries to handle it?
Yep. I wonder whether we sent ETags or what the Expires header is like.
Once we receive new api data, how do we clear the renderToString cache?
You mean how do we know what key to clear? Maybe we key the rts cache using something like dataTimestamp+lang
?
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 wonder whether we sent ETags or what the Expires header is like.
Expires and cache control headers are explicitly set to not cache, which makes sense. I think comparing the publish/update date is probably fine for now.
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.
RE #3279 (comment) - implemented a basic version of this in b560f0a
1818d64
to
2c6f0f0
Compare
Rebased, not using |
Changed to 'In Progress', as this should be based off #3386, and not merged until that lands. Also, we need more discussion around #3279 (comment) |
0c9eccf
to
cf073b9
Compare
Done. |
themeName: theme.name, | ||
themeAuthor: theme.author, | ||
themeScreenshot: theme.screenshot, | ||
} ); |
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.
Could this call go somewhere deeper in the component hierarchy, e.g. inside ThemesListFetcher
(to provide some initial state there, also on the client side)? Thinking about how to keep this part of server/pages
as generic as possible for isomorphic routing.
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.
Actually, renderThemeSheet
looks like something we could keep as middleware in my-sites/themes/controller
: it basically writes to context
and dispatches stuff via store
, which should be available via context
.
4e37c27
to
aa0a25c
Compare
setSection = require( 'state/ui/actions' ).setSection; | ||
setSection = require( 'state/ui/actions' ).setSection, | ||
wpcom = require( 'lib/wp' ), | ||
ActionTypes = require( 'state/themes/action-types' ); |
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.
Should be ThemesActionTypes
8c9b414
to
f8ecf9c
Compare
Rebased. |
Added dynamic data to content sections and fixed price. Next up: make code not suck. |
4514c0c
to
e128fc0
Compare
rebased after #3464 |
//TODO: use makeElement() | ||
context.primary = ( | ||
<ReduxProvider store={ context.store } > | ||
<Head title={ props.title } isSheet> |
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.
We're still using the hardcoded Pineapple Fifteen title, but I think that should be hooked up in a separate PR
title={ isSheet ? 'Pineapple Fifteen Theme — WordPress.com' : get( 'title', tier ) } |
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 think we should leave this until after routing. It's possibly being implemented in one of those PRs.
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.
Maybe this stuff, with some modifications? -> https://github.com/Automattic/wp-calypso/pull/3425/files#diff-85f90b61d9c36634c5464a3180470726R70
b622acf
to
1d17c23
Compare
bumpStat( 'calypso-ssr', 'loggedout-design-cache-miss' ); | ||
} | ||
|
||
export function render( element, path, initialState ) { |
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.
Maybe better to have a key
param instead of path
and initialState
, allowing caller to decide appropriate key?
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, also I was thinking the API could be something like render.set( key, element )
and render.get( key )
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, also I was thinking the API could be something like render.set( key, element ) and render.get( key )
I think better to put a comment before the async renderThemeSheet()
than expose the caching from the render module.
eac589a
to
e187341
Compare
function updateRenderCache( themeSlug ) { | ||
wpcom.undocumented().themeDetails( themeSlug, ( error, data ) => { | ||
if ( error ) { | ||
console.log( `Error fetching theme ${ themeSlug } details: `, error.message || error ); |
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.
Can we use debug
for these console.logs?
👍 after squash. Let's get this in and iterate. |
361e87c
to
fb146d1
Compare
fb146d1
to
f69e60c
Compare
Wrap theme sheets with the theme-details component to use real data, and fetch and cache data server-side for initial render. Server-side data caching: - if the theme's details aren't in the themeDetails cache, don't SSR & fire and forget a theme details XHR, which will renderToString when it has data for the theme. - if the theme is in the cache, then we'll have markup for it, so render that doing it this way means we don't have to block the request, but we lose SSR for cache misses. i'm unsure of whether blocking on the response will be a problem (need timing stats), if it is, memcache or a CDN would be preferable.
f69e60c
to
b2cc08d
Compare
Themes: Bootstrap theme-details store for theme sheets
if ( config.isEnabled( 'server-side-rendering' ) ) { | ||
const theme = themeDetails.get( req.params.theme_slug ); | ||
if ( theme ) { | ||
Object.assign( context, renderThemeSheet( theme ) ); |
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 it possible that this code path ends up renderingToString synchronously via renderThemeSheet()
and render()
, i.e. blocking the request?
I find the two different caches and how they interact rather confusing, hard to reconcile with #3562, and possibly error-prone. If we want to cache the markup based on If we just want to cache the theme details data for their own sake, we should do that inside our Redux reducer -- it's made for storing data for different theme IDs already, so we're kind of re-creating that logic here. |
debug( 'caching', themeSlug ); | ||
themeDetails.set( themeSlug, data ); | ||
// update the render cache | ||
renderThemeSheet( data ); |
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.
Why don't we also render index.jade
here?
Filed #3774 based on my comments. |
To Test
Go to http://calypso.localhost:3000/themes/{theme} both logged-in and logged-out