Varnish, a web application accelerator, is pretty good at serving static files, making it a decent candidate for blogs, news portals, etc. When it comes to session based applications, however, developers need to work harder to make it play nice with the app. Varnish excels at serving static content because the "http request" sent by the user never hits the server; instead, the response is generated from a cached object served straight from memory. This approach yields impressive results, as the load time is only bound by the speed at which the data passes back and forth through the wire. The issues begin to spawn as soon as the layout starts to reflect dynamic bits of information that cannot be shared among users, like a shopping cart, for example. In such a scenario, Varnish cannot rely on the cache alone, and instead, must hit the back-end to pull the personalized content. There are several approaches to embedding dynamic content in a page, the most popular and official one at the moment is Edge Side Includes or ESI for short. ESI works by replacing the esi-include tags embedded in the page with subsequent child requests, which are fired at the server level. The response of all these requests are ultimately merged together into one final response that gets sent back. Sadly, while it is an innovative approach, there's hardly any solid Magento module out there implementing this to its full extent. Only a few proof of concepts are found scattered on the net. Currently, the best Varnish module is Page Cache by Phoenix Media, given its official approval stamp by Varnish software. At the current time of writing, it does not contain any support for ESI, although the official documentation advertises that support is under development. Today, I will give you a few tips to implement ESI support yourself, in case you grow tired of waiting for an official solution.
- As mentioned earlier, ESI tags can be embedded in any template with the special syntax: <esi:include src="<?php echo $this->getUrl('esi/index/cart'); ?>"/>
- To instruct Varnish to parse them, you need to set: do_esi to true in the vcl_fetch subroutine: set beresp.do_esi = true;
- For a smoother development experience, it is probably good to replace these with normal function calls for when Varnish is not available: <esi:remove> ... </esi:remove>. For this you can use the special Surrogate http header in vcl_recv: set req.http.Surrogate-Capability = "abc=ESI/1.0"; you set it in Varnish to instruct the application that a reverse proxy is in place, and it should act accordingly. Then, in Magento, you can parse this header and dump the ESI tags.
- Now for the actual subrequests, a good strategy is to create a new module, and store all your ESI logic in there. Feel free to namespace the subrequests with /esi in the routes like so, then create a controller, and in that controller, pull and render the snippets that you're interested in displaying. You might want to send etags to take advantage of the Not-Modified http header to save bandwidth. When testing this approach, I noticed only a small speed boost, and it's pretty hard to speed things up once a script needs to hit PHP and boot the Magento front controller.