I had set up compiling LESS on server side in Express, and it worked right in jade without putting less in layout.
my terminal:
if(err) throw err;
^
Error: ENOENT, open '/Users/lijung/Documents/Project/clubond/public/stylesheets/left_navigator.less'
app.js:
/**
* Module dependencies.
*/
var express = require('express')
, path = require('path')
, club = require('./routes/club')
, less = require('less')
, fs = require('fs');
var app = module.exports = express.createServer();
// Configuration
app.configure(function(){
var RedisStore = require('connect-redis')(express);
app.use(express.cookieParser());
app.use(express.session({ secret: "william", store: new RedisStore }));
app.use(express.logger());
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.set('view options', { layout: false });
app.use(express.static(path.join(__dirname, 'public')));
});
app.configure('development', function(){
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.configure('production', function(){
app.use(express.errorHandler());
});
// Routes
//index-in-layout
app.get('/club/:id', club.chkExist, club.getDataById, site.clubPage);
//compile less
app.get("*.less", function(req, res) {
var path = __dirname + req.url;
fs.readFile(path, "utf8", function(err, data) {
if(err) throw err;
less.render(data, function(err, css) {
if (err) throw err;
res.header("Content-type", "text/css");
res.send(css);
});
});
});
app.listen(3000);
console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);
I put my layout in views named index_in_layout:
!!! 5
html
head
title= title
script(src='/javascripts/jquery.min.js')
link(rel="stylesheet", href="/stylesheets/index.css")
link(rel="stylesheet",type='text/css', href="/public/stylesheets/left_navigator.less")
script(src='/javascripts/index_in.js')
block script
body
index.jade:
extends ./index_in_layout
block script
script(src='/javascripts/new_club.js')
script(src='/javascripts/new_bond.js')
script(src='/javascripts/new_event.js')
script(src='/javascripts/popup.js')
script(src='/javascripts/list_clubs.js')
script(src='/javascripts/list_bonds.js')
script(src='/javascripts/list_events.js')
link(rel='stylesheet', type='text/css', href='/public/stylesheets/test.less')
block body
Terminal keeps telling me Error: ENOENT that my left_navigator.less can't open. I put test.less and navigator.less in the same directory, it makes no sense.
LESS on server side driving me crazy. Can someone help me out please. Thanks
Unless I'm missing something, you really don't need to go through these heroics to get less working :-) Generally you just need to add one line to your app.configure call like this:
app.configure(function() {
app.set('views', __dirname + '/views');
...
app.use(express.compiler({ src: __dirname + '/public', enable: ['less'] }));
app.use(connect.static(__dirname + '/public'));
app.use(app.router);
});
If you do it this way, you don't need the special route for *.less files. You just request *.css with the same name in your public folder and it's automatically generated. I use master/child layouts with jade and LESS here if an example would help:
https://github.com/JustinBeckwith/ExpressStarter
Happy Coding!
Related
can't seem to figure out what the problem with my file structure might be. I'm using Aurelia as a front end and node for the server. I did a join that fixed some of the issues but now I'm getting this error:
Error: (SystemJS) Error: XHR error (404 Not Found) loading http://localhost:3000/src/main.js
Error loading http://localhost:3000/src/main.js
This is my server.js file:
var express = require('express'),
app = express(),
engines = require('consolidate'),
MongoClient = require('mongodb').MongoClient,
assert = require('assert'),
bodyParser = require('body-parser');
app.engine('html', engines.nunjucks);
app.set('view engine', 'html');
app.set('views', __dirname + '/views');
app.use(bodyParser.urlencoded({ useNewUrlParser: true }));
app.use('/scripts', express.static(require('path').join(__dirname, 'scripts')));
function errorHandler(err, req, res, next) {
console.log(err.message);
console.log(err.stack);
res.status(500).render('error_template', {err: err});
}
MongoClient.connect('mongodb://localhost:27017/', function(err, client) {
assert.equal(null, err);
console.log('MongoDB connected!')
var db = client.db('todos');
app.get('/', function(req, res) {
res.render('index', {});
});
app.use(errorHandler);
});
var server = app.listen(3000, function() {
var port = server.address().port;
console.log("Express server listening on port %s.", port);
});
app.use('/scripts', express.static(require('path').join(__dirname, 'scripts')));
This line of code takes a local folder and makes it available through the express server. You need to do the same thing for your src folder
either with:
app.use('/src', express.static(require('path').join(__dirname, 'src')));
or:
app.use(express.static(require('path').join(__dirname, 'src')));
the first parameter allows you to name the directory it will be served as, which is usually the same.
And even though I didn't include the require('path').join(__dirname,... in the comment, it's good practice to include it.
So I'm working on developing a Node/Express webapp for basic CRUD operations and I'm having a hard time implementing Handlebars within the project.
When I try to use handlebars none of my stylesheets from my .hbs (previously .html) pages are loading.
Here's the file tree:
Here is the error:
And here is an example of the script import statements from
index.hbs
<!-- Bootstrap -->
<link href="../vendors/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
And Finally here is the server.js file
var express = require('express'),
bodyParser = require('body-parser'),
path = require('path'),
mysql = require('mysql'),
dbconfig = require('./config/database'),
exphbs = require('express-handlebars');
var connection = mysql.createConnection(dbconfig.connection)
connection.query('USE ' + dbconfig.database);
var app = express();
//Body Parser Middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
//Set static path
//app.use(express.static(path.join(__dirname, 'public')));
//app.use(express.static(__dirname + '/public'));
//app.set('views', __dirname + '/views');
//app.use('/views', express.static(path.join(__dirname, '/views')));
app.engine('hbs', exphbs({defaultLayout: false}));
app.set('view engine', 'hbs');
app.set(express.static(__dirname + '/public'));
//app.use('/views/vendors', express.static(path.join(__dirname, '/views/vendors')));
//app.use(express.static(__dirname + '/public/vendors'));
app.get('/', function(req, res) {
res.render('index');
connection.query("SELECT * FROM Student", function(err, rows){
console.log(rows);
});
});
app.listen(80, function() {
console.log('we are live on 80');
});
I tried using various static paths from other things I found on SO but wasn't able to get any of them to work.
Any help would be greatly appreciated!!
Thanks!
Fixed my problem by adding the following line above my app.get('/'....
app.use("/vendors",express.static(__dirname + "/vendors"));
app.use("/build",express.static(__dirname + "/build"));
app.use("/images",express.static(__dirname + "/images"));
app.get('/', function(req, res) {
I think that can be possible that the problem is in the handlebars configuration, please look at a configuration like this:
app.engine('.hbs',exphbs({
defaultLayout:'layouts',
layoutsDir:path.join(app.get('views'),'layouts'),
partialsDir:path.join(app.get('views'),'partials'),
extname:'.hbs',
helpers: helpers
}));
app.set('view engine','hbs');
maybe in yours it would be:
app.engine('hbs', exphbs({defaultLayout: false, extname:'.hbs',}));
if you are usign app.set(express.static(__dirname + '/public'));
try to put in the public folder your styles for example the bootstrap folder, and then all you have to do is call it in this way:
<link href="/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
I've recently started learning Node.js and I am trying to set up an express install with less-middleware and want to use Bootstrap 3 less files. I've had a look around but can only find tutorials for Bootstrap 2.
This is my code so far:
/**
* Module dependencies.
*/
var express = require('express');
var routes = require('./routes');
var user = require('./routes/user');
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(express.cookieParser('your secret here'));
app.use(express.session());
app.use(app.router);
app.use(require('less-middleware')({
dest: __dirname + '/public/stylesheets',
src: __dirname + '/public/stylesheets/less',
prefix: '/stylesheets',
compress: true,
debug: true,
force: true
}));
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('/users', user.list);
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
When I run the server, I get the following:
GET / 200 190ms - 180b
source : /home/user/www/website.com/public/stylesheets/less/bootstrap.less
dest : /home/user/www/website.com/public/stylesheets/bootstrap.css
read : /home/user/www/website.com/public/stylesheets/less/bootstrap.less
render : /home/user/www/website.com/public/stylesheets/less/bootstrap.less
GET /stylesheets/bootstrap.css 200 565ms - 97.43kb
But the styles I have changed don't seem to take effect. Could someone tell me where I'm going wrong please?
Thanks
Used this instead from the less-middleware github page and it's working fine now.
var less = require('less-middleware');
app.configure(function(){
// ...
var bootstrapPath = path.join(__dirname, 'node_modules', 'bootstrap');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use('/img', express['static'](path.join(bootstrapPath, 'img')));
app.use(app.router);
app.use(less({
src : path.join(__dirname, 'public/stylesheets', 'less'),
paths : [path.join(bootstrapPath, 'less')],
dest : path.join(__dirname, 'public', 'stylesheets'),
prefix : '/stylesheets',
debug: true
}));
app.use(express['static'](path.join(__dirname, 'public')));
// ...
});
I got a little bit confused about my node.js application. As far as I thought, node.js runs in a single process. However if I start my application by invoking node app.jsand monitor it with htop, I can see 4 sub-processes running, where I'd expect only one to be.
app.js
var express = require('express'),
routes = require('./routes'),
objects = require('./objects'),
http = require('http'),
path = require('path'),
pinLayout = objects.pinlayout,
// utils
util = require('util'),
wiringPi = require('wiring-pi'),
winston = require('winston'),
async = require('async');
// Logger - winston
var log = new(winston.Logger)({
transports: [
new(winston.transports.Console)({
colorize: true,
timestamp: true
}),
new(winston.transports.File)({
filename: './log/app.log'
})
]
});
// WiringPi
wiringPi.setup('gpio');
var app = express();
// all environments
app.set('port', process.env.PORT || 3001);
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(require('less-middleware')({
src: __dirname + '/public',
force: true,
compress: true
}));
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
// 404 Page
app.use(function(req, res, next) {
res.render('404.jade', {
title: "404 - Page Not Found",
showFullNav: false,
status: 404,
url: req.url
});
});
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler({
dumpExceptions: true,
showStack: true
}));
}
Although your code runs in a single thread, node.js uses a thread pool (mostly) for file system operations. This is needed because there are no async APIs for fs.
For example, when you call file.readFile, you will go through Read(), which will call:
ASYNC_CALL(read, cb, fd, buf, len, pos);
read is the blocking unix read(2). This will run in a thread until it completes. These are the threads you are seeing.
I'm developing a site with Node.js + Express and using as view engine Hogan.js.
This is my file app.js:
/**
* Module dependencies.
*/
var express = require('express')
, routes = require('./routes')
, user = require('./routes/user')
, 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', 'hjs');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser('your secret here'));
app.use(express.session());
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);
app.get('/about', routes.about);
app.get('/users', user.list);
http.createServer(app).listen(app.get('port'), function(){
console.log("Express server listening on port " + app.get('port'));
});
The file /routes/index.js is:
/*
* GET pages.
*/
exports.index = function(req, res){
res.render(
'index',
{
title: 'Home Page',
author: 'Bruce Wayne'
}
);
};
exports.about = function(req, res){
res.render(
'about',
{
title: 'About Page',
author: 'Bruce Wayne'
}
);
};
In /views folder, there are:
|- part.hjs
|- index.hjs
|- cv.hjs
The file part.hjs is:
<h3>Hello {{ author }}</h3>
The file index.hjs is:
<h1>Title: {{ title }} </h1>
{{> part }}
Welcome to Gotham City.
And the file about.hjs is:
<h1>Title: {{ title }}</h1>
{{> part }}
I'm not Joker.
I've two questions:
How can I use properly the partials in my pages? (this code doesn't work)
Can I use the same "title" for two or more pages without repeat the values assignment in file /routes/index.js?
Best regards, Vi.
I've found a solution for the first question.
First of all, I removed hjs:
npm remove hjs
Then, I installed the package hogan-express:
npm install hogan-express
Furthermore, I edited app.js:
/**
* Module dependencies.
*/
var express = require('express')
, routes = require('./routes')
, user = require('./routes/user')
, http = require('http')
, path = require('path');
var app = express();
app.engine('html', require('hogan-express'));
app.enable('view cache');
app.configure(function(){
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'html');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser('your secret here'));
app.use(express.session());
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);
app.get('/users', user.list);
http.createServer(app).listen(app.get('port'), function(){
console.log("Express server listening on port " + app.get('port'));
});
And routes/index.js:
exports.index = function(req, res) {
res.locals = {
title: 'Title',
};
return res.render(
'index',
{
partials:
{
part: 'part',
}
}
);
};
Now, in /views there are index.html, part.html.
The file part.html contains:
<h1>{{ title }}</h1>
The file index.html contains:
{{> part}}
Hello world!
So, It works fine.
At least in Express 4+, partials just work out of the box. You can use express-generator (from npm) with --hogan or -H option.
After doing that, you need to add partials to the render method:
router.get('/', function(req, res, next) {
res.render('index',
{
title: 'My Site',
partials: {header: 'header'}
});
});
Then, in your template use {{ > xxx }}
<body>
{{> header }}
<h1>{{ title }}</h1>
<p>Welcome to {{ title }}</p>
</body>
NOTE: this has header.hjs in views
To use partials with express+hogan, just do the following:
app.get('/yourRoute', function(req, res){
res.render('yourPartial', function(err,html){
var partialHTML = html;
res.render('yourMainView', { myPartial: partialHTML }, function(err,html){
res.send(html);
});
});
}
And now, yourMainView.html:
<p>Something Something Something</p>
{{{partialHTML}}}
<p>Bla Bla Bla</p>
Notice the triple '{' instead of double as you usually do! That telling hogan (mustache) to parse this as HTML rather then a string!
That's it.
As for your partials question, if you use consolidate.js you can simply do:
res.render('index', {
partials: {
part : 'path/to/part'
}
});
This is a problem. Partial support is difficult to come by in Express 3.
Your best bet is:
https://github.com/visionmedia/consolidate.js
npm install consolidate
These patches take different approaches to adding partials for Hogan:
https://github.com/visionmedia/consolidate.js/pull/51
https://github.com/visionmedia/consolidate.js/pull/29
Unfortunately, the engine doesn't have a hook for filesystem based partials natively, so I think people are confused about how and where partials should be implemented. I ended up with LinkedIn's Dust.js implementation, since partial support was already there. Master actually has even better support, plus I submitted a patch yesterday for relative paths.
Josh
I would use mmm instead of hjs.
https://github.com/techhead/mmm
Disclaimer: I wrote the package.
Just replace all occurrences of hjs with mmm and partials will start working. There is a lot more information and an example at the link above.
As for your other question, if you want to share properties across multiple views, you have a couple of options.
When you call res.render(name, options), the options will actually be merged onto res.locals and app.locals before being passed to the rendering engine. Therefore to set an app-wide property, you can simply assign it to app.locals.
app.locals.title = "Default Title"; // Sets the default title for the application
This concept really applies to just about any Express 3 View Engine.
However, for mmm specifically, please see the section under Presentation Logic for more ways to bind values to a template or set of templates.