Home > Web Front-end > JS Tutorial > body text

Node.js Web Application Framework Express Getting Started Guide_Javascript Tips

WBOY
Release: 2016-05-16 16:46:36
Original
1145 people have browsed it

1. Installation

Copy the code The code is as follows:
$ npm install express

or use it anywhere Executable express(1) installation:

Copy the code The code is as follows:
# Translation Note: This method is strongly recommended
$ npm install - g express

2. Get started quickly

The fastest way to get started with express is to use the executable express(1) to generate an application, as shown below:

Create an app:

Copy the code The code is as follows:

$ npm install -g express
$ express /tmp/foo && cd /tmp/foo

Install dependency packages:
Copy codeThe code is as follows:

$ npm install -d

Start the server:
Copy the code The code is as follows:

$ node app.js

3. Create a server

To create an express.HTTPServer instance, just call the createServer() method. Common to this application example, we can define routing based on HTTP actions (HTTP Verbs), taking app.get() as an example:

Copy code The code is as follows:

var app = require('express').createServer();

app.get('/', function(req, res){
res.send('hello world');
});

app.listen(3000);

4. Create an HTTPS server

Initialize an express.HTTPSServer instance as above. Then we pass it a configuration object that accepts key, cert and other (properties/methods) mentioned in the https documentation.

Copy code The code is as follows:

var app = require('express').createServer( { key: ... });

5. Configuration

Express supports any environment, such as production and development. Developers can use the configure() method to set the current required environment. If the call to configure() does not include any environment names, it will run the specified callbacks in all environments.

Annotation: Aliases like production / development / stage can be chosen by yourself, as shown in app.configure in application.js. See the example below for actual usage.

The following example only dumpExceptions (throws an error) during the development phase and returns a stack exception. But in both environments we use methodOverride and bodyParser. Pay attention to the use of app.router. It can (optional) be used to load (mount) the route of the program. In addition, the first call to app.get(), app.post(), etc. will also load the route.

Copy code The code is as follows:

app.configure(function(){
app .use(express.methodOverride());
app.use(express.bodyParser());
app.use(app.router);
});

app.configure('development', function(){
app.use(express.static(__dirname '/public'));
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

app.configure('production', function(){
var oneYear = 31557600000;
app.use(express.static(__dirname '/public', { maxAge: oneYear }));
app.use(express.errorHandler());
});


For similar environments you can pass multiple environment strings:
Copy code The code is as follows:

app.configure('stage', 'prod', function(){
// config
});

For any internal setting (#), Express provides set(key[, val]), enable(key) and disable(key) methods:

Annotation: For details of settings, see: app.set in application.js.

Copy code The code is as follows:

app.configure(function(){
app .set('views', __dirname '/views');
app.set('views');
// => "/absolute/path/to/views"

app.enable('some feature');
// Equivalent to: app.set('some feature', true);

app.disable('some feature');
// Equivalent to: app.set('some feature', false);

app.enabled('some feature')
// => false
});


To change the environment, we can set the NODE_ENV environment variable, such as:
Copy the code The code is as follows:

$ NODE_ENV=production node app.js

This is very important, Because most caching mechanisms are only turned on during the production phase.

6. Settings

Express supports the following out-of-the-box settings:

1.basepath is the base path of the application used for res.redirect(), which explicitly handles mounted apps.
2.view View is the default root directory For CWD/views
3.view engine The default View engine processing (View files) does not need to use the suffix
4.view cache Enable View cache (enabled in the production stage)
5.charet Change encoding, The default is utf-8
6.case sensitive routes are case sensitive in routing
7.strit routing After enabling (in routing) the trailing / will not be ignored (Annotation: app.get('/sofish ') and app.get('/sofish/') will be different)
8.json callback enables res.send() / res.json() explicit jsonp support (transparent jsonp support)

7. Routing

Express provides a set of informative and expressive routing APIs using HTTP actions. For example, if we want to process an account with the path /user/12, we can define the route as follows. Values ​​associated with named placeholders can be accessed using req.params.

Copy code The code is as follows:

app.get('/user/:id', function(req, res){
res.send('user ' req.params.id);
});

The route is a string that is internally compiled into a regular string. For example, when /user/:id is compiled, a simplified version of the regular expression looks like this:
Copy the code The code is as follows:

// Modify the official string
//user/([^/] )/?/

Regular expressions can be passed in to apply to complex scene. Since content groups captured via literal regular expressions are anonymous, we may access them directly via req.params. Therefore, the first set of content we capture will be req.params[0], while the second set is immediately following req.params[1].
Copy code The code is as follows:

app.get(/^/users?(?: /(d )(?:..(d ))?)?/, function(req, res){
res.send(req.params);
});

Curl For the request of the above defined route:
Copy the code The code is as follows:

$ curl http:/ /dev:3000/user
[null,null]
$ curl http://dev:3000/users
[null,null]
$ curl http://dev:3000/users /1
["1",null]
$ curl http://dev:3000/users/1..15
["1","15"]

below They are instances of some routes, associated with the paths they may use:
Copy the code The code is as follows:

"/user/:id"
/user/12

"/users/:id?"
/users/5
/users

"/files/*"
/files/jquery.js
/files/javascripts/jquery.js

"/file/*.*"
/files/jquery.js
/files/javascripts/jquery.js

"/user/:id/:operation?"
/user/1
/user/1/edit

"/products.:format"
/products.json
/products.xml

"/products.:format?"
/products.json
/products.xml
/products

"/user/:id.:format?"
/user/12
/user/12.json


For example, we can use POST to send json data through bodyParser This middleware can parse json request content (or other content) to return data and store the return result in req.body:
Copy code The code is as follows:

var express = require('express')
, app = express.createServer();

app.use(express.bodyParser());

app.post('/', function(req, res){
res.send(req.body);
});

app.listen(3000);


Usually we can use a "foolish" placeholder like user/:id that has no (naming) restrictions. However, for example, if we want to limit the user ID to only numbers, then we might use /user/:id([0-9]), which will only take effect when the placeholder contains at least one digit (adaptation , match).

8. Passing Route Control

We can control the next adapted route by calling the third parameter, the next() function. If no adapter is found, control will be passed back to Connect, and the middleware will be called in the order added in use(). The same principle applies to multiple routes defined to the same path. They will be called in sequence until one of them decides to respond to the request without calling next().

Copy code The code is as follows:

app.get('/users/:id?' , function(req, res, next){
var id = req.params.id;
if (id) {
          // do something
  } else {
        next();
}
});

app.get('/users', function(req, res){
// do something else
});


app.all() method only needs to be called once Conveniently apply the same logic to all HTTP actions. Below we use this to extract a user from the dummy data and assign it to req.user.
Copy code The code is as follows:

var express = require('express')
, app = express.createServer();

var users = [{ name: 'tj' }];

app.all('/user/:id/:op?', function(req, res, next){
req.user = users[req.params.id];
if (req .user) {
next();
} else {
next(new Error('cannot find user ' req.params.id));
}
});

app.get('/user/:id', function(req, res){
res.send('viewing ' req.user.name);
});

app.get('/user/:id/edit', function(req, res){
res.send('editing ' req.user.name);
});

app.put('/user/:id', function(req, res){
res.send('updating ' req.user.name);
});

app.get('*', function(req, res){
res.send(404, 'what???');
});

app.listen(3000);


9. Middleware

The Connect middleware (properties) used usually accompany one of your regular Connect servers, passed to express.createServer() . For example:

Copy code The code is as follows:

var express = require('express');

var app = express.createServer(
express.logger()
, express.bodyParser()
);


In addition, within the configure() block - this progressive In a progressive manner, we can also easily use use() to add middleware.
Copy code The code is as follows:

app.use(express.logger({ format: ' :method :url' }));

Usually, when using connect middleware you may use require('connect'), like this:
Copy code The code is as follows:

var connect = require('connect');
app.use(connect.logger());
app.use(connect.bodyParser());

This is somewhat annoying, so express re-exports these middleware properties, even though they are the same:
Copy code The code is as follows:

app.use(express.logger());
app.use(express.bodyParser());

The order of middleware is very important. When Connect receives a request, the first middleware we pass to createServer() or use() for execution will come with three parameters, request, response, and a callback. function (usually next). When next() is called, it will be the second middleware's turn, and so on. This is noteworthy because many middlewares depend on each other. For example, methodOverride() queries the req.body method to detect HTTP method overloads, while bodyParser() parses the request content and stores it in req. body. Another example is cookie parsing and session support, we must first use() cookieParser() followed by session().

Many Express applications contain a line like app.use(app.router). This may seem a bit strange, but in fact it is just a line that contains all the defined routing rules and performs a route lookup based on the existing URL request and HTTP method. A middleware function. Express allows you to determine its to position, but by default it is placed at the bottom. By changing the location of the route, we can change the priority of the middleware. For example, we want to make error reporting the last middleware so that any exceptions passed to next() can be handled through it; or we want static files The service priority is lower to allow our router to listen for the number of downloads of a single static file request, etc. This looks more or less like this:

Copy the code The code is as follows:

app.use( express.logger(...));
app.use(express.bodyParser(...));
app.use(express.cookieParser(...));
app.use (express.session(...));
app.use(app.router);
app.use(express.static(...));
app.use(express.errorHandler (...));

First we add logger(), which may contain the node's req.end() method to provide us with response time data. The content of the next request will be parsed (if there is data), followed by cookie parsing and session support. At the same time, req.session will be defined when the route in app.router is triggered. We do not call it at this time. next(), so the static() middleware will not know this request. If the following route has been defined, we can record various statuses, refuse downloads, consume download points, etc.
Copy code The code is as follows:

var downloads = {};

app.use(app.router);
app.use(express.static(__dirname '/public'));

app.get('/*', function(req, res, next){
var file = req.params[0];
downloads[file] = downloads[file] || 0;
downloads[file] ;
next();
});

10. Routing middleware

Routing can use router middleware to pass more than one callback function (or array) to its method. This feature is great for restricting access, downloading data via routing, etc.

Usually asynchronous data retrieval might look like the following example, where we use the :id parameter and try to load a user:

Copy code The code is as follows:

app.get('/user/:id', function(req, res, next){
loadUser(req.params.id, function(err, user ){
if (err) return next(err);
res.send('Viewing user ' user.name);
});
});

is To ensure the DRY principle and improve readability, we can apply this logic within a middleware. As shown below, abstracting this logic into middleware will allow you to reuse it while keeping our routing simple.
Copy code The code is as follows:

function loadUser(req, res, next) {
// You would fetch your user from the db
var user = users[req.params.id];
if (user ) {
req.user = user;
next();
} else {
next(new Error('Failed to load user ' req.params.id));
}
}

app.get('/user/:id', loadUser, function(req, res){
res.send('Viewing user ' req.user.name);
});


Multiple routes can be applied sequentially to deeper logic, such as restricting access to a user account. The example below allows only authenticated users to edit his or her account.
Copy code The code is as follows:

function andRestrictToSelf(req, res, next) {
req.authenticatedUser.id == req.user.id
? next()
: next(new Error('Unauthorized'));
}

app.get('/user/:id/edit', loadUser, andRestrictToSelf, function(req, res){
res.send('Editing user ' req.user.name);
} );


Always remember that routes are just simple functions, as shown below, we can define functions that return middleware to create a more expressive and flexible solution.
Copy code The code is as follows:

function andRestrictTo(role) {
return function( req, res, next) {
req.authenticatedUser.role == role
? next()
: next(new Error('Unauthorized'));
}
}

app.del('/user/:id', loadUser, andRestrictTo('admin'), function(req, res){
res.send('Deleted user ' req.user.name);
});


Commonly used middleware "stacks" can be passed through an array (will be applied recursively), which can be mixed and matched to any level (which can be mixed and matched to any degree).
Copy code The code is as follows:

var a = [middleware1, middleware2]
, b = [middleware3, middleware4]
, all = [a, b];

app.get('/foo', a, function(){});
app.get('/bar', a, function(){});

app.get('/', a, middleware3, middleware4, function(){});
app.get('/', a, b, function(){});
app .get('/', all, function(){});


For the complete code of this example, please see the route middleware example repository.

We may want to "skip" the remaining routing middleware many times and continue to match subsequent routes. To do this, we simply call next() with the 'route' string - next('route'). If no remaining routes match the requested URL, Express will return 404 Not Found.

11. HTTP method

I have come across app.get() several times so far. In addition, Express also provides other common HTTP actions, such as app.post(), app.del(), etc.

A common example of POST usage is to submit a form. Next we simply set the method attribute of the form to post in html, and control will be assigned to the route defined below.

Copy code The code is as follows:






By default Express does not know how to handle the content of this request, so we must add bodyParser middleware , it will parse the content requested by application/x-www-form-urlencoded and application/json, and store the variables in req.body. We can use this middleware like the following example:
Copy the code The code is as follows:

app.use(express.bodyParser());

As shown below, our route will have access to the req.body.user object, which will contain name and email when defined. (Annotation: If the content sent by the form is not empty).
Copy code The code is as follows:

app.post('/', function(req, res){
console.log(req.body.user);
res.redirect('back');
});

When you want to use something like PUT in a form In this way, we can use a hidden input named _method, which can be used to modify the HTTP method. In order to do this, we first need the methodOverride middleware, which must appear after the bodyParser in order to use the form values ​​contained in its req.body.
Copy code The code is as follows:

app.use(express.bodyParser());
app.use(express.methodOverride());

As for why these methods are not available by default, simply because it is not required for the complete functionality required by Express. The use of methods depends on your application. You may not need them. The client can still use methods like PUT and DELETE. You can use them directly because methodOverride provides a very good solution for forms. The following will demonstrate how to use the PUT method, which may look like:
Copy the code The code is as follows:






app.put('/', function(){
console.log(req.body.user);
res.redirect('back');
});

12. Error handling

Express provides the app.error() method so that the received exception can be thrown in a route or passed to next(err). The following example will handle different pages based on a specific NotFound exception:

Copy the code The code is as follows:

function NotFound(msg){
this.name = 'NotFound';
Error.call(this, msg);
Error.captureStackTrace(this, arguments.callee);
}

NotFound.prototype.__proto__ = Error.prototype;

app.get('/404', function(req, res){
throw new NotFound;
});

app.get('/500', function(req, res){
throw new Error('keyboard cat!');
});


As follows, we can Calling app.error() multiple times. Here we detect instances of NotFound and either display a 404 page or pass it to the next error handler. It is worth noting that these handlers can be defined anywhere, as they will be placed under the route handler during listen(). It allows definitions within the configure() block so that we can use different exception handling methods based on the environment.
Copy code The code is as follows:

app.error(function(err, req, res, next){
if (err instanceof NotFound) {
res.render('404.jade');
} else {
next(err);
}
}) ;

For the sake of simplicity, here we assume that all errors in this demo are 500. Of course, you can choose the one you like. When node executes a system call on the file system, you may receive an error.code with ENOENT, which means "no such file or directory exists" error. We can use it in the error handler, or when there is A specified page can be displayed when needed.
Copy code The code is as follows:

app.error(function(err, req, res) {
res.render('500.jade', {
error: err
});
});

Our app can also use Connect's errorHandler middleware to report exceptions. For example, when we want to output stderr exceptions in the "development" environment, we can use:
Copy the code The code is as follows:

app.use(express.errorHandler({ dumpExceptions: true }));

At the same time during the development phase we may need to display the exceptions we pass and throw on fancy HTML pages. For this we can set showStack to true.
Copy code The code is as follows:

app.use(express.errorHandler({ showStack: true , dumpExceptions: true }));

errorHandler middleware can also return json when Accept: application/json exists, which is very useful for developing applications that rely heavily on client-side Javascript.

13. Route parameter preprocessing

Route parameter preprocessing, through implicit data loading and request verification, can greatly improve the readability of your program. For example, you often need to continuously obtain basic data from multiple routes. Like loading a user with /user/:id, usually we might do it like this:

Copy code The code is as follows:

app.get('/user/:userId', function(req, res, next){
User.get(req.params.userId, function(err, user){
if (err) return next(err);
res.send('user ' user.name);
});
});

Through preprocessing, we Parameters can be mapped to callbacks that perform validation, control, or even load data from the database. As follows, we call app.param() with the parameter name, hoping to map it to some middleware. As you can see, we accept the id parameter which represents the placeholder value. Using this, we load the user and handle errors as normal, and simply call next() to pass control to the next preprocessor or route handler.
Copy code The code is as follows:

app.param('userId', function(req, res, next, id){
User.get(id, function(err, user){
if (err) return next(err);
if (!user) return next(new Error( 'failed to find user'));
req.user = user;
next();
});
});

Once this is done, the above Will greatly improve the readability of routing and allow us to easily share logic throughout the program:
Copy code Code As follows:

app.get('/user/:userId', function(req, res){
res.send('user ' req.user.name);
});


14. View processing

View files use the format ., where is the name of the required module. For example layout.ejs will tell the view system to require('ejs'), the loaded module must (export) the exports.compile(str, options) method, and return a Function to accommodate Express. app.register() can be used to change this default behavior and map file extensions to a specific engine. For example "foo.html" can be processed by ejs.

The following example uses Jade to process index.html. Because we are not using layout: false, the content processed by index.jade will be passed into a local variable named body in layout.jade.

Copy code The code is as follows:

app.get('/', function(req, res){
res.render('index.jade', { title: 'My Site' });
});

The new view engine setting allows us to specify the default template engine , for example, when we use jade, we can set it like this:
Copy code The code is as follows:

app .set('view engine', 'jade');

allows us to do this:
Copy code The code is as follows:

res.render('index');

corresponds to:
Copy code The code is as follows:

res.render('index.jade');

When the view engine is set, the extension is optional, but we can still mix and match Template engine:
Copy code The code is as follows:

res.render('another-page. ejs');

Express also provides view options settings, which will be applied every time a view is rendered. For example, you may do this if you do not want to use layouts:
Copy code The code is as follows:

app.set('view options', {
layout: false
});

This can be overloaded inside the res.render() call when needed:
Copy code The code is as follows:

res.render('myview.ejs', { layout: true });

When there is a need to change a layout, we Usually you need to specify another path. For example, when we have set the view engine to jade, and the file is named ./views/mylayout.jade, we can simply pass the parameters like this:
Copy code The code is as follows:

res.render('page', { layout: 'mylayout' });

Otherwise (Annotation: No When the view engine is set to jade or other engines), we must specify an extension:
Copy the code The code is as follows:

res.render('page', { layout: 'mylayout.jade' });

They can also be absolute paths:
Copy code The code is as follows:

res.render('page', { layout: __dirname '/../../mylayout.jade ' });

There is a good example for this - customizing the opening and closing tags of ejs:
Copy code The code is as follows:

app.set('view options', {
open: '{{',
close: '}}'
})

15. View component

Express’s view system has built-in support for parts and collections, which is equivalent to replacing a document fragment with a “mini” view. For example, to display comments repeatedly in a view, we can use the widget set:

Copy the code The code is as follows:

partial('comment', { collection: comments });

If no other options or local variables are needed, we can omit the entire object and simply pass in an array, which is the same as The above are equivalent:
Copy the code The code is as follows:

partial('comment', comments);

In use, the widget set provides support for some "magic" local variables for free:

1.firstInCollection true, when it is the first object
2.indexInCollection index in the collector object
3.lastInCollection true, when it is the last object
4 .collectionLength The length of the collector object

The transfer (generation) of local variables has a higher priority. At the same time, local variables passed to the parent view are also adapted to the child view. For example, when we use partial('blog/post', post) to render a blog post, it will generate a post local variable. There is a local variable user in the view that calls this function, and it will also be valid for blog/post. (Annotation: partial here is more like the include method in php).

Note: Please use widget collectors with caution. Rendering a widget collection array with a length of 100 is equivalent to us needing to process 100 views. For simple collections, it is better to repeat the built-in rather than use a widget collector to avoid excessive overhead.

16. View Search

View search is performed relative to the parent view (path). For example, if we have a view page called views/user/list.jade, and partial('edit') is written inside it, it will try to load views/ user/edit.jade, similarly partial('../messages') will load views/messages.jade.

The View system also supports template indexing, allowing you to use a directory with the same name as the view. For example, in a route, res.render('users') returns views/users.jade, which is views/users/index.jade. (Annotation: First handle the . case, and then handle the / case. For details, see view.js.)

When using the above view index, we use partial('users') to reference views/users/index.jade in the same directory as the view. At the same time, the view system will try to index ../users/index. Without us calling partial('users').

17. Template Engines

The following are the most commonly used template engines for Express:

1.Haml: haml implementation
2.Jade: haml.js successor
3.EJS: Embedded JavaScript
4.CoffeeKup: Templates based on CoffeeScript
5.jQuery Templates

18. Session support

Session support can be obtained by using Connect's session middleware. For this, we usually need to add the cookieParser middleware in front of it, which will parse and store cookie data in req.cookies.

Copy code The code is as follows:

app.use(express.cookieParser());
app.use(express.session({ secret: "keyboard cat" }));

By default, the session middleware uses Connect's built-in memory storage, but there are many other implementations. For example, connect-redis provides a Redis session storage, which can be used as follows:
Copy code The code is as follows :

var RedisStore = require('connect-redis')(express);
app.use(express.cookieParser());
app.use(express.session( { secret: "keyboard cat", store: new RedisStore }));

At this point, the req.session and req.sessionStore properties will be available to all routes and subsequent middleware. All properties on req.session will be automatically saved in a response, for example when we want to add data to the shopping cart:
Copy code The code is as follows:

var RedisStore = require('connect-redis')(express);
app.use(express.bodyParser());
app .use(express.cookieParser());
app.use(express.session({ secret: "keyboard cat", store: new RedisStore }));

app.post('/add-to-cart', function(req, res){
// We may POST multiple items through a form
// (use bodyParser() in some cases Middleware)
var items = req.body.items;
req.session.items = items;
res.redirect('back');
});

app.get('/add-to-cart', function(req, res){
// When returned, the page GET /add-to-cart
// We can check req. session.items && req.session.items.length
// To print out the prompt
if (req.session.items && req.session.items.length) {
req.notify('info' , 'You have %s items in your cart', req.session.items.length);
}
res.render('shopping-cart');
});


For req.session, it also has methods like Session#touch(), Session#destroy(), Session#regenerate(), etc. to maintain and operate the session. See the Connect Session documentation for more details.

19. Upgrade Guide

For students using Express 1.x, if you have important programs that need to be upgraded to 2.x for better support, please see the official very detailed migration guide : http:/ /expressjs.com/guide.html#migration-guide

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template