title: How to properly render partial views, and load JavaScript files in AJAX using Express/Jade?
body: <p><strong>Summary</strong></p>
  
  <p>I am using Express + Jade for my web application, and I'm struggling with rendering partial views for my AJAX navigation.</p>
  
  <p>I kind of have two different questions, but they are totally linked, so I included them in the same post.
  I guess it will be a long post, but I guarantee it's interesting if you have already struggled with the same issues. I'd appreciate it very much if someone took the time to read &amp; propose a solution.</p>
  
  <p><strong>TL;DR : 2 questions</strong></p>
  
  <ul>
  <li>What's the <strong>cleanest</strong> and <strong>fastest</strong> way to render fragments of views for an AJAX navigation with Express + Jade ?</li>
  <li>How should JavaScript files relative to each view be loaded ? </li>
  </ul>
  
  <p><strong>Requirements</strong></p>
  
  <ul>
  <li>My Web App needs to be compatible with users who have disabled<br>
  JavaScript </li>
  <li>If JavaScript is enabled, only the page's own content (and    not the
  whole layout) should be sent from the server to the client</li>
  <li>The app needs to be fast, and load as few bytes as possible</li>
  </ul>
  
  <hr>
  
  <h1> Problem #1 : what I've tried</h1>
  
  <h2>Solution 1 : having different files for AJAX & non-AJAX requests</h2>
  
  <p>My <strong>layout.jade</strong> is : </p>
  
  <pre><code>doctype html
      html(lang="fr")
          head
              // Shared CSS files go here
              link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
          body
              div#main_content
                  block content
              // Shared JS files go here
              script(src="js/jquery.min.js")
  </code></pre>
  
  <p>My <strong>page_full.jade</strong> is :   </p>
  
  <pre><code>extends layout.jade
  
  block content
      h1 Hey Welcome !
  </code></pre>
  
  <p>My <strong>page_ajax</strong> is :</p>
  
  <pre><code>h1 Hey Welcome
  </code></pre>
  
  <p>And finally in <strong>router.js</strong> (Express) :</p>
  
  <pre><code>app.get("/page",function(req,res,next){
     if (req.xhr) res.render("page_ajax.jade");
     else res.render("page_full.jade");
  });
  </code></pre>
  
  <p><strong>Drawbacks</strong> :</p>
  
  <ul>
  <li>As you probably guessed, I have to edit my views twice every time I
  need to change something. Quite frustrating.</li>
  </ul>
  
  <hr>
  
  <h2>Solution 2 : same technique with `include`</h2>
  
  <p>My <strong>layout.jade</strong> remains unchanged :</p>
  
  <pre><code>doctype html
      html(lang="fr")
          head
              // Shared CSS files go here
              link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
          body
              div#main_content
                  block content
              // Shared JS files go here
              script(src="js/jquery.min.js")
  </code></pre>
  
  <p>My <strong>page_full.jade</strong> is now :</p>
  
  <pre><code>extends layout.jade
  
  block content
     include page.jade
  </code></pre>
  
  <p>My <strong>page.jade</strong> contains the actual content without any layout/block/extend/include :</p>
  
  <pre><code>h1 Hey Welcome
  </code></pre>
  
  <p>And I have now in <strong>router.js</strong> (Express) : </p>
  
  <pre><code>app.get("/page",function(req,res,next){
     if (req.xhr) res.render("page.jade");
     else res.render("page_full.jade");
  });
  </code></pre>
  
  <p><strong>Advantages</strong> :</p>
  
  <ul>
  <li>Now my content is only defined once, that's better.</li>
  </ul>
  
  <p><strong>Drawbacks</strong> :</p>
  
  <ul>
  <li>I still need <em>two</em> files for <em>one</em> page.</li>
  <li>I have to use the same technique in Express on <strong>every</strong> route. I
  just moved my code repetition problem from Jade to Express. Snap.</li>
  </ul>
  
  <hr>
  
  <h2>Solution 3 : same as Solution 2 but fixing the code repetition problem.</h2>
  
  <p>Using <a href="http://codetunnel.com/how-to-toggle-jade-layout-in-express-for-nodejs/" rel="noreferrer">Alex Ford's technique</a>, I could define my own <code>render</code> function in <strong>middleware.js</strong> :</p>
  
  <pre><code>app.use(function (req, res, next) {  
      res.renderView = function (viewName, opts) {
          res.render(viewName + req.xhr ? null : '_full', opts);
          next();
      };
   });
  </code></pre>
  
  <p>And then change <strong>router.js</strong> (Express) to :</p>
  
  <pre><code>app.get("/page",function(req,res,next){
      res.renderView("/page");
  });
  </code></pre>
  
  <p>leaving the other files unchanged.</p>
  
  <p><strong>Advantages</strong></p>
  
  <ul>
  <li>It solved the code repetition problem</li>
  </ul>
  
  <p><strong>Drawbacks</strong></p>
  
  <ul>
  <li>I still need <em>two</em> files for <em>one</em> page.</li>
  <li>Defining my own <code>renderView</code> method feels a litle dirty. After all, I
  expect my template engine/framework to handle this for me.</li>
  </ul>
  
  <hr>
  
  <h2>Solution 4 : Moving the logic to Jade</h2>
  
  <p>I don't like using <em>two</em> files for <em>one</em> page, so what if I let Jade decide what to render instead of Express ? At first sight, it seems very uncomfortable to me, because I think the template engine should <strong>not</strong> handle any logic at all. But let's try.</p>
  
  <p>First, I need to pass a variable to Jade that will tell it what kind of request it is :</p>
  
  <p>In <strong>middleware.js</strong> (Express)</p>
  
  <pre><code>app.use(function (req, res, next) {  
      res.locals.xhr = req.xhr;
   });
  </code></pre>
  
  <p>So now my <strong>layout.jade</strong> would be the same as before :</p>
  
  <pre><code>doctype html
      html(lang="fr")
          head
              // Shared CSS files go here
              link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
          body
              div#main_content
                  block content
              // Shared JS files go here
              script(src="js/jquery.min.js")
  </code></pre>
  
  <p>And my <strong>page.jade</strong> would be :</p>
  
  <pre><code>if (!locals.xhr)
      extends layout.jade
  
  block content
     h1 Hey Welcome !
  </code></pre>
  
  <p>Great huh ? Except that won't work because <em>conditional extends</em> are impossible in Jade. So I could move the test from <strong>page.jade</strong> to <strong>layout.jade</strong> :</p>
  
  <pre><code>if (!locals.xhr)
      doctype html
         html(lang="fr")
             head
                 // Shared CSS files go here
                 link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
             body
                 div#main_content
                      block content
                  // Shared JS files go here
                  script(src="js/jquery.min.js")
   else
       block content
  </code></pre>
  
  <p>and <strong>page.jade</strong> would return to :</p>
  
  <pre><code>extends layout.jade
  
  block content
     h1 Hey Welcome !
  </code></pre>
  
  <p><strong>Advantages</strong> :</p>
  
  <ul>
  <li>Now, I have only one file per page</li>
  <li>I don't have to repeat the <code>req.xhr</code> test in every route or in every
  view</li>
  </ul>
  
  <p><strong>Disadvantages</strong> :</p>
  
  <ul>
  <li>There is logic in my template. Not good</li>
  </ul>
  
  <hr>
  
  <h2>Summary</h2>
  
  <p><strong>These are all techniques I thought of and tried, but none of them really convinced me. Am I doing something wrong ? Are there cleaner techniques ? Or should I use another template engine/framework ?</strong></p>
  
  <hr>
  
  <h1>Problem #2</h1>
  
  <p><strong>What happens (with any of these solutions) if a view has its own JavaScript files ?</strong></p>
  
  <p>For example, using solution #4, if I have two pages, <strong>page_a.jade</strong> and <strong>page_b.jade</strong> which both have their own client-side JavaScript files <strong>js/page_a.js</strong> and <strong>js/page_b.js</strong>, what happens to them when the pages are loaded in AJAX ?</p>
  
  <p>First, I need to define an <code>extraJS</code> block in <strong>layout.jade</strong> :</p>
  
  <pre><code>if (!locals.xhr)
      doctype html
         html(lang="fr")
             head
                 // Shared CSS files go here
                 link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
             body
                 div#main_content
                      block content
                  // Shared JS files go here
                  script(src="js/jquery.min.js")
                  // Specific JS files go there
                  block extraJS
   else
       block content
       // Specific JS files go there
       block extraJS
  </code></pre>
  
  <p>and then <strong>page_a.jade</strong> would be :</p>
  
  <pre><code>extends layout.jade
  
  block content
     h1 Hey Welcome !
  block extraJS
     script(src="js/page_a.js")
  </code></pre>
  
  <p>If I typed <code>localhost/page_a</code> in my URL bar <em>(non-AJAX request)</em>, I would get a compiled version of :</p>
  
  <pre><code>doctype html
         html(lang="fr")
             head
                 link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
              body
                 div#main_content
                    h1 Hey Welcome A !
                 script(src="js/jquery.min.js")
                 script(src="js/page_a.js")
  </code></pre>
  
  <p>That looks good. But what would happen if I now went to <code>page_b</code> using my <em>AJAX navigation</em> ? My page would be a compiled version of :</p>
  
  <pre><code>doctype html
         html(lang="fr")
             head
                 link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
             body
                 div#main_content
                    h1 Hey Welcome B !
                    script(src="js/page_b.js")
                 script(src="js/jquery.min.js")
                 script(src="js/page_a.js")
  </code></pre>
  
  <p><strong>js/page_a.js</strong> and <strong>js/page_b.js</strong> are both loaded on the same page. What happens if there's a conflict (same variable name etc...) ? 
  Plus, if I go back to <strong>localhost/page_a</strong> using AJAX, I would have this :</p>
  
  <pre><code>doctype html
         html(lang="fr")
             head
                 link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
             body
                 div#main_content
                    h1 Hey Welcome B !
                    script(src="js/page_a.js")
                 script(src="js/jquery.min.js")
                 script(src="js/page_a.js")
  </code></pre>
  
  <p>The same JavaScript file (<strong>page_a.js</strong>) is loaded twice on the same page ! Will it cause conflicts, double firing of each event ? 
  Whether or not that's the case, I don't think it's clean code.</p>
  
  <p>So you might say that specific JS files should be in my <code>block content</code> so that they're removed when I go to another page. Thus, my <strong>layout.jade</strong> should be : </p>
  
  <pre><code>if (!locals.xhr)
      doctype html
         html(lang="fr")
             head
                 // Shared CSS files go here
                 link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
             body
                 div#main_content
                      block content
                      block extraJS
                  // Shared JS files go here
                  script(src="js/jquery.min.js")
   else
       block content
       // Specific JS files go there
       block extraJS
  </code></pre>
  
  <p>Right ? Err....If I go to <code>localhost/page_a</code>, I will get a compiled version of : </p>
  
  <pre><code>doctype html
         html(lang="fr")
             head
                 link(type="text/css",rel="stylesheet",href="css/bootstrap.min.css")
              body
                 div#main_content
                    h1 Hey Welcome A !
                    script(src="js/page_a.js")
                 script(src="js/jquery.min.js")
  </code></pre>
  
  <p>As you might have noticed, <strong>js/page_a.js</strong> is actually loaded <em>before</em> jQuery, so it won't work, because jQuery is not defined yet...
  So I don't know <strong>what to do for this problem</strong>. I thought of handling script requests client-side, using (for example) <code>jQuery.getScript()</code>, but the client would have to know the scripts' filename, see if they're already loaded, maybe remove them. I don't think it should be done client-side.</p>
  
  <p><strong>How should I do handle JavaScript files loaded via AJAX ? Server-side using a different strategy/template engine ? Client-side ?</strong></p>
  
  <p>If you've made it this far, you're a true hero, and I'm grateful, but I would be even more grateful if you could give me some advice :)</p>