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

[question] How does Gatsby know about new content when using gatsby-source-wordpress? #2753

Closed
selrond opened this issue Nov 2, 2017 · 28 comments
Labels
type: question or discussion Issue discussing or asking a question about Gatsby

Comments

@selrond
Copy link
Contributor

selrond commented Nov 2, 2017

Do I have to manually regenerate the whole site? How does it work?

@KyleAMathews
Copy link
Contributor

Yeah — you'll need to trigger a new build when the WordPress content is updated.

I believe @sebastienfi has a wordpress plugin he's using with Netlify to automate this.

@selrond
Copy link
Contributor Author

selrond commented Nov 2, 2017

@KyleAMathews you mean sebastienfi/gatsby-wordpress-netlify-starter?

I've glanced into the source but don't see where he's automating it.

Is there something sensible that can be done so it runs automatically? Because in current form it's not very useful.

@KyleAMathews
Copy link
Contributor

He mentioned there's a wordpress plugin he uses that can fire a webhook when content is added or updated.

@garytokyo
Copy link

@selrond you can add the following to your functions.php file (or create a plugin)

add_action( 'save_post', 'fireFunctionOnSave' );
function fireFunctionOnSave($post_id)
{
  if(wp_is_post_revision( $post_id) || wp_is_post_autosave( $post_id )) {
    return;
  }
  // Send post request or whatever here
}

Hope that helps

@crgeary
Copy link
Contributor

crgeary commented Jan 5, 2018

You should be able to use HookPress too. This will allow you to define webhooks for particular actions/filters in WordPress.

Personally I prefer adding a button to the toolbar that says "publish/deploy" which triggers the webhook.

@selrond
Copy link
Contributor Author

selrond commented Jan 9, 2018

@garytokyo @crgeary good idea, but I still have to host my static site on a nodejs server in order to rebuild it there right?

@garytokyo
Copy link

@selrond not necessarily host it on a nodejs server - you would just have to have node and npm installed on your server (or a server). You could fire off a post request to a php script for instance that then triggers the gatsby build process (I'm pretty sure that is possible to run shell commands from PHP). I haven't set it up yet but I am also fairly sure you can use thirdparty services like DeployBot - set up a webhook that is triggered on wordpress save which runs your deploy commands.

@crgeary
Copy link
Contributor

crgeary commented Jan 9, 2018

@selrond If you're hosting your Gatsby site on Netlify (if not, you probably should cos it's awesome), then they include a CI environment that supports Node JS for builds & deployments. :)

@selrond
Copy link
Contributor Author

selrond commented Jan 9, 2018

@garytokyo right, either way though - you have to have some kind of a private server, instead of shared hosting (which is enough for WordPress alone). It makes it a bit pricier

@fk fk added the type: question or discussion Issue discussing or asking a question about Gatsby label Feb 8, 2018
@zetdotcom
Copy link

Hi guys, I know the topic is closed, but when I was looking at this it didn't provide me with the answer (maybe it's just me). I have done a little blog post on how to trigger Gatsby build on new Wordpress post.
However, the site needs to be hosted on Netlify (which I find awesome so why not use it).

gatsby-wordpress-netlify-auto-update.

Disclaimer: I am still a newbie so if there is anything wrong with the post let me know.

@bogdancss
Copy link
Contributor

bogdancss commented May 8, 2018

hey @zetdotcom - I tried following the example. I have a Netlify webhook ready and added this to the end of the functions.php file:

add_action( 'save_post', 'fireFunctionOnSave' );
function fireFunctionOnSave($post_id)
{
  if(wp_is_post_revision( $post_id) || wp_is_post_autosave( $post_id )) {
    return;
  }
    $curl = curl_init( 'https://api.netlify.com/build_hooks/123123123' );
    curl_setopt( $curl, CURLOPT_POST, true );
    curl_setopt( $curl, CURLOPT_RETURNTRANSFER, true );
    $response = curl_exec( $curl );
    curl_close( $curl );
}

After adding/deleting/updating a post, it does not trigger any builds - what am I missing?

Thanks

@zetdotcom
Copy link

Hi. Have you set up your deploy settings in Netlify? I.e. give your repository url, ,set build command as 'gatsby build', public directory 'public/', and production branch to 'master'.
Is build triggered when you push to your github repo?

@gapgag55
Copy link

gapgag55 commented May 9, 2018

@b0gd4n I finally solve this problem by using code below.

$response = Requests::post( NETLIFY_BUILD_HOOK );

Reference: https://deliciousbrains.com/php-curl-how-wordpress-makes-http-requests/

@gapgag55
Copy link

gapgag55 commented May 9, 2018

@zetdotcom Absolutely yes!!

@bogdancss
Copy link
Contributor

bogdancss commented May 9, 2018

@gapgag55 so replace

$response = curl_exec( $curl ); with $response = Requests::post( NETLIFY_BUILD_HOOK ); ?

@gapgag55
Copy link

gapgag55 commented May 9, 2018

@b0gd4n Do like this,

add_action( 'save_post', 'fireFunctionOnSave' );
function fireFunctionOnSave($post_id)
{
   if(wp_is_post_revision($post_id) || wp_is_post_autosave($post_id)) {
      return;
   }
   $response = Requests::post( NETLIFY_BUILD_HOOK_URL );
}

@bogdancss
Copy link
Contributor

@gapgag55 damn - that worked. Thank you!

@bogdancss
Copy link
Contributor

hey @gapgag55 - is there a way of not triggering a build when a user logs in? - the code above seems to trigger the hook as soon as I log in, as well as when I bin a draft post and if I save a draft of a post.

Would there be a way of only triggering the hook when you bin a published post, when you change a published post to un-published, and when you publish a post?

Thanks

@gapgag55
Copy link

gapgag55 commented May 18, 2018

@crgeary
Copy link
Contributor

crgeary commented May 22, 2018

I'll probably make a WordPress plugin for this in the near future. I'll make it work for anything that uses webhooks, but with extra bits specifically for Netlify (as they have an API I can access).

I was thinking..

  1. A "deploy" button that you can press to manually trigger a deployment.
  2. Hooking into the common CRUD events that WP fires for posts/pages & taxonomies.
  3. Pulling in Netlify deployment history via their API.
  4. Supporting custom actions/filters so you can hook in as you need to for custom stuff.

Does anyone want/need anything else? :)

@crgeary
Copy link
Contributor

crgeary commented Jun 2, 2018

TLDR... Here's a plugin I wrote to do it for you: crgeary/wp-jamstack-deployments.


@b0gd4n the save_post hook will fire anytime a post is changed. Whether that be an edit you've made, trashing a post, or even just clicking "new post" as this will create a draft for you.

Just to make things more annoying, WordPress uses posts for menus & menu items (among other things). Therefore saving menus will trigger a build per menu item + the menu itself. So basically a navigation menu with 10 items will fire 11 save_post hooks when you save it.

This is probably why that code runs when you login to the site. WordPress is probably saving some kind of a post in the background, which usually only happens when someone is actively using the site due to how WP-Cron works.


@b0gd4n & @zetdotcom I see you're using curl_* functions to make a request to Netlify. I would recommend you use wp_remote_post or wp_safe_remote_post to abstract away the possible complexities and let WordPress core handle it.


With this in mind, I've built a plugin that has a manual deploy button as part of the admin bar, and also automatically deploys whenever you change a post type (save_post hook), or when you change a term (created_term, delete_term, edit_term hooks). With the ability to extend this and add your own hooks programmatically.

I have some additional features to add, but the core work is done around triggering builds.

The future roadmap is to add better integration with Netlify, and decrease the number of requests made by deferring them. If you ran a script that updated 10 posts, currently it would fire 10 requests. However, I'd like to make it so that 10 updates happen, and then 1 request is made after the 10th. But this is a future todo.

For now, here is the plugin: crgeary/wp-jamstack-deployments

I'll look at getting this onto the WordPress repository, but for now (at least while it's BETA) it's going to be Github only.

@KyleAMathews
Copy link
Contributor

Due to the high volume of issues, we're closing out older ones without recent activity. Please open a new issue if you need help!

@dbismut
Copy link
Contributor

dbismut commented Sep 14, 2018

Hey, just for the sake of reference, if anyone gets here.

I've set up a basic prototype using the following stack.

Features

  • Wordpress as a headless CMS
  • Gatsby front-end
  • Both Wordpress and Gatsby run on separate dockers hosted on Digital Ocean
  • Both Wordpress and Gatsby are available under the same domain name (.tk)
  • Nginx redirects all /wp* routes to the docker running Wordpress
  • All other routes fall back to the docker running Gatsby
  • Cloudflare is also enabled
  • Live preview is available in Gatsby using Wordpress REST API which handles Cookie auth to make sure only authenticated admins can use it
  • Continuous integration (on Gatsby only for the moment) is managed through CircleCI that redeploys Gatsby's docker image to Digital Ocean
  • Publishing or updating an article on Wordpress triggers the Circle CI build (but skips tests) so that the Gatsby docker can be rebuilt with the latest content. I've not used @crgeary plugin but it should be manageable to integrate it.

What's missing

  • I've only worked with posts, but I think the same could be easily manageable with pages
  • Localisation is not enabled (again I think this is manageable)
  • I had to disable gatsby-offline-plugin as the service worker interfered with the Wordpress admin panel (I was trying to bypass the service worker for /wp* routes with no avail)
  • Would be cool if Wordpress could be notified when CircleCI finished deploying
  • Could be interesting to further secure Wordpress docker to prevent any unauthorized access

Total cost

  • Digital Ocean droplet: $5 / month
  • CircleCI: free for open source projects
  • .tk domain: free with https://www.freenom.com
  • Cloudflare: free for personal projects
  • SSL: free with Let's encrypt

Gatsby repo is available here. It's very simple, can probably be optimized. In Wordpress enabled theme functions.php, here is how I manage to enable live preview changes. I'm far from being a php / wordpress pro so this can also be optimized.

// functions.php
function preview_link_fix( $preview_link, $post ) {
  $id = $post->ID;

  $latest_revision_id = '';

  if($post->post_status !== 'draft') {
    $revisions = wp_get_post_revisions($id);
    $last_revision = array_shift($revisions);
    $latest_revision_id = $last_revision ? $last_revision->ID : '';
  }

  $nonce = wp_create_nonce( 'wp_rest' );

  $parsedUrl = parse_url( $preview_link );
  $path = $parsedUrl['path'];
  if ($path === '/') $path = "/preview";

  $scheme = $parsedUrl['scheme'];
  $host = $parsedUrl['host'];
  $query = $parsedUrl['query'];

  return "$scheme://$host$path?$query&revision_id=$latest_revision_id&_wpnonce=$nonce&status=$post->post_status";
}

add_filter( 'preview_post_link', 'preview_link_fix', 10, 2);

Happy to help.

@jimmysafe
Copy link

Hey, I have setup a docker with gatsby and wordpress but for some reason I would like to keep everything together and not use netlify to host my gatsby site.

What I would like to do is to host the whole app with wordpress, db and gatsby on Digital Ocean.

Is there a way to trigger the gatsby site build on wordpress update button click with this setup?

hopefully someone can help me with this, :)

@jonniebigodes
Copy link

@jimmysafe to the best of my knowledge, for the time being, when you use gatsby and probably gatsby-source-wordpress, basically it's a one way process, you fetch the data at build time. When you update wordpress, gatsby has no way to to know about the update. You might need to setup some webhooks to trigger a new deployment when content changes, for instance when you add a post/page.

@slaterbbx
Copy link

This might be something to mention, you can host on "Firebase Webhosting" for free, it also has cloud functions for the node backend, you can host there, do your backend on prismic.io ( also free and has graphql ) and prismic.io has webhooks available.

Now you can have everything hosting and scripted in JS for free 100% with all your needs filled.

You will not get to use wordpress headless, but really, prismic is 1000 times better and more efficient + its a CDN and its 100% freemium up to some crazy limits like firebase is.

@Koli14
Copy link

Koli14 commented Jan 20, 2020

I just find this project, seems promising:
https://github.com/staticfuse/create-gatsby-theme-publisher
They created a WP plugin, which handles automatic deployment, and they have a quite detaild doc+tutorial. ;)

@ozluy
Copy link

ozluy commented Mar 24, 2020

If you use Netlify,

on your Netlify account
go to Settings > Build & deploy > Build hooks > Add build hook

then you will have hook looks like this https://api.netlify.com/build_hooks/{uuid}

copy that and use it on Wordpress
go to WP Admin > Settings > Webhooks > Add webhook
paste your Netlify webhook by choosing one of publish_post, publish_page or comment_post.

It worked for me 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: question or discussion Issue discussing or asking a question about Gatsby
Projects
None yet
Development

No branches or pull requests