O'Reilly logo

Node for Front-End Developers by Garann Means

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

Parsing Other File Types

If we wanted to dynamically generate CSS (maybe for use in a theme builder of some sort) or JavaScript (perhaps cherry-picking pieces of a more comprehensive JS library), all we have to do is change the file type we’re reading in. Because we read in the files as strings, it makes no difference if they’re something Node could technically try to execute. Here again, Node’s lack of out-of-the-box handling for common file types works to our advantage. Any file can be an application, a library, a template, or a static resource—it’s entirely up to us and how we treat it.

Let’s say that we do indeed have a site offering some kind of customizable client-side widget library. For example, assume we have a customizable CSS file using Mustache to populate user-defined values:

h1 { color: #{{main}}; }
h2 { color: #{{secondary}}; } 
input { border-style: {{border}}; border-radius: {{corners}}px; }

To provide our end users with CSS and JavaScript matching their site’s needs, we only really need to change our routing. We’ll assume the values we’re receiving are coming from a form post, and that the rest of our application file remains the same:

connect(
  connect.static(__dirname + "/public"),
  connect.bodyParser(),
  connect.router(function(app) {
    app.post("/theme", function(req, res) {
      var theme = {
        main: req.body.mainColor,
        secondary: req.body.secondaryColor,
        border: req.body.borderStyle,
        corners: req.body.borderRadius
      };
      // load and render the CSS template
      requirejs(["text!public/css/theme.css"], function(tmpl) {
        var css = mustache.to_html(tmpl, theme);
        res.writeHead(200, {
          "Content-Type": "text/css",
          "Content-Length": css.length
        });
        res.end(css);
      });
    };
    app.post("/builder", function(req, res) {
      var options = {
        shim: req.body.html5shim,
        flash: req.body.useFlash,
        sockets: req.body.useWebSockets,
        jsonp: req.body.useJsonp
      };
      // load and render the JS template
      requirejs(["text!public/js/builder.js"], function(tmpl) {
        var js = mustache.to_html(tmpl, options);
        res.writeHead(200, {
          "Content-Type": "application/javascript",
          "Content-Length": js.length
        });
        res.end(js);
      });
    };
  })
).listen(8000);

Since we don’t want our CSS or JavaScript composed into our parent template, we can skip the render function and recreate its functionality for both MIME types we’ll want to return. You can probably see how the logic to render and return a response could be abstracted out into a function of its own, but since our example application only handles these two scenarios, the less efficient code above will get the job done.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required