I prefer open-source software and have been a long-time advocate of OSS in general. Recently, I started liking WP Rocket plugin that offers some unique features. I already have a perfect Nginx configuration for WP Super Cache plugin (that I consider as the best full-cache plugin till date). Since, WP Rocket uses disk caching like WPSC, I wanted to quickly convert the existing configurations to fit WP Rocket. I did succeed in it and you can find it in my WordPress-Nginx repo. Here I explain how WP Rocket stores the cached content and how it could be integrated into Nginx.
We begin with the classic location block that looks like this…
<span class="hljs-comment"># version 1</span>
<span class="hljs-attribute">location</span> / {
<span class="hljs-attribute">try_files</span> <span class="hljs-variable">$uri</span> <span class="hljs-variable">$uri</span>/ /index.php<span class="hljs-variable">$is_args</span><span class="hljs-variable">$args</span>;
}
Our aim is to modify it to fit WP Rocket by the end of this little article.
Let’s start with the home page. The cache for the home page is stored at /wp-content/cache/wp-rocket/example.com/index.html
. We can easily find the value of example.com through the variable named $host in Nginx. The following code will search for the cached content before passing the request to the PHP.
<span class="hljs-comment"># version 2</span>
<span class="hljs-attribute">location</span> / {
<span class="hljs-attribute">try_files</span> <span class="hljs-string">"/wp-content/cache/wp-rocket/<span class="hljs-variable">$host</span>/index.html"</span> <span class="hljs-variable">$uri</span> <span class="hljs-variable">$uri</span>/ /index.php<span class="hljs-variable">$is_args</span><span class="hljs-variable">$args</span>;
}
It’s time to by-pass cache on particular scenarios, such as logged-in users. We need to use version #1 mentioned earlier for logged-in users and version #2 for others who can use cached content, if exists. So, how can we split the requests based on cookies (or any other similar factor)? There is no doubt that we need to use if
statement and we need to use two location block to match different kind of requests (logged-in users and non-logged-in users). The recommend solution is to use a non-standard HTTP status code and then divert the configuration based on a condition. Here’s the snippet taken directly from the official Nginx page…
<span class="hljs-attribute">location</span> / {
<span class="hljs-attribute">error_page</span> <span class="hljs-number">418</span> = <span class="hljs-variable">@other</span>;
<span class="hljs-attribute">recursive_error_pages</span> <span class="hljs-literal">on</span>;
<span class="hljs-attribute">if</span> (<span class="hljs-variable">$something</span>) {
<span class="hljs-attribute">return</span> <span class="hljs-number">418</span>;
}
<span class="hljs-comment"># some configuration</span>
...
}
<span class="hljs-attribute">location</span> <span class="hljs-variable">@other</span> {
<span class="hljs-comment"># some other configuration</span>
...
}
In the above code, if the condition $something
is false, then # some configuration
is executed. If the condition is true, then # some other configuration
is executed. Did you get it? I know it could take a while to grab in. When you are ready, let’s use the same technique to divert our requests based on the cookie for logged-in user…
<span class="hljs-comment"># version 3</span>
<span class="hljs-attribute">location</span> / {
<span class="hljs-attribute">error_page</span> <span class="hljs-number">418</span> = <span class="hljs-variable">@cachemiss</span>;
<span class="hljs-attribute">recursive_error_pages</span> <span class="hljs-literal">on</span>;
<span class="hljs-attribute">if</span> (<span class="hljs-variable">$http_cookie</span> <span class="hljs-regexp">~* "wordpress_logged_in_")</span> { <span class="hljs-attribute">return</span> <span class="hljs-number">418</span>; }
<span class="hljs-comment"># executed only for general visitors (who are not logged-in)</span>
<span class="hljs-attribute">try_files</span> <span class="hljs-string">"/wp-content/cache/wp-rocket/<span class="hljs-variable">$host</span>/index.html"</span> <span class="hljs-variable">$uri</span> <span class="hljs-variable">$uri</span>/ /index.php<span class="hljs-variable">$is_args</span><span class="hljs-variable">$args</span>;
}
<span class="hljs-attribute">location</span> <span class="hljs-variable">@cachemiss</span> {
<span class="hljs-comment"># executed only for logged-in users</span>
<span class="hljs-attribute">try_files</span> <span class="hljs-variable">$uri</span> <span class="hljs-variable">$uri</span>/ /index.php<span class="hljs-variable">$is_args</span><span class="hljs-variable">$args</span>;
}
Note: you may use any HTTP status code that isn’t used elsewhere.
Let’s add a couple of more cookie checks to bypass cache for commenters and password-protected posts…
<span class="hljs-comment"># version 4</span>
<span class="hljs-attribute">location</span> / {
<span class="hljs-attribute">error_page</span> <span class="hljs-number">418</span> = <span class="hljs-variable">@cachemiss</span>;
<span class="hljs-attribute">recursive_error_pages</span> <span class="hljs-literal">on</span>;
<span class="hljs-attribute">if</span> (<span class="hljs-variable">$http_cookie</span> <span class="hljs-regexp">~* "wordpress_logged_in_")</span> { <span class="hljs-attribute">return</span> <span class="hljs-number">418</span>; } <span class="hljs-comment"># logged-in users</span>
<span class="hljs-attribute">if</span> (<span class="hljs-variable">$http_cookie</span> <span class="hljs-regexp">~* "comment_author_")</span> { <span class="hljs-attribute">return</span> <span class="hljs-number">418</span>; } <span class="hljs-comment"># commenters</span>
<span class="hljs-attribute">if</span> (<span class="hljs-variable">$http_cookie</span> <span class="hljs-regexp">~* "wp_postpass_")</span> { <span class="hljs-attribute">return</span> <span class="hljs-number">418</span>; } <span class="hljs-comment"># password protected posts</span>
<span class="hljs-attribute">try_files</span> <span class="hljs-string">"/wp-content/cache/wp-rocket/<span class="hljs-variable">$host</span>/index.html"</span> <span class="hljs-variable">$uri</span> <span class="hljs-variable">$uri</span>/ /index.php<span class="hljs-variable">$is_args</span><span class="hljs-variable">$args</span>;
}
<span class="hljs-attribute">location</span> <span class="hljs-variable">@cachemiss</span> {
<span class="hljs-attribute">try_files</span> <span class="hljs-variable">$uri</span> <span class="hljs-variable">$uri</span>/ /index.php<span class="hljs-variable">$is_args</span><span class="hljs-variable">$args</span>;
}
Now, cookies are taken care. We also need to bypass the cache on the following conditions…
- For POST requests.
- For search requests (format: example.com/?s=search_query).
- To view pages by ID (format: example.com/?p=id_of_the_post)
- For AMP test requests (format: example.com/?amp=1)
- For previewing of posts while editing them (format: example.com/?preview=true).
When we add support for all the above, our config would become…
<span class="hljs-comment"># version 5</span>
<span class="hljs-attribute">location</span> / {
<span class="hljs-attribute">error_page</span> <span class="hljs-number">418</span> = <span class="hljs-variable">@cachemiss</span>;
<span class="hljs-attribute">recursive_error_pages</span> <span class="hljs-literal">on</span>;
<span class="hljs-attribute">if</span> (<span class="hljs-variable">$http_cookie</span> <span class="hljs-regexp">~* "wordpress_logged_in_")</span> { <span class="hljs-attribute">return</span> <span class="hljs-number">418</span>; }
<span class="hljs-attribute">if</span> (<span class="hljs-variable">$http_cookie</span> <span class="hljs-regexp">~* "comment_author_")</span> { <span class="hljs-attribute">return</span> <span class="hljs-number">418</span>; }
<span class="hljs-attribute">if</span> (<span class="hljs-variable">$http_cookie</span> <span class="hljs-regexp">~* "wp_postpass_")</span> { <span class="hljs-attribute">return</span> <span class="hljs-number">418</span>; }
<span class="hljs-comment"># bypass cache for common query strings</span>
<span class="hljs-attribute">if</span> (<span class="hljs-variable">$arg_s</span> != <span class="hljs-string">""</span>) { <span class="hljs-attribute">return</span> <span class="hljs-number">418</span>; } <span class="hljs-comment"># search query</span>
<span class="hljs-attribute">if</span> (<span class="hljs-variable">$arg_p</span> != <span class="hljs-string">""</span>) { <span class="hljs-attribute">return</span> <span class="hljs-number">418</span>; } <span class="hljs-comment"># request a post / page by ID</span>
<span class="hljs-attribute">if</span> (<span class="hljs-variable">$arg_amp</span> != <span class="hljs-string">""</span>) { <span class="hljs-attribute">return</span> <span class="hljs-number">418</span>; } <span class="hljs-comment"># amp test</span>
<span class="hljs-attribute">if</span> (<span class="hljs-variable">$arg_preview</span> = <span class="hljs-string">"true"</span>) { <span class="hljs-attribute">return</span> <span class="hljs-number">418</span>; } <span class="hljs-comment"># preview post / page</span>
<span class="hljs-attribute">try_files</span> <span class="hljs-string">"/wp-content/cache/wp-rocket/<span class="hljs-variable">$host</span>/index.html"</span> <span class="hljs-variable">$uri</span> <span class="hljs-variable">$uri</span>/ /index.php<span class="hljs-variable">$is_args</span><span class="hljs-variable">$args</span>;
}
<span class="hljs-attribute">location</span> <span class="hljs-variable">@cachemiss</span> {
<span class="hljs-attribute">try_files</span> <span class="hljs-variable">$uri</span> <span class="hljs-variable">$uri</span>/ /index.php<span class="hljs-variable">$is_args</span><span class="hljs-variable">$args</span>;
}
Well, now, we have a working configuration to server cached content from WP Rocket Plugin. There are lot more to it than what’s discussed above. For example, I’ve only talked about home page so far. Also, we need to add support for SSL. You can find the complete Nginx configuration for WP Rocket Plugin at my repo. If you need explanation for the entire configuration, please say so in the comment section below. If there is enough interest, I will add it later. Happy caching!