Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Let the application do the work, not the VCL

Thijs Feryn
December 03, 2015

Let the application do the work, not the VCL

My talk at the 10th Varnish User Group Meeting in Rotterdam.

Thijs Feryn

December 03, 2015
Tweet

More Decks by Thijs Feryn

Other Decks in Technology

Transcript

  1. Expires: Thu, 31 Dec 2015 23:59:59 GMT Cache-Control: s-maxage=86400 Cache-Control:

    s-maxage=3600 Cache-Control: no-cache, no-store, s-maxage=0
  2. <!DOCTYPE html> <html> <head> <title>The Demo</title> <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link rel="stylesheet" href="/css/bootstrap.min.css"> <link rel="stylesheet" href="/css/bootstrap-theme.min.css"> <script src="/js/jquery-2.1.4.min.js"></script> <script src="/js/bootstrap.min.js"></script> </head> <body> <nav class="navbar navbar-inverse navbar-fixed-top"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="#">Project name</a> </div> <div id="navbar" class="navbar-collapse collapse"> <form class="navbar-form navbar-right"> <div class="form-group"> <input type="text" placeholder="Email" class="form-control"> </div> <div class="form-group"> <input type="password" placeholder="Password" class="form-control"> </div> <button type="submit" class="btn btn-success">Sign in</button> </form> </div> </div> </nav> <div class="jumbotron"> <div class="container"> <h1>Hello, world!</h1> <p>This is a template for a simple marketing or informational website. It includes a large callout called a jumbotron and three supporting pieces of content. Use it as a starting point to create something more unique.</p> <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more &raquo;</a></p> </div> </div>
  3. <!DOCTYPE html> <html> <head> <title>The Demo</title> <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link rel="stylesheet" href="/css/bootstrap.min.css"> <link rel="stylesheet" href="/css/bootstrap-theme.min.css"> <script src=“/js/jquery-2.1.4.min.js"></script> <script src="/js/bootstrap.min.js"></script> </head> <body> <nav class="navbar navbar-inverse navbar-fixed-top"> {{ render_esi(url('nav')) }} </nav> <div class="jumbotron"> {{ render_esi(url('jumbotron')) }} </div> <div class="container"> {% block content %}{% endblock %} <hr> <footer> {{ render_esi(url('footer')) }} </footer> </div> </body> </html>
  4. <!DOCTYPE html> <html> <head> <title>The Demo</title> <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link rel="stylesheet" href="/css/bootstrap.min.css"> <link rel="stylesheet" href="/css/bootstrap-theme.min.css"> <script src=“/js/jquery-2.1.4.min.js"></script> <script src="/js/bootstrap.min.js"></script> </head> <body> <nav class="navbar navbar-inverse navbar-fixed-top"> {{ render_esi(url('nav')) }} </nav> <div class="jumbotron"> {{ render_esi(url('jumbotron')) }} </div> <div class="container"> {% block content %}{% endblock %} <hr> <footer> {{ render_esi(url('footer')) }} </footer> </div> </body> </html> ESI tags
  5. <!DOCTYPE html> <html> <head> <title>The Demo</title> <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link rel="stylesheet" href="/css/bootstrap.min.css"> <link rel="stylesheet" href="/css/bootstrap-theme.min.css"> <script src=“/js/jquery-2.1.4.min.js"></script> <script src="/js/bootstrap.min.js"></script> </head> <body> <nav class="navbar navbar-inverse navbar-fixed-top"> <esi:include src="http://localhost:8888/nav" /> </nav> <div class="jumbotron"> <esi:include src="http://localhost:8888/jumbotron" /> </div> <div class="container"> {% block content %}{% endblock %} <hr> <footer> <esi:include src="http://localhost:8888/footer" /> </footer> </div> </body> </html> ESI tags
  6. <?php date_default_timezone_set('Europe/Brussels'); require_once __DIR__.'/../vendor/autoload.php'; use \Symfony\Component\HttpFoundation\Response; use \Silex\Provider; use \Silex\Application;

    $app = new Application(); $app->register(new TwigServiceProvider(), array( 'twig.path' => dirname(__DIR__).'/views', )); $app->register(new HttpFragmentServiceProvider()); $app->register(new UrlGeneratorServiceProvider()); $app->register(new SessionServiceProvider()); Init code
  7. Base controller $app->get('/', function () use ($app) { $response =

    new Response($app['twig']->render('index.twig')); $response->setSharedMaxAge(3600); return $response; })->bind('home');
  8. {% extends "layout.twig" %} {% block content %} <!-- Example

    row of columns --> <div class="row"> <div class="col-md-4"> <h2>Heading</h2> <p>Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui. </p> <p><a class="btn btn-default" href="#" role="button">View details &raquo;</ a></p> </div> <div class="col-md-4"> <h2>Heading</h2> <p>Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui. </p> <p><a class="btn btn-default" href="#" role="button">View details &raquo;</ a></p> </div> <div class="col-md-4"> <h2>Heading</h2> <p>Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.</p> <p><a class="btn btn-default" href="#" role="button">View details &raquo;</ a></p> </div> </div> {% endblock %}
  9. Navigation controller $app->get('/nav', function () use ($app) { //+ ADD

    MORE SESSION LOGIC $response = new Response($app['twig']->render('nav.twig')); $response->headers->addCacheControlDirective('no-cache',true); $response->headers->addCacheControlDirective('no-store',true); return $response; })->bind('nav');
  10. <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data- toggle="collapse"

    data-target="#navbar" aria-expanded="false" aria- controls="navbar"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="#">Project name</a> </div> <div id="navbar" class="navbar-collapse collapse"> <form class="navbar-form navbar-right"> <div class="form-group"> <input type="text" placeholder="Email" class="form- control"> </div> <div class="form-group"> <input type="password" placeholder="Password" class="form-control"> </div> <button type="submit" class="btn btn-success">Sign in</ button> </form> </div><!--/.navbar-collapse --> </div>
  11. Jumbotron controller $app->get('/jumbotron', function () use ($app) { $response =

    new Response($app['twig']->render('jumbotron.twig')); $response->setSharedMaxAge(86400); return $response; })->bind('jumbotron');
  12. <div class="container"> <h1>Hello, world!</h1> <p>This is a template for a

    simple marketing or informational website. It includes a large callout called a jumbotron and three supporting pieces of content. Use it as a starting point to create something more unique.</ p> <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more &raquo;</a></p> </div>
  13. Footer controller $app->get('/footer', function () use ($app) { $response =

    new Response($app[‘twig']->render('footer.twig')); $response->setPublic(); $response->setExpires( DateTime::createFromFormat( "m-d H:i:s",'12-31 23:59:59', new DateTimeZone('Europe/London') ) ); return $response; })->bind('footer');
  14. vcl 4.0; backend default { .host = "127.0.0.1"; .port =

    "8888"; } sub vcl_recv { set req.http.Surrogate-Capability = “key=ESI/1.0"; return(hash); } sub vcl_backend_response { if (beresp.http.Surrogate-Control ~ "ESI/1.0") { unset beresp.http.Surrogate-Control; set beresp.do_esi = true; } } Simplified VCL
  15. <?php date_default_timezone_set('Europe/Brussels'); require_once __DIR__.'/../vendor/autoload.php'; use \Symfony\Component\HttpFoundation\Response; use \Silex\Application; $app =

    new Application(); $app->register(new \Silex\Provider\TwigServiceProvider(), array( 'twig.path' => dirname(__DIR__).'/views', )); $app->register(new Silex\Provider\HttpFragmentServiceProvider()); $app->register(new Silex\Provider\UrlGeneratorServiceProvider()); $app->register(new Silex\Provider\SessionServiceProvider());
  16. CDN

  17. <?php date_default_timezone_set('Europe/Brussels'); require_once __DIR__.'/../vendor/autoload.php'; use \Symfony\Component\HttpFoundation\Response; use \Silex\Application; $app =

    new Application(); $app->register(new \Silex\Provider\TwigServiceProvider(), array( 'twig.path' => dirname(__DIR__).'/views', )); $app->register(new Silex\Provider \HttpCacheServiceProvider(), array( 'http_cache.cache_dir' => dirname(__DIR__).'/cache/', )); $app->register(new Silex\Provider\HttpFragmentServiceProvider()); $app->register(new Silex\Provider\UrlGeneratorServiceProvider()); $app->register(new Silex\Provider\SessionServiceProvider());