Make WordPress WP-API faster by not loading theme and plugins

前端 未结 4 550
广开言路
广开言路 2021-02-04 19:14

I would like to make requests to the WordPress API much faster. My API is implemented in a plugin (using register_rest_route to register my routes). However, since this is a plu

4条回答
  •  春和景丽
    2021-02-04 19:40

    I think you might be focusing on the wrong issue.

    Loading php files is not nearly as slow as reading from your db and this is likely to be your 500ms load time. You should actually look at reducing this anyway (cache wp-options, etc), but what i suggest to you in relation to the api, is to cache the output using a mu-plugin. Using exit we can load output from file and serve that instantly.

    Our Method: 1. Create a folder called mu-plugins in the wp-content folder (may already be there)

    1. create a file called api-cache.php

    2. enter this code into your file:

      function get_api_cache(){
      
          //dont run if we are calling to cache the file (see later in the code)
          if( isset($_GET['cachecall']) && $_GET['cachecall'] === true)
              return;
      
          $url = "$_SERVER[REQUEST_URI]";
      
          //do a little error checking
      
          $uri= explode('/',$url);
      
          //we have a array (1st key is blank)
          if( $uri[1] !== 'wp-json' || $uri[2] !== 'wp' || $uri[3] !== 'v2'){
              return;
          } 
      
          //lock down the possible endpoints we dont want idiots playing with this...
          $allowed_endpoints= array(
              'posts'
          );
      
          $endpoint= array_pop($uri); // not sure if this is valid or not, is there more structure to some api calls?
      
          if( !in_array( $endpoint, $allowed_endpoints) ){
              return;
          } 
      
          //ok reasonably confident its a api call...
      
          $cache_folder= get_stylesheet_directory().'/api_cache/';
      
          // prob best if not within php server but to get you going
          if(! file_exists ( $cache_folder ) ){
              mkdir($cache_folder); //warning 777!!
          }
      
      
          /*
          * Need to choose a method of control for your cached json files
          * you could clear out the folder on update post/ taxonomies etc
          * or cron clear out hourly/weekly whatever freq you want
          */
      
      
          if( file_exists($cache_folder.$endpoint.'.json') ){
              $json= file_get_contents($cache_folder.$endpoint.'.json');
              header('Content-Type: application/json');
              echo $json;
              exit;// we need nothing else from php exit 
          } else {
              //make sure there will be no errors etc..
              $ch = curl_init();
              $url= "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]?cachecall=true";
              $timeout= 5;
              curl_setopt($ch, CURLOPT_URL, $url);
              curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
              curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
              $json = curl_exec($ch);
              curl_close($ch);
              file_put_contents($cache_folder.$endpoint.'.json', $json);  
          }
      
      }
      
      get_api_cache();    
      

    Now you should notice a significant difference on your load time on the 2nd load (this first time it is caching the output).

    A few disclaimers:

    1. you should read the comments in the code
    2. You need curl
    3. You need to be aware the cache folder is 777, I would strongly suggest you move this away from your theme folder and preferably outside your http accessible files.
    4. There were no catch all hooks to capture the data to be cached, hence i used curl to grab the content, this may change in the future and a hook/filter would improve the process time a bit when creating the cache file.
    5. I have not included a method to update cache files. You need to decide on how often you want to update, a site that gets lots of posts per day and a lot of visits, you might do a cron job to just delete the files (e.g. 3 times a day, hourly, every 10 minutes, etc-- what is a reasonable tradeoff in update time?) or add a hook to save post to only update when your posts change, etc..
    6. add your endpoints to the array for them (you can remove the if statement to allow all endpoints, but then you may have a situation where 404s are being cached!)

提交回复
热议问题