Generator CommandsTo generate a skeleton Express.js app, we need to run a terminal command: express [options] [dir|appname] e.g., express cli-app, where the options are as follows: defau
Trang 1Generator Commands
Trang 2Generator Commands
Generator Commands Comparable to Ruby on Rails and many other web frameworks, Express.js comes with a command-line interface (CLI) for jump-starting your development process The CLI generates
a basic foundation for the most common cases Unlike Rails or Sails, Express generator doesn’t support the addition of routes/models (as
of this writing)
Trang 3Generator Commands
If you followed the global installation instructions in Chapter 1, you should be able to see the version number if you run the $ express -V form anywhere on your machine If you type $ express -h or $ express help, you get the list of available options and their usage In this
book, we’re using the latest (as of this writing) version, 4.2.0, which is compatible with Express.js 4.x
Trang 4Generator Commands
To generate a skeleton Express.js app, we need to run a terminal
command: express [options] [dir|appname] (e.g., express cli-app), where the options are as follows:
default, Jade (http://jade-lang.com/tutorial/) is used
Stylus (http://learnboost.github.io/stylus), or Compass
(http://compass-style.org); by default, plain CSS is used
Trang 5Generator Commands
These options are optional, of course, so you can just run express cli-app and you’ll get an app with default settings If the dir/appname option is omitted, Express.js will create files using the current folder
as the base for the project Otherwise, the application will be under the specified directory
Trang 6Generating a Skeleton Express.js app
For the sake of experimenting, let’s run this command: $ express -e -c less -f cli-app The generator tool will output created files and suggest commands to run to boot up the server
Express.js provides a robust command-line tool for spawning
boilerplates rapidly The downside is that Express.js Generator
approach is not very configurable For example, it’s possible to use a Handlebars template engine (and many others not just Hogan, Jade, JSHTML, or EJS provided by CLI) when you create apps manually, but Express.js Generator doesn’t have this option (as of this writing)
Trang 7Reviewing the Application’s Structure
Let’s briefly examine the application structure The project’s root
folder includes two very important files, app.js and package.js, as
indicated on these lines shown in Figure 2-5: create:
cli-app/package.json and create: cli-app/ app.js The app.js file is the main file (as discussed in the previous chapter) and it connects all the other pieces The package.json file has all the needed dependencies (express at the bare minimum) Then, we have three folders:
files
pasted) into separate files/ internal modules
Trang 8Reviewing the Application’s Structure
The public folder has three folders of its own when project is generated
by express-generator:
options)
The routes folder has two files: index.js, which handles the home page (root or /), and users.js, which
handles the /users route The folders in the public folder are not mandatory, and you can create arbitrary folders that will be exposed on the / route of your server by the express.static() middleware For example, the content of public/img will be available at http://localhost:3000/img I personally prefer img, js and css instead of images, javascripts and stylesheets When you rename the folders inside /public, you don’t need
to make any additional change in the Express.js configuration You can also rename the views and public folders themselves, but you’ll need to make some additional changes in configuration statements
Trang 9Open the main web server file app.js in your favorite text editor We’ll briefly go through the
auto-generated code and what it does before diving deeper into each one of those configurations We include the following module dependencies:
var express = require('express');
var path = require('path');
var favicon = require('static-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var users = require('./routes/users');
Trang 10Next, we create the Express.js app object:
var app = express();
Then, we define configuration settings For now, you can probably guess their meaning based on their names That is, where to get template files (views) along with what template engine to use (view engine) More details on these parameters so for now let’s move along with the app.js file:
app.set('views', path.join( dirname, 'views'));
app.set('view engine', 'ejs');
We next define middleware (discussed in detail in Chapter 4) to serve favicon, log events, parse the request body, support old browsers’ HTTP methods, parse cookies, and utilize routes:
app.use(favicon()); app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded()); app.use(cookieParser());
Trang 11The following middleware is responsible for compiling Less styles into CSS styled that will be
served to the browser: app.use(require('less-middleware')(path.join( dirname, 'public')));
We pass the folder (public) as a parameter to make it scan this folder recursively for any *.less files The CSS file name and Less file name need to match, so if we use /css/style.css(e.g., in HTML or Jade), we need to have /public/css/style.less Express.js will compile Less for each request This statement takes care of serving static assets from the public folder:
app.use(express.static(path.join( dirname, 'public')));
The routes are defined as a module in a separate file, so we just pass the functions’ expressions instead of defining them right here as anonymous request handlers:
app.get('/', routes.index);
app.get('/users', user.list);
Trang 12Express.js gets its environment variable from process.env.NODE_ENV, which is passed as NODE_ENV=production, for example, either when the server is started or in the machine’s configurations With this condition, we enable a more explicit error handler for the development environment The generator provides us with a 404 (Not Found) middleware, and two 500 (Internal Server Error) error handlers, one for development (more verbose) and one for production:
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404; next(err); });
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', { message: err.message, error: err }); }); }
Trang 13app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', { message: err.message, error: {} }); });
Unlike the Hello World example, this server is not booted right away, but exported:
module.exports = app; In /bin/www, the server is imported from the app.js file: #!/usr/bin/env node var debug = require('debug')('cli-app'); var app = require(' /app'); This statement sets a custom setting with the name port to use it later for server boot-up: app.set('port',
process.env.PORT || 3000); Finally, the server is started with familiar listen():
var server = app.listen(app.get('port'), function() { debug('Express server listening on port ' + server.address().port); });
Trang 14For your reference, the following is the full code for app.js:
var express = require('express');
var path = require('path');
var favicon = require('static-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
Trang 15For your reference, the following is the full code for app.js:
// view engine setup
app.set('views', path.join( dirname, 'views'));
app.set('view engine', 'ejs');
app.use(favicon());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser()); a
pp.use(require('less-middleware')(path.join( dirname, 'public')));
app.use(express.static(path.join( dirname, 'public')));
app.use('/', routes); app.use('/users', users);
Trang 16For your reference, the following is the full code for app.js:
/// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404; next(err); });
/// error handlers // development error handler // will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', { message: err.message, error: err }); });
}
Trang 17For your reference, the following is the full code for app.js:
// production error handler // no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', { message: err.message, error: {} }); });
module.exports = app;
If you navigate ($ cd cli-app) into the project folder and run $ npm install, you should observe the installation of NPM modules based on the package.json entry After the installations are finished, run npm start or $ /bin/www When you navigate to
http://localhost:3000 in your browser
Trang 18Express.js generator is not a very powerful tool, because it doesn’t do much after the boilerplate creation However, it provides developers with boilerplates/skeletons that can be used for rapid prototyping In addition, beginners can learn about recommended structure and code organization, as well
as learn how to include some middleware such as Less and express.static() The next section summarizes some common patterns and conventions regarding the folder structure of Express.js apps.