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.
Get Node for Front-End Developers now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.