Adding views in Express/ejs - node.js

Basic question time:
I'm new to node.js/express/ejs.
How do I add a new ejs powered page to my server?
Example: I want to have a new page on my server that shows up as mysite.com/foo.html, and I want it to be rendered through app.router & ejs. How do I add this page and start to edit it?
I've started by working from the example of index.*js* that comes with the default express --ejs install. But digging into that code, 'find ./ -name "index.*js*"' comes up with no less than 25 different files that might be involved in producing that two-line index page.
Start me on the right path?

In your views directory add a file named foo.ejs and add the EJS you want to be rendered.
Then create another file named foo.js in the routes directory. Here is what the content
module.exports.index = function(req, res){
res.index('foo');
};
In the main express app file (the one you run via node app.js) first require the new route
var foo = require('./routes/foo');
then tell express about it
app.get('/foo.html', foo.index);

Related

Access Node Environment Variables in Jade file

I am trying to figure out how to optionally display text in a jade file based on the environment. I can't seem to figure out how to access the NODE_ENV variable in my jade file.
In my index.jade file I am doing:
if process.env.NODE_ENV === 'development'
h1 I am in development mode
else
h1 I am not in development mode
The problem is that process.env.NODE_env is undefined.
When I try and do: h1 #{process.env} outside of the if statement, Jade outputs [Object Object] onto the page.
When I try and do: h1 #{process.env.NODE_ENV} outside of the if statement, Jade does not output anything onto the page.
I am not rendering my Jade files on fly, rather I am building them all as "static" files whenever I start the server.
Anything you want to access in the jade template has to be in the locals object sent down from the server. For something like the process environment, you can do this right when you fire up your app:
const express = require('express');
var app = express();
app.locals.env = process.env; // though you might prefer to clone this instead of setting them equal
Then in your jade template you can do
#{env.NODE_ENV}
UPDATE
Adding for direct use, rather than in an express server.
const pug = require('pug');
// Compile the source code
const compiledFunction = pug.compileFile('template.pug');
// Render a set of data
console.log(compiledFunction(process.env));
That'll log it, but of course you could just as easily write that to an HTML file using fs utilities instead.

Express app.get() creates new virtual directory - I don't want that

I just changed my routing from query-strings to a kind of restful API.
Before:
http://www.server.de/?item=1234
After:
http://www.server.de/item/1234
I route these requests with Express as follows:
app.get('/item/:itemID', function(req, res){
var itemID = req.param('itemID');
res.sendfile(__dirname + '/public/application.html');
});
Every file, that application.html wants load (like styles, images, javascripts ...) is saved in a subdirectory assets/... After the routing-change, they are being searched in the "virtual" directory item/assets/... which of course returns 404 (until I change the paths in the .hmtl-file).
How can I route such URLs without changing the whole context of paths?
Edit:
Watch Tim Coopers comment. Redefining the paths in the .html-file as absolute did the trick.

How to do navigation durandal.js?

i am trying to use durandal.js for single page architecture,
i already have application where i am loading all pages in div = old approach for single page architecture,
what i want to do is when i click on page i need to open hotspa pages,
for now i write something like this . www.xyz.com#/details,
where # details is my durandal view page!
when i put <a> herf ....#/details, i got error like this :
http://postimg.org/image/hoeu1wiz5/
but when i refresh with same url, it is working fine, i am able to see view!
i do not know why i got this error
If you are using anything before version 2.0 of Durandal, you are getting this because in your Shell.js you are not defining router, or you have a bad definition of where the router module is, or possibly you are defining scripts in your index instead of 'requiring them' via require.js
1st - Check shell.js, at the top you should have a define function and it should say / do something like this, and should be exposing that to the view like so -
define(['durandal/plugins/router'], function (router) {
var shell = {
router: router
};
return shell;
};
2nd - Check and make sure the 'durandal/plugins/router' is point to the correct location in the solution explorer, in this case it is app > durandal > plugins > router. If it is not or if there is no router you can add it using nuget.
3rd - Make sure you aren't loading scripts up in your index or shell html pages. When using require.js you need to move any scripts you are loading into a require statement for everything to function properly. The 'Mismatched anonymous define() module' error usually occurs when you are loading them elsewhere - http://requirejs.org/docs/errors.html#mismatch

Unable to Change Favicon with Express.js

This is a really basic question, but I'm trying to change the favicon of my node.js/Express app with
app.use(express.favicon(__dirname + '/public/images/favicon.ico'));
and I'm still getting the default favicon. This is in my app.configure function, and yes, I've verified that there is a favicon.ico in the /public/images/favicon.ico.There's nothing about a favicon.ico in the console, either, which leads me to believe that this line of code is being ignored. Everything else in the function (setting port, setting views directory, setting template engine. etc.) seems to be working fine, so why would this line of code not be executing?
What I tried
Emptying browser cache
Restarting Terminal and running node app.js again
Adding { maxAge: 2592000000 }, as described here
Thanks in advance.
Update: I got it to work. See my answer below for more information.
I tried visiting the site in Safari for the first time (I normally use Chrome) and noticed that it was showing the correct favicon. I tried clearing my cache in Chrome again (twice) to no avail, but after more searching, I found that apparently favicons aren't stored in the cache. I "refreshed my favicon" using the method described here and it worked!
Here's the method (modified from the above link), in case the link goes dead:
Open Chrome/the problematic browser
Navigate to the favicon.ico file directly, e.g. http://localhost:3000/favicon.ico
Refresh the favicon.ico URL by pressing F5 or the appropriate browser Refresh (Reload) button
Close the browser and open your website - voila, your favicon has been updated!
What worked for me finally:
Look that the
app.use(express.favicon(__dirname + '/public/images/favicon.ico'));
is at the beginning of the app configuration function. I had it before at the end. As the Express doc says: 'The order of which middleware are "defined" using app.use() is very important, they are invoked sequentially, thus this defines middleware precedence.'
I didn't need to set any maxAge.
To test it:
Restart the server with node app.js
Clear the browser cache
Refresh the Favicon with directly accessing it by using "localhost:3000/your_path_to_the favicon/favicon.ico" and reloading
The above answer is no longer valid.
If you use
app.use(express.favicon(__dirname + '/public/images/favicon.ico'));
You'll get this error:
Error: Most middleware (like favicon) is no longer bundled with Express and must be installed separately
What you're going to need to do is get serve-favicon.
run
npm install serve-favicon --save
then add this to your app
var express = require('express');
var favicon = require('serve-favicon');
var app = express();
app.use(favicon(__dirname + '/public/images/favicon.ico'));
smiley favicon to prevent error:
var favicon = new Buffer('AAABAAEAEBAQAAAAAAAoAQAAFgAAACgAAAAQAAAAIAAAAAEABAAAAAAAgAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAA/4QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEREQAAAAAAEAAAEAAAAAEAAAABAAAAEAAAAAAQAAAQAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//wAA//8AAP//AAD8HwAA++8AAPf3AADv+wAA7/sAAP//AAD//wAA+98AAP//AAD//wAA//8AAP//AAD//wAA', 'base64');
app.get("/favicon.ico", function(req, res) {
res.statusCode = 200;
res.setHeader('Content-Length', favicon.length);
res.setHeader('Content-Type', 'image/x-icon');
res.setHeader("Cache-Control", "public, max-age=2592000"); // expiers after a month
res.setHeader("Expires", new Date(Date.now() + 2592000000).toUTCString());
res.end(favicon);
});
to change icon in code above
make an icon maybe here: http://www.favicon.cc/ or here :http://favicon-generator.org
convert it to base64 maybe here: http://base64converter.com/
then replace the icon base 64 value
general information how to create a personalized fav icon
icons are made using photoshop or inkscape, maybe inkscape then photoshop for vibrance and color correction (in image->adjustments menu).
for quick icon goto http://www.clker.com/ and pick some Vector Clip Arts, and download as svg.
then bring it to inkscape and change colors or delete parts, maybe add something from another vector clipart image, then to export select the parts to export and click file>export, pick size like 16x16 for favicon or 32x32, for further edit 128x128 or 256x256. ico package can have several icon sizes inside. it can have along with 16x16 pixel fav icon a high quality icons for link for the website.
then maybe enhance the imaage in photoshop. like vibrance bivel round mask , anything.
then upload this image to one of the websites that generate favicons.
there are also programs for windows for editing icons(search like "windows icon editor opensource", figure our how to create two images of different size inside a single icon).
to add the favicon to website. just put the favicon.ico as a file in your root domain files folder. for example in nodejs in public folder that contans the static files. it doesn't have to be anything special like code above just a simple file.
What worked for me follows. Set express to serve your static resources as usual, for example
app.use(express.static('public'));
Put favicon inside your public folder; Then add a query string to you icon url, for example
<link rel="icon" type="image/x-icon" href="favicon.ico?v="+ Math.trunc(Math.random()*999)>
In this case, Chrome is the misbehaving Browser; IE. Firefox. Safari (all on Windows) worked fine, WITHOUT the above trick.
Simplest way I could come up with (valid only for local dev, of course) was to host the server on a different port
PORT=3001 npm run start
Have you tried clearing your browser's cache? Maybe the old favicon is still in the cache.
How to do this without express:
if (req.method == "GET") {
if (/favicon\.ico/.test(req.url)) {
fs.readFile("home/usr/path/favicon.ico", function(err, data) {
if (err) {
console.log(err);
} else {
res.setHeader("Content-Type","image/x-icon");
res.end(data);
}
});
}

Moving route logic out of app.js

I'm designing an app with node.js and Express, and I was wondering if it was possible to move certain routing logic out of the app.js file. For exapmle, my app.js currently contains:
app.get('/groups',routes.groups);
app.get('/',routes.index);
Is there a way to move this logic out of the app.js file, and only have something like:
app.get('/:url',routes.get);
app.post('/:url",routes.post);
such that all GET requests would be processed by routes.get and all POST requests processed with routes.post?
You could pass a regular expression as the route definition:
app.get(/.+/, someFunction);
This would match anything. However, if you simply want to move your route definitions outside of your main app.js file, it is much clearer to do something like this:
app.js
var app = require('express').createServer();
...
require('routes').addRoutes(app);
routes.js
exports.addRoutes = function(app) {
app.get('/groups', function(req, res) {
...
});
};
This way, you're still using Express' built-in routing, rather than re-rolling your own (as you'd have to do in your example).
FULL DISCLOSURE: I am the developer of the node module mentioned below.
There is a node module that does kind of what you're asking for (and will, eventually, do more). It offers automatic routing based on convention over configuration for express. The module name is honey-express, but is currently in alpha development and not yet available on NPM (but you can get it from the source at https://github.com/jaylach/honey-express.
A short example of how it works: (Please note that this coffeescript)
# Inside your testController.coffee file. Should live inside /app/controllers
honey = require 'honey-express'
TestController = new honey.Controller
index: ->
# #view() is a helper method to automatically render the view for the action you're executing.
# As long as a view (with an extension that matches your setup view engine) lives at /app/views/controller/actionName (without method, so index and not getIndex), it will be rendered.
#view()
postTest: (data) ->
# Do something with data
Now, inside your app.js file you just have to setup some simple configuration:
# in your app.configure callback...
honey.config 'app root', __dirname + '/app'
app.use honey.router()
Now anytime a request comes in, honey will automatically look for a controller with the specified route, and then look for a matching action.. for example -
/test will automatically route to the index/getIndex() method of
testController
/ will automatically route to the index/getIndex() method of the homeController (the default controller is home), if it exists
/test/test will automatically route to the postTest() method of testController if the http method is POST.
As I mentioned, the module is currently in it's alpha state but the automatic routing works wonderfully and has been tested on two different projects now :) But since it's in alpha development, the documentation is missing. Should you decide to go this route, you can look at the sample I have up on the github, look through the code, or reach out to me and I'd be happy to help :)
EDIT: I should also note that honey-express does require the latest (BETA) version of express as it uses features that are not present in 2.x of express.

Resources