express + stylus + jade, nothing gets compiled - node.js

I cannot get this simple app.js to work: static files are served but jade and styl files are not compiled.
Here the __dirname ls:
damianomacbook:www damiano$ ls
app.jade app.js app.styl config.xml johnd.jpg
.jade and .styl files are served normally and plain.
Here what happens when curling css and html files (which the middlewares functions are supposed to generate on the fly):
damianomacbook:www damiano$ curl localhost:8080/app.css
curl: (52) Empty reply from server
damianomacbook:www damiano$ curl localhost:8080/app.html
Cannot GET /app.html
What's missing?
Guilty code:
var express = require('express');
var stylus = require('stylus');
var nib = require('nib');
var app = express();
function compile(str, path) {
return
stylus(str)
.set('filename', path)
.use(nib());
}
app.use(express.logger('dev'));
app.set('views', __dirname);
app.set('view engine', 'jade');
app.use(stylus.middleware({
src: __dirname,
compile: compile
}));
app.use(express.static(__dirname));
app.listen(8080);

Your GET /app.html is failing because serving HTML pages is done with the express router, not middleware, and you don't have any routes defined. The static middleware doesn't convert anything (thus the name), so it's not going to serve /app.html unless there's an actual app.html file on disk. To get /app.html working, add:
app.get('/app.html', function (req, res) { res.render('app');});
//or you probably want app.get('/', ...if you want this to be your home page
//you probably also don't want/need ".html" in your URLs as this has fallen out of style
Your stylus problem is the automatic semicolon insertion monster. You must not put the "return" keyword on a line by itself. Your compile function is returning undefined instead of a stylus instance. Keep the compile formatted as it is on the nib documentation and all is well.

Related

NodeJS won't serve my static files

I encountered a lot of instances of my problem, however none of them worked for me. Where is my server root, if both of these paths don't work? Static files aren't found neither under la-wars > public > css > file, nor under the more relative public > css > file.
This is how I use express for the purpose:
app.use(express.static(path.join(__dirname, 'public')));
And it results in the second 404 result below. With the first one, I had express.static() commented out and tried an absolute path in the markup.
EDIT: The entire entry point app:
var express = require('express'),
app = require('express')(),
ejs = require('ejs'),
path = require('path'),
cookieParser = require('cookie-parser'),
util = require('util'),
port = process.env.PORT || 3000,
user = require('./models/user.js'),
formidable = require('formidable'),
router = express.Router();
app.use(express.static(path.join(__dirname, 'public')));
app.set('views', __dirname + '/views');
app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');
//app.use(require('.middleware/auth.js'));
app.use(require('./routes')(express));
app.listen(port);
It depends what the url is you put on your html pages, but from the console's error window, I'm going to guess this (notice extra first argument) solves your problem:
app.use("/public", express.static(__dirname + '/public'));
It seems you use both "/public" (for the js) and "public" (for the css) in your html file. The code above should at least fix one of the two errors.
The call:
app.use(express.static(path.join(__dirname, 'public')));
is saying that it could serve your files in the 'public' folder directly, so you can keep this but in the html files remove the "public/" from the urls and begin them with "/" directly.
You will find slider.jsat the url of http://localhost:3000/js/slider.js - that's how it works.

Exclude sub directory from static files in express

Is there any way to exclude sub directory from express static middleware in express 4.8.5.
For example if I have :
app.use(express.static(__dirname + 'public'));
And my public directory is like this :
- public
- css
- images
- scripts
- index.html
- exclude_me
- scripts
- views
- index.html
So I need to exclude last sub directory and when user does :
GET /exclude_me
It should call my route rather than returning directory automatically.
I can't just remove it from public dir because it depends on stuff inside it because public directory is angular application and exclude_me is another angular application that fetches scripts from /exclude_me/scripts AND from /public/scripts.
I know it is little confusing but it is how it is and I cannot just remove it from public dir because it won't see public/scripts any more which are needed and I cannot leave it because I cannot authorize it then (all authorization is in public/scripts)
If there is some smarter way to do this, feel free to let me know :)
You can add your own middleware. Here's what I did to exclude some folders:
app.use('/public', (req, res, next) => {
if (env !== 'development') {
var result = req.url.match(/^\/js\/(maps|src)\/.+\.js$/)
if (result) {
return res.status(403).end('403 Forbidden')
}
}
next()
})
app.use('/public', express.static(path.join(__dirname, '/public')))
It's possible by adding regular expressions to the first optional param of use method.
According with Express 4.x API path documentation.
Example, I don't want to give access to my secure folder inside public folder:
var express = require('express');
var app = express();
app.use([/^\/public\/secure($|\/)/, '/public'], express.static(__dirname + '/public'));
This will allow you to access all files but not the ones in the secure folder.
You can use it also to restrict a file extension, example files that ends with .js.map:
app.use([/(.*)\.js\.map$/, '/public'], express.static(__dirname + '/public'));
And you also can add multiple rules, like this example where secure folder and files that end with .js.map are ignored from the static folder:
app.use([/^\/public\/secure($|\/)/, /(.*)\.js\.map$/, '/public'], express.static(__dirname + '/public'));
I had a similar problem, which may be the answer you were seeking. Given the following directory:
public
css/
images/
secure/
index.html
The Express Middleware stack I wanted was this:
1. Static files (except the `secure/` directory)
2. Logging
3. Authentication
4. `secure/` static files
Here's how I solved it:
var express = require('express');
var path = require('path');
var app = express();
// path.join here makes it work cross platform with Windows / Linux / etc
var statics = express.static(path.join(__dirname, 'public'));
function secureStatic(secure) {
return function (req, res, next) {
if (/^\/secure/.test(req.path) === !!secure) return statics(req, res, next);
return next();
};
}
// add public files
app.use(secureStatic());
app.use(logging());
app.use(authentication());
// add secured files
app.use(secureStatic(true));
This will only serve public files when unauthenticated, and only serve secure files after authentication.
Most solutions above are to use a middleware.
However, there is a just easier way to solve this.
Don't serve static assests directly with the dir public rather than serve dir just what you want to serve with a virtual path prefix .
You can serve like below
var express = require('express');
var app = express();
app.use('/public', __dirname + 'css');
app.use('/public', __dirname + 'images');
...

How to use static in express js on OS X?

Faced with strange problem: can't setup static folder for express js.
Folder that should be static: /Users/user/Sites/move/assets
Server.js file: /Users/user/Sites/move/app/server.js
URL i use: http://localhost:5001/assets/css/bootstrap.css
Server.js file looks like this:
function Run(config) {
var express = require('express'),
ejs = require('ejs');
var app = express();
app.configure(function() {
// express.static(config.APP_BASE_PATH + '/assets' prints /Users/user/Sites/move/assets
app.use(express.static(config.APP_BASE_PATH + '/assets'));
// Also used
// app.use('assets', express.static(config.APP_BASE_PATH + '/assets'));
});
app.get('/', function(req, res){
res.render('index.html');
});
app.listen(config.APP_PORT);
}
Where is the problem?
It is also possible to create application skeleton with configured static assets, using npm and expres command.
npm install -g express
express --sessions --css stylus --ejs myapp
When you say this:
app.use(express.static(config.APP_BASE_PATH + '/assets'));
It means that a request for /assets/css/bootstrap.css will be looked up as:
config.APP_BASE_PATH + '/assets' + '/assets/css/bootstrap.css'
Which is clearly not what you want.
Instead, you can prefix the middleware declaration:
app.use('/assets', express.static(config.APP_BASE_PATH + '/assets'));
Which means that if a request starts with /assets, the static middleware will take everything after that prefix (so /css/bootstrap.css) and look that up in the directory that you passed.
The starting / is important, otherwise it won't match the incoming request.

hogan.js with master pages or layouts

Is it possible in any way to use hogan.js as template engine with layouts something like
"Razor or master pages in .NET"?
I would get a result like this:
layout.hjs:
contains "header" & "footer"
and
index.hjs:
will include layout.hjs and contain only page content.
sure:
layout.hjs:
{{> header}}
{{$content}}
default content
{{/content}}
{{> footer}}
index.hjs:
{{<layout}}
{{$content}}
your content goes here
{{/content}}
{{/layout}}
see the hogan test file for all it can do:
https://github.com/twitter/hogan.js/blob/master/test/index.js
btw. this is Hogan#3.0.0, get it with a git url with mpn
I'm not sure what you mean, "Razor or master pages in .NET"? What are you looking to do, use view partials?
But the basic way of setting up Hogan.js for Express is as follows:
var express = require('express');
var app = express();
app.set('views', __dirname + '/views');
app.set('view engine', 'hjs');
app.use(app.router);
app.use(express.static( __dirname + '/public' ));
app.get('/', function( req, res, next ) {
res.render('index');
});
app.listen(3000);
You will have to npm install express [--save], npm install hjs [--save], depending if it's inside your package.json already or not.
Then you just make a views directory and throw an index.hjs file and you're set.
Let me know what you want to do with your templates and we can work from there.

How do I use Node and Express with coffeescript and requirejs?

Here's what I want.
A node application using the express webserver
Using coffeescript on the server and more importantly the client
Using require.js on the client (and eventually on the server)
The recommended way I've been able to find of hooking up coffeescript for the client is to use connect-assets. This seems to require using jade helpers to actually compile coffeescript eg.
!=js('monalisa.js')
seems to compile monalisa.coffee and generate the correct <script> tag. Now I want to use require.js and here I stumble. How do I ensure that connect-assets compiles everything correctly without using the jade helpers?
Here's my fairly simple app.js:
require('coffee-script');
var express = require('express')
, http = require('http')
, path = require('path')
, connectAssets = require('connect-assets');
var publicDir = path.join(__dirname, 'public');
var app = express();
app.configure(function(){
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( connectAssets() );
app.use('/public', express.static(publicDir));
app.use(express.logger());
app.use(express.methodOverride());
app.use(app.router);
});
app.configure('development', function(){
app.use(express.errorHandler({
dumpExceptions: true,
showStack: true
}));
});
app.get('/', require('./routes').index);
app.get('/monalisa', require('./routes/monalisa').monalisa);
http.createServer(app).listen(app.get('port'), function(){
console.log("Express server listening on port " + app.get('port'));
});
I've created a package to help solve this problem; it's called connect-assets-jspaths.
From the readme:
Installation
npm install connect-assets-jspaths
Note, there is a dependency on CoffeeScript.
Server Side Usage
assets = require "connect-assets"
jsPaths = require "connect-assets-jspaths"
# Snip ...
app.use assets()
# Exports the global function exportPaths() and jsUrl(); see below in View Helpers.
jsPaths assets
# Optionally, pass a log function to see progress
# jsPaths assets, console.log
Watch changes and re-compile
Now you can pass some additional callbacks in and it will monitor your connect assets directories for changes.
fileChangedCallback = (err, filePath) ->
console.log "File Changed: #{filePath}"
jsPaths assets, console.log, fileChangedCallback, (err, watcher) ->
console.log "Watcher initialized"
NOTE You'll probably want to disable this for production mode.
View Usage
This module exports two global functions exportPaths() and jsUrl().
// Using this in your view
!= exportPaths("jsPaths")
// Turns into this when rendered in production
<script type="text/javascript">
var jsPaths = { "main", "/builtAssets/js/main.13819282742.js" /* snip all the other file paths */ };
</script>
// Using this in your view
- var mainJsPath = jsUrl("/js/main.js")
script(type="text/javascript", data-main="#{mainJsPath}", src="//cdnjs.cloudflare.com/ajax/libs/require.js/2.0.2/require.min.js")
// Turns into this when rendered in production
<script type="text/javascript" data-main="/builtAssets/js/main.13819282742.js" src="//cdnjs.cloudflare.com/ajax/libs/require.js/2.0.2/require.min.js"></script>
Dynamic RequireJS Paths
Now that we have a variable with our requireJS friendly paths in it, we can set those paths in the RequireJS config
# Example main.coffee file in /assets/js folder
requirePaths =
paths:
jquery: "//cdnjs.cloudflare.com/ajax/libs/jquery/1.7.2/jquery.min"
underscore: "//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.3.3/underscore-min"
backbone: "//cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.2/backbone-min"
text: "/js/lib/text"
handlebars: "/js/lib/handlebars"
if jsPaths
for own key, value of jsPaths
# Fix up the lib references
key = key.slice 4 if key.slice(0, 4) == "lib/"
requirePaths.paths[key] = value
require.config
paths: requirePaths.paths
shim:
jquery:
exports: "$"
underscore:
exports: "_"
backbone:
deps: ["underscore", "jquery"]
exports: "Backbone"
require ['app'], (App) ->
new App().initialize()
Try mimosa, it'll help you with each one of those things out of the box. http://www.mimosajs.com
mimosa new [name] will give you a starter project with all of it.
Sorry for the new answer, but I decided to go make an account. =)
Mimosa will give you a small Express application if you choose Express as part of the mimosa new workflow. And if you choose CoffeeScript it'll give you an Express app in CoffeeScript. And it'll have RequireJS included in the scaffolded application. So you should not need to rewrite anything. You just need to plug your stuff in. If anything the Express app it gives you will serve as an example for you to do it yourself without using Mimosa.

Resources