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

Server side rendering API endpoint #780

Closed
notnownikki opened this issue May 12, 2017 · 25 comments
Closed

Server side rendering API endpoint #780

notnownikki opened this issue May 12, 2017 · 25 comments
Labels
[Feature] Block API API that allows to express the block paradigm. Framework Issues related to broader framework topics, especially as it relates to javascript [Type] Question Questions about the design or development of the editor.

Comments

@notnownikki
Copy link
Member

notnownikki commented May 12, 2017

I discussed this with @youknowriad on Slack, but wanted to put it into an issue too.

The current server side rendering is problematic not as nice as it could be. If we have a block that gets a URL from the user, and does some rendering server side to embed the content in a post, we have to duplicate that rendering in the editor block too. We're doing the same work twice, without guarantee that the renders will match, and someone could easily update one and not the other.

My suggestion is to have an API endpoint that takes the required input (in the case of twitter - the URL of the tweet), and returns the rendered HTML from the server side render (which in the case of twitter, WordPress' oembed already does for us).

That way, we could simply send a twitter URL to the endpoint, and have the HTML for embedding it returned. And we only have one bit of code doing that transform from URL to embed HTML.

Additionally, sometimes we want to sandbox some things in iframes, so that javascript or form submissions or stylesheets don't affect the editor.

This is where we could use the Sandbox element (included in the twitter block PR #754 ).

The Sandbox element takes some HTML and puts it in an iframe, and makes sure any script elements in the HTML get run. This works really well for the twitter embeds, as we need to load and run javascript from twitter, but do not want it running in the same context as our editor.

Blocks that use this server side rendering mechanism would be able to flag if the returned HTML gets sandboxed or not.

This opens up the possibility of extending the Embed block so that it can do everything that WordPress oembed can do, very easily.

It would also lets us do pretty much anything a shortcode can currently do, with minimal work. We'd produce a UI asking for the same inputs the shortcode has, constuct the shortcode as a string, send it to the rendering API, and get back the HTML, all ready to go.

The saved content of these blocks would vary. In the case of the twitter block, or a shortcode-based block, it would save the content to be processed by WordPress when the post is rendered. In the case of other blocks where WordPress does not automatically process the content, it would save the HTML returned by the API.

If we get this in place, we could automate generating the base of blocks that work with shortcodes, and could add many many blocks very quickly.

@youknowriad
Copy link
Contributor

youknowriad commented May 12, 2017

The current server side rendering is problematic.

I don't think so, this issue for me is just using the current server side function (render function of a registered block) in an endpoint. It's not one way or another it's adding a feature to the server.

My suggestion is to have an API endpoint that takes the required input (in the case of twitter - the URL of the tweet), and returns the rendered HTML from the server side render (which in the case of twitter, WordPress' oembed already does for us).

I think the API should be generic, accepts a "block" (block type and attributes), or a serialized block (comment + content) and returns the SSR.

Blocks that use this server side rendering mechanism would be able to flag if the returned HTML gets sandboxed or not.

This could be just a component

<ServerSideRender blockType="" attributes={ attributes } />

and if you want it to be sandboxed

<Sandbox>
  <ServerSideRender blockType="" attributes={ attributes } />
</Sandbox>

I don't think we should add anything to the block API itself.

@notnownikki
Copy link
Member Author

I don't think so, this issue for me is just using the current server side function (render function of a registered block) in an endpoint. It's not one way or another it's adding a feature to the server.

Sorry, problematic was the wrong word :) I don't think there's anything wrong with it, it's just we're missing a feature that could save us render code duplication.

@notnownikki
Copy link
Member Author

> I think the API should be generic, accepts a "block" (block type and attributes), or a serialized block (comment + content) and returns the SSR.

<Sandbox>
  <ServerSideRender blockType="" attributes={ attributes } />
</Sandbox>

+1000 😄

@nylen
Copy link
Member

nylen commented May 12, 2017

Note that for oEmbeds at least, we just landed an endpoint in WP trunk (and planned for 4.8) that should be perfect for this:

@notnownikki
Copy link
Member Author

notnownikki commented May 12, 2017 via email

@mtias mtias added [Feature] Block API API that allows to express the block paradigm. Framework Issues related to broader framework topics, especially as it relates to javascript [Type] Question Questions about the design or development of the editor. labels May 15, 2017
@kopepasah
Copy link
Member

I am glad to have searched and found this issue before posting my own.

While building out the WordPress embed, I starting thinking about how we are building out embeds and why we are not reusing the current WordPress embed functionality. Good to see that oEmbeds are getting an endpoint (thanks for sharing @nylen) and is it definitely something we can utilize within these blocks.

@notnownikki
Copy link
Member Author

notnownikki commented May 24, 2017 via email

@kopepasah
Copy link
Member

@notnownikki I have no clarification for targeting a future release, but in this case the functionality is going in 4.8, which is set release within the next coming weeks.

The WordPress oEmbed functionality does much more than just give us the HTML, as there is a ton of "under the hood" work going on when an oEmbed is added. In my opinion, utilizing the current functionality within WordPress will save a lot of time for oEmbeds.

If anyone sees a reason why we should not give this a try, please do post here.

@youknowriad
Copy link
Contributor

I think using the proxy oEmbed endpoint is worth it for the oEmbed block but I see a great value in the SSR endpoint to avoid repeating logic in the client and the server. #870 is a good example for this.

@notnownikki
Copy link
Member Author

notnownikki commented May 24, 2017 via email

@nylen
Copy link
Member

nylen commented May 24, 2017

As far as using the oembed endpoint, I'm not sure that we should use it in this case, as it doesn't seem to be released yet, and I don't think we want to target a pre-release version of WP with gutenburg, do we? Happy if someone has clarification on this :)

Targeting WP 4.8 and functionality contained therein is fine. Once 4.8 is released (in fact we could do this at any point, now that beta versions are out), we should add a minimum version check to the plugin.

I expect that other unreleased functionality will be developed within Gutenberg itself.

In my opinion, utilizing the current functionality within WordPress will save a lot of time for oEmbeds.

+100. This will also be a really good test of this code that already exists in core.

I see a great value in the SSR endpoint to avoid repeating logic in the client and the server.

Maybe so, but this needs to be pretty carefully planned. For example, I'm imagining an endpoint like GET /wp/v2/posts/:id/blocks. To match the rest of the API design, it's possible that this needs to be a full collection that allows fetching and updating individual blocks.

One of the worst things we could do here is release multiple endpoints that provide almost the same functionality but in slightly different ways.

how do I update the code in there so that it has the new oembed endpoint? What do I tell everyone else who needs that for the plugin to run properly?

I am not sure about a VVV-specific procedure, but normally there are a few ways to accomplish this:

  • Check out the WP code from git or svn, and update it to the latest version.
  • Using WP CLI: wp core update https://wordpress.org/wordpress-4.8-beta2.zip
  • Use the WP Beta Tester plugin.

See also the 4.8 beta 2 release post.

@youknowriad
Copy link
Contributor

GET /wp/v2/posts/:id/blocks

This is not enough for our need. Because the block and the post are potentially not saved, we need to send the block markup. That said, I'm ok with duplicating the logic right now.

@notnownikki
Copy link
Member Author

@kopepasah just so you can see what I've been doing with oEmbed, #816 extends the Embed block to render things server side, and as a result, supports all the oEmbed functionality (although there are some wrinkles rendering previews in the editor that we're working on).

I'll start work on a PR for a server side rendering endpoint for blocks, and changing #816 to use the new oembed endpoint.

@westonruter
Copy link
Member

Maybe so, but this needs to be pretty carefully planned. For example, I'm imagining an endpoint like GET /wp/v2/posts/:id/blocks. To match the rest of the API design, it's possible that this needs to be a full collection that allows fetching and updating individual blocks.

I'm very keen on aligning this with designing endpoints for widgets, which I believe should be reusing blocks in a different context.

@nylen
Copy link
Member

nylen commented May 25, 2017

☝️ For publicly consumable APIs especially, it's really important that we do a lot of this kind of planning, discussion, and testing.

@westonruter
Copy link
Member

Closely related is being able to define a props schema when registering a block, per: #886 (comment) and #104 (comment)

As of now is there any validation or sanitization of a block's props? To me it seems yes there would be in JS, but since a user can just modify the flattened text to change values to be whatever they want, this couldn't be relied on. And with server-side rendering in particular on the frontend context and for dynamic blocks, it seems like passing through all blocks' props through their corresponding schemas upon saving a post content would have to be done.

@youknowriad
Copy link
Contributor

youknowriad commented Dec 22, 2017

I'm thinking we should just close this. This doesn't seem to be as useful as we thought it would. The edit is in general very different from the save method which makes this useless.

@ericnicolaas
Copy link

My understanding of what is being proposed here is to provide an API endpoint which allows the editor-side preview of a block to be rendered server-side.

I would still find something like that very useful.

I can see that this has already been implemented for embeds.

In my opinion, it makes a lot of sense to provide a more general purpose API endpoint and a component such as the ServerSideRender component described by @youknowriad above. In particular, this would greatly simplify the process of converting existing shortcodes into dynamic blocks.

Drawing from my own experience with trying to do this with my plugin, I find the expectation that my block's edit function will contain a faithful reproduction of the server-side rendering to be unrealistic, considering:

  • The server-side rendering uses PHP filters, actions, methods, which would need to be rewritten in Javascript if the goal is to produce something client-side that is a realistic preview of what the user will see on the frontend.
  • The server-side rendering uses PHP templates in the plugin's directory, which can be overridden by other plugins or themes/child themes. Even if I go to all the effort of faithfully reproducing the exact same markup client-side as exists in the core plugin, the preview will be invalid as soon as a client overrides the server-side template. As noted by @westonruter in this comment, the source of truth for some blocks' rendering will always be the server-side renderer.
  • Not all of the dynamic data feeding the block is currently available in a REST API endpoint.

Currently, it seems like Gutenberg is forcing me to make a choice between:

  • Rewriting great swathes of PHP code as Javascript code (a violation of the DRY principle), while simultaneously adding REST API endpoints for every bit of dynamic data I need in my blocks. The sheer amount of work involved makes this a huge deterrent, and I would suggest the uptake of Gutenberg blocks amongst plugin developers like me would be significantly slower.
  • Not providing a block preview, instead opting for some generic placeholder image or something like that. This is hardly ideal, but considering the alternative, it's probably what I will end up doing for now.

If the proposal in this issue is implemented, it would give me a third choice:

  • Leverage ServerSideRender to render a block preview.

Given something like this already exists for embeds, I don't understand why something similar cannot exist to provide for a broader context of needs.

@westonruter
Copy link
Member

@ericnicolaas I strongly agree (not surprisingly). I love the idea of a ServerSideRender component.

This component would make it straightforward to implement widget blocks for Calendar (#1462), Recent Comments (#1792), Tag Cloud (#1801), and so on.

Note that this is conceptually similar to what is being worked on for Shortcode previews in #1054.

@ericnicolaas
Copy link

Thanks @westonruter. I've been watching #4710 closely, which specifically handles the Shortcode previews. While that will work for a bunch of my use-cases, not all the places where I'd like to use this are currently a shortcode. So a more general-purpose component would be ideal.

@westonruter
Copy link
Member

@ericnicolaas yes, I agree. I just meant that the implementation of the shortcode preview endpoint should look similar to the server-side-rendering endpoint.

@Lewiscowles1986
Copy link
Contributor

any way I can help with this?

@miina
Copy link
Contributor

miina commented Mar 12, 2018

FI: I will start looking into and working on the SSR endpoint / component.

@Lewiscowles1986
Copy link
Contributor

@miina check out #4710 & https://github.com/Lewiscowles1986/gutenberg/tree/new-shoes/

I'd like to get something similar for latest / recent posts keeping PHP WP functionality rather than the new Gutenberg JS/React frontend functionality.

@miina
Copy link
Contributor

miina commented Mar 14, 2018

Initial PR: #5602

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Block API API that allows to express the block paradigm. Framework Issues related to broader framework topics, especially as it relates to javascript [Type] Question Questions about the design or development of the editor.
Projects
None yet
Development

No branches or pull requests

10 participants