I'm trying to define some Node routes using Coffeescript in the following way:
My app.js file:
/**
* Module dependencies.
*/
require('coffee-script');
var express = require('express');
var http = require('http');
var path = require('path');
var app = express();
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
require('./routes')(app);
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
My routes.coffee file (located at the same level as app.'s):
routes = (app) ->
app.get '/login', (req,res) ->
res.render "views/login",
title: 'Login'
stylesheet: 'login'
module.exports = routes
My issue are:
1 when I try to run node app - I get:
module.js:340
throw err;
^
Error: Cannot find module './routes'
If I explicitly specify the .coffee suffix: require('./routes.coffee')(app); - I get:
routes = (app) ->
^
SyntaxError: Unexpected token >
What is the proper way of doing this, please?
In CoffeeScript 1.7, the line require('coffee-script') no longer allows you to require CoffeeScript files. Instead, you need to either:
require('coffee-script/register')
or
require('coffee-script').register()
See the documentation.
Related
New to Node.js.
I'm using the VS2015 Express 3 template. How can I write my routing to:
Have a page at "/"
Have a a catch all route that responds with the home page "/"
Doesn't interfere with JS and CSS files
I.e., I tried the following, but then the JS and CSS files in the public directory respond with 404 don't render or execute. I thought that the static files code would handle it, but it does not. It works until I add the block with "*".
var express = require('express');
var routes = require('./routes');
var http = require('http');
var path = require('path');
var app = express();
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(app.router);
app.use(require('stylus').middleware(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'public')));
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
app.get('/', routes.index);
app.get('*', function (req, res) {
res.send('/', 404);
});
http.createServer(app).listen(app.get('port'), function () {
console.log('Express server listening on port ' + app.get('port'));
});
The solution, as suggested by jfriend00, is to add the following line below app.get('/', routes.index):
app.use(routes.index);
I've been playing around with node using jetbrains webstorm IDE. Last night I was trying to setup nib and bootstrap-stylus. However I always get an error that nib or bootstrap cant be found in the import tags.
#import 'nib'
or
#import 'bootstrap'
however if i use
#import '../../node_modules/bootstrap-stylus/lib/bootstrap'
everything works as expected. I don't think this is the right way? there must be some way to tell stylus where to look for imports?
my app.js looks like this
/**
* Module dependencies.
*/
var express = require('express');
var routes = require('./routes');
var user = require('./routes/user');
var http = require('http');
var path = require('path');
var nib = require('nib');
var bootstrap = require('bootstrap-stylus');
var app = express();
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
function compile(str, path) {
return stylus(str)
.set('filename', path)
.set('compress', true)
.use(nib());
}
app.use(stylus.middleware({
src: path.join(__dirname, 'public')
, compile: compile
}));
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
app.get('/', routes.index);
app.get('/users', user.list);
http.createServer(app).listen(app.get('port'), function () {
console.log('Express server listening on port ' + app.get('port'));
});
Thanks!
It should be as simple as rewriting your compile() function as follows:
function compile(str, path) {
return stylus(str)
.set('filename', path)
.set('compress', true)
.use(nib())
.use(bootstrap()); // each plugin has to be loaded
}
More information about plugin usage and stylus can be found here: https://gist.github.com/jenius/8263065
And in the official documentation: http://learnboost.github.io/stylus/docs/js.html#usefn
Hi i am following peepcode nodejs screencast, now i have an issues of rendering the login form. My code are as follow:
app.js
/**
* Module dependencies.
*/
require('coffee-script');
var express = require('express')
, http = require('http')
, path = require('path');
var app = express();
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
require('./apps/authentication/routes');
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
and my i have a routes within authentication folder. The code as follow:
routes.coffee
routes = (app) ->
app.get '/login', (req,res) ->
res.render "views/login",
title: 'Login'
stylesheet: 'login'
module.exports = routes
The coffee script indentation all works fine, but i have an error when i navigate localhost:3000/login on browser. The error it display are Cannot GET /login. Where am i wrong?
In app.js, change this line:
require('./apps/authentication/routes');
to this:
require('./apps/authentication/routes')(app);
What is happening is that in routes.coffee, you're exporting a function that takes a single arg, 'app', and then sets up the route on your app object. You need to call it passing app as the argument.
I don't seem to get JSHTML to work as a template engine on Express.js in Node.js. When I install my Express.js application and a basic application is created for me, and I run it I get this error message:
500 TypeError: Property 'engine' of object #<View> is not a function
at View.render (/Users/blackbook/nodejs/ds/node_modules/express/lib/view.js:75:8)
at Function.app.render (/Users/blackbook/nodejs/ds/node_modules/express/lib/application.js:504:10)
at ServerResponse.res.render (/Users/blackbook/nodejs/ds/node_modules/express/lib/response.js:677:7)
at exports.index (/Users/blackbook/nodejs/ds/routes/index.js:7:7)
at callbacks (/Users/blackbook/nodejs/ds/node_modules/express/lib/router/index.js:165:11)
at param (/Users/blackbook/nodejs/ds/node_modules/express/lib/router/index.js:139:11)
at pass (/Users/blackbook/nodejs/ds/node_modules/express/lib/router/index.js:146:5)
at Router._dispatch (/Users/blackbook/nodejs/ds/node_modules/express/lib/router/index.js:173:5)
at Object.router (/Users/blackbook/nodejs/ds/node_modules/express/lib/router/index.js:33:10)
at next (/Users/blackbook/nodejs/ds/node_modules/express/node_modules/connect/lib/proto.js:190:15)
My app.js looks like this (it's what Express.js created for me):
/**
* Module dependencies.
*/
var express = require('express')
, routes = require('./routes')
, http = require('http')
, path = require('path');
var app = express();
app.configure(function(){
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jshtml');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
});
app.configure('development', function(){
app.use(express.errorHandler());
});
app.get('/', routes.index);
http.createServer(app).listen(app.get('port'), function(){
console.log("Express server listening on port " + app.get('port'));
});
I have this installation:
Node.js v.0.8.5
Express.js#3.0.0rc2
jshtml#0.2.3
JSHTML currently works with Express.js 2. There are plans on getting the engine to work with Express.js 3, but currently I am too busy with enjoying the summer! Expect a fix for this problem in the winter!
According to https://github.com/visionmedia/express/wiki/Migrating-from-2.x-to-3.x you can use app.engine for 2-x compatibility.
e.g.
var fs = require("fs");
var jshtml = require("jshtml");
app.engine("jshtml", function (path, options, fn) {
fs.readFile(path, 'utf8', function (err, str) {
if (err) return fn(err);
str = jshtml.compile(str,options)(options).toString();
fn(null, str);
});
});
consolidate.js is used as a bridge between many template engines and express. If your engine isn't supported checkout the source code. Most engines need like 15 lines of code to implement.
I have it working in my project and will probably issue a pull request soon but for now look at my comment in
https://github.com/elmerbulthuis/jshtml/issues/5
Try the following. It works for me, as like you.
Firstly, install jshtml-express via npm and then do the following.
var app = express();
**app.engine('jshtml', require('jshtml-express'));**
// All environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jshtml');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
I hope it will work for you as well.
I get this error:
500 Error: ENOENT, open 'C:\Users\Gilbert\WebstormProjects\games\views\layout.hbs
but my project has no reference to this file. when trying to render a simple test page with HBS, I used a pregenerated express app that created a layout.jshtml file but deleated this file.
app.js:
/**
* Module dependencies.
*/
var express = require('express')
, routes = require('./routes')
, http = require('http')
, path = require('path');
var app = express();
app.configure(function(){
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'hbs');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(require('less-middleware')({ src: __dirname + '/public' }));
app.use(express.static(path.join(__dirname, 'public')));
});
app.configure('development', function(){
app.use(express.errorHandler());
});
app.get('/', routes.index);
http.createServer(app).listen(app.get('port'), function(){
console.log("Express server listening on port " + app.get('port'));
});
routes/index.js:
/*
* GET home page.
*/
exports.index = function(req, res){
res.render('hi.hbs', { title: 'Express' });
};
views/hi.hbs:
<h1>IT WORKS</h1>
With HBS you must manually disable need for a layout with layout:false this should be done in the view options to make it app global.