大神的node书,免费

视频:https://node.university/courses/short-lectures/lectures/3949510

另一本书:全栈JavaScript,学习backbone.js node.js and MongoDB.

1,2章:

  1. Setting up Node.js and Other Essentials [2nd Edition]
  2. Using Express.js 4 to Create Node.js Web Apps [2nd Edition]

第一章

  • Node.js and npm (Node package manager) installation
  • Node.js script launches
  • Node.js syntax and basics
  • Node.js integrated development environments (IDEs) and code editors
  • Awareness of file changes
  • Node.js program debugging

Key Differences Between Node and Browser JavaScript

node没有window, 因此也就没有document对象模型,没有DOM,没有hierarchy of element。

node有global object.(小写字母),可以在任何node环境,文件,app中使用。

你可以在global object上创建property,同时它也有内建的properties。这些properties也是global的,因此可以用在anywhere。

在browser,有内建的modules。

但是node没有core modules,通过文件系统可以使用各种modules。


REPL

进入node控制台,直接在terminal输入node, 这是一个virtual 环境,通常称为read-eval-print-loop

可以直接执行Node.js/JavaScript代码。

⚠️:

require()方法,是node.js的modules功能,在chrome browser 控制台上会报告❌ReferenceError。


Launching Node.js Scripts

语法:

node filenamenode -e "直接输入javaScript代码"
//如$ node -e "console.log(new Date())

参数e, 是evaluate script, -e, --eval=...


Node.js Basics and Syntax

Node.js使用chrome v8引擎和ESCAScript,因此大多数语法和前端js类似。

  • Loose typing
  • Buffer—Node.js super data type
  • Object literal notation
  • Functions
  • Arrays
  • Prototypal nature
  • Conventions

Loose Typing

大多数时候支持自动typecasing。primitives包括:String, Number, Boolean, Undefined, Null。

Everything else is an object。包括:Class, Function, Array, RegExp。

在Js,String, Number, Boolean对象有帮助方法:

//例子:
'a' === new String('a')   //false,  因为使用new String会返回对象
//所以用toString()
'a' === new String('a').toString()   // true
//或者使用==,执行自动typecasing, ===加入了类型判断

Buffer—Node.js Super Data Type

Buffer是Node.js增加的数据类型。

它是一个有效的数据存储data store.

它功能上类似Js的ArrayBuffer。

⚠️:(具体内容,如何创建,使用未看。)

Object Literal Notation对象字面量符号

Node8以后的版本都支持ES6。

比如,箭头函数,使用class, 可以extend另一个对象{...anotherObject}, 动态定义属性名,使用super()关键字,使用函数的短语法。

Functions

在Node.js,函数最重要,它们是对象!可以有属性。

使用function expression定义一个函数,可以anonymous。例子:

//outer 'this'
const f = () => {  //still outer "this"console.log('Hi')return true
}

JavaScript把函数当成对象,所以函数也可以作为参数传递给另一个函数,嵌套函数会发生callbacks。

Arrays

let arr4 = new Array(1,"Hi", {a:2}, () => {console.log('boo')})
arr4[3]() // boo

从Array.prototype,global object继承了一些方法。

Prototypal Nature

JavaScript没有classes的概念,对象都是直接继承自其他对象,即prototypal inheritance!

在JS有几种继承模式的类型:

  1. Classical
  2. Pseudoclassical
  3. Functional

ES6,引用了class,但本质未变,只是写法上更方便。使用了new , class, extends关键字。

具体见之前博客:https://www.cnblogs.com/chentianwei/p/10197813.html

传统的是函数继承模式:

//函数user
let user = function(ops) {return {firstName: ops.firstName || 'John', lastName: ops.lastName || 'Doe', email: ops.email || 'test@test.com', name: function() { return this.firstName + this.lastName}  }
}//继承函数user,
let agency = function(ops) {ops = ops || {}var agency = user(ops)agency.customers = ops.customers || 0agency.isAegncy = truereturn agency
}


Node.js Globals and Reserved Keywords

  • process
  • global
  • module.exports, exports

Node.js Process Information

每个Node.js script的运行,都是一个系统进程。

可以使用process对象得到,当前进程的相关信息:

process.pidprocess.cwd()

node -e "console.log(process.pid)"

global Scope in Node.js

浏览器中的window, document对象都不存在于Node.js.

global是全局对象,可以使用大量方法。如console, setTimeout(), global.process, global.require(), global.module

例子: global.module

Module {id: '<repl>',exports: {},parent: undefined,filename: null,loaded: false,children: [],paths:[ '/Users/chentianwei/repl/node_modules','/Users/chentianwei/node_modules','/Users/node_modules','/node_modules','/Users/chentianwei/.node_modules','/Users/chentianwei/.node_libraries','/Users/chentianwei/.nvm/versions/node/v11.0.0/lib/node' ] }

process对象有一系列的有用的信息和方法:

//退出当前进程,如果是在node环境编辑器,直接退出回到终端目录:
process.exit()

⚠️在node环境,直接输入process,得到process对象的所有方法和信息。

Exporting and Importing Modules

module.exports = (app) => {//
  return app
}

const messages = require('./routes/messages.js')

真实案例使用:

const messages = require(path.join(__dirname, 'routes', 'messages.js'))

解释:

_dirname获得绝对路径, 在加上routes/message.js,得到真实的路径。

Node.js Core Modules

核心/基本模块

Node.js不是一个沉重的标准库。核心模块很小,但足够建立任何网络应用。

Networking is at the core of Node.js!

主要但不是全部的core modules, classes, methods, and events include the following:

  • http(http://nodejs.org/api/http.html#http_http): Allows to create HTTP clients and servers
  • util(http://nodejs.org/api/util.html): Has a set of utilities
  • querystring(http://nodejs.org/api/querystring.html): Parses query-string formatted data
  • url(http://nodejs.org/api/url.html): Parses URL data
  • fs(http://nodejs.org/api/fs.html): Works with a file system (write, read)

方便的Node.js Utilities

  • Crypto (http://nodejs.org/api/crypto.html): Has randomizer, MD5, HMAC-SHA1, and other algorithms
  • Path (http://nodejs.org/api/path.html): Handles system paths
  • String decoder (http://nodejs.org/api/string_decoder.html): Decodes to and from Buffer and String types

使用npm安装Node.js的Modules

留意我们需要package.json, node_modules文件夹来在本地安装modules:

$ npm install <name>

例子:

npm install superagent//然后在program.js,引进这个模块。
const superagent = require('superagent')

使用npm的一大优势,所有依赖都是本地的。

比如:

module A 使用modules B v1.3,

module C 使用modules B v2.0

A,C有它们各自的B的版本的本地拷贝。

这种策略比Ruby和其他一些默认使用全局安装的平台更好。

最好不要把node_modules文件夹放入Git repository,当这个程序是一个模块会被其他app使用的话。

当然,推荐把node_modules放入会部署的app中,这样可以防备由于依赖更新导致的意外损害。

Taming Callbacks in Node.js

callbacks让node.js异步。使用promise, event emitters,或者async library可以防止callback hell

Hello World Server with HTTP Node.js Module

Node.js主要用于建立networking app包括web apps。

因为天然的异步和内建的模块(net, http),Node.js在networks方面快速发展。

下面是一个例子:

创建一个server object, 定义请求handler, 传递数据回到recipient,然后开启server.js。

const http = require('http')
const port = 3000
const server = http.createServer((req, res) => {res.writeHead(200, {'Content-Type': 'text/plain'})res.end('Hello World\n')
}).listen(port, () => {console.log(`Server running at http://localhost:${port}`)
})

首先,需要用http module。并设置服务port.

然后,创建一个server, 它有一个回调函数,函数包括response的处理代码。

为了设置right header和status code:

  res.writeHead(200, {'Content-Type': 'text/plain'})

再输出一个字符串,使用end symbol.

req和res参数是关于一个HTTP request和response data的信息。另外这2个参数可以使用stream(这是一个模块)

再然后,为了让server接受请求requests,使用listen()方法

最后,再terminal输入:

node server.js

terminals上显示console.log的信息:

Server running at http://localhost:3000
//在浏览器打开连接,可看到'Hello World'字样。这是res.end()实现的。


Debugging Node.js Programs

现代软件开发者,可以使用如Chrome Developer Tools, Firfox Firebug。

因为Node.js和浏览器 JavaScript环境类似,所以我们可以使用大量丰富的Debug工具:

  • Core Node.js Debugge(非用于交互界面)
  • Node Inspector: Port of Google Chrome Developer Tools ✅推荐✅。
  • IDEs: WebStorm, VS Code and other IDEs

Core Node.js Debugger

最好的debugger是 console.log(), ?。因为它不会打断interrupt the flow。

首先,把debugger关键字,放在代码内。

然后,使用开启一个js文件的检查:

 node inspect program.js

使用:

  • nextn: step to the next statement
  • contc: continue until the next debugger/break point

更多的见the official web site(http://nodejs.org/api/debugger.html).

非GUI,不直观。

Debugging with node inspector

备注(原书提供的node-inspector安装不上,打开其git,提示我看这篇文章:

Debugging Node.js with Chrome DevTools

使用chrome自带的EevTools即可。

用法:

  1. node版本必须大于6.3
  2. 运行代码:node --inspect hello.js(或者node --inspect-brk hello.js)
  3. 之后在浏览器地址栏输入:  chrome//inspect
  4. 进入一个界面,点击“Open dedicated DevTools for Node”链接。
  5. 会自带打开一个新窗口,可以在这里debug。
    • 当你在terminal退出debug后,这个浏览器窗口会保留,当你再次dubug后,它会自动链接。

所有的chrome devtool功能都可以使用。

node官方的debug文档:

https://nodejs.org/en/docs/guides/debugging-getting-started/

缺点是:无法在原文件上断点。dubugger!

Visual Studio Code (https://code.visualstudio.com/nodejs

被推荐的一个免费的跨平台的Node.js编辑器,包括内建terminal, Node.js debugging。和大量扩展功能。

被高度推荐:使用方法见(廖雪峰)

atom可以在原文件断点但是功能弱,可以使用chrome代替。


Watching for File Changes

Node.js程序储存在内存,如果改变source code, 我们需要重启进程process(i.e., node).

手动killing 进程并重开启一个新的. (Control + C on mac)

⚠️提示:使用Express.js,它会自动reload模版文件,为每次的新请求。所以server无需重启。



第二章 使用框架来创建Node.js Web Apps

(摘录)

Node.js相比Ruby或Java是一个比较年轻的平台。Express是很流行的框架之一。

  • What Express.js is
  • How Express.js works
  • Express.js Installation
  • Express.js scaffolding (command-line tool)
  • The Blog Project overview
  • Express.js Hello World example

Express是web框架,基于core Node.js http和  Connect (http://www.senchalabs.org/connect) 组件。

组件被称为中间件middleware。它们是框架哲学的基石,配置大于约定。

因此,Express是高度配置的,在开发阶段是灵活的和高度客制的。

如果你写node web apps, 只使用core Node.js modules,你会发现你反复的一遍遍的造轮子:

  • Parsing of HTTP request bodies
  • Parsing of cookies
  • Getting information from URL
  • Reading query string from URLs or request bodies
  • 管理web sessions
  • 组织routes和a chain of if 条件,基于URL paths和HTTP methods of the request.
  • 根据data types, 决定适当的响应头
  • ...

Express.js提供了MVC-like的结构为你的web apps。

models可以使用 Mongoose (http://mongoosejs.com) or Sequelize (http://sequelizejs.com) libraries 。

Express.js类似Ruby on Rails. 区别是rails是约定大于配置。

虽然Express是最流行的框架,但仍有不同特色的新框架出现,如Meteor。


How Express.js Works

一个主文件,一般叫server.js, app.js, index.js。

一般这个文件是node命令的开始, 或者作为模块export这个文件 。

在这个文件内,我们做:

  1. 包括第三方依赖作为modules, 例如controllers, utilities, helpers, models。
  2. 配置app设置,如template engine, 和它的文件扩展。
  3. 连接数据库,如MongoDB, Redis, MySQL
  4. 定义middleware,如error handlers, static file folder, cookies, 其他parsers.
  5. 定义routes
  6. 开始app
  7. Export这个app 作为modules

当Express.js app运行,它监听请求。每个进来的请求通过一个定义的中间件链条和路径被处理processed。

通过execution flow进行控制。


安装

创建Express.js app使用,2种方法:

1. express-generator:一个全局的npm包,提供命令行工具来快速的创建程序手脚架--推荐快速的prototyping和服务端(thick server)渲染程序。

2. express:  一个本地的包模块在Node.js app's的node_modules文件夹内--推荐任何程序,需要import express(使用require()或import)

看看当前版本,然后安装:

npm view express
npm i -g express-generator@latestexpress --version

注意⚠️mac用户,可能需要安装权限。使用sudo。


Local Express.js 在本地安装Express.js

建立一个文件夹,进入,然后创建package.json,

npm init

然后安装一个版本:

$ npm install express@4.15.4  --exact

{"name": "hello-simple","version": "1.0.0","description": "","main": "index.js","scripts": {"test": "echo \"Error: no test specified\" && exit 1"},"author": "","license": "ISC","dependencies": {"express": "^4.15.4"}
}

package-lock.json ,用于锁定版本。

如果想要改变版本:

npm install express@4.15.5 --save

Create a server.js file

const express = require('express')
let app = express()app.all('*', (req, res) => {res.send('Welcome to Practical node.js!')
})app.listen(3000, () => {return console.log('Open at localhost:3000')
})

Then launch it with node server.js to see "Welcome to Practical Node.js!" in a browser at http://localhost:3000.


Express.js Scaffolding  创建express.js的手脚架

Comparable with Ruby on Rails and many other web frameworks, Express.js comes with a CLI for jump-starting your development process

帮助命令:

$ express -h

//运行一个terminal命令,创建手脚架
express [options] [dir|appname]

  • -v--view <engine>: Add view support  (defaults to pug)
  • -c <engine>--css <engine>: Add stylesheet <engine> support, such as LESS (http://lesscss.org), Stylus(http://learnboost.github.io/stylus) or Compass(http://compass-style.org) (by default, plain CSS is used)
  • --git: Add .gitignore
  • -f--force: Force app generation on a nonempty directory

下面的步骤:

  1. 检查版本
  2. 执行scaffolding command with options
  3. run app locally
  4. 理解sections, routes, middleware, configuration
  5. 看一下Pug模版。(详细看Chapter3)

Express.js Command-Line Interface

$ express -c styl express-styl
//根据terminal上的提示:输入下面的代码,进入文件夹并安装相关依赖。
$ cd express-styl && npm install//运行app
$ DEBUG=express-styl:* npm start

创建了一个app,?!

进入express-styl/app.js:

const express = require('express');
const path = require('path');
const favicon = require('serve-favicon');
const logger = require('morgan');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const stylus = require('stylus');const index = require('./routes/index');
const users = require('./routes/users');let app = express();// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(stylus.middleware(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'public')));app.use('/', index);
app.use('/users', users);// 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 handler
app.use(function(err, req, res, next) {// set locals, only providing error in developmentres.locals.message = err.message;res.locals.error = req.app.get('env') === 'development' ? err : {};// render the error pageres.status(err.status || 500);res.render('error');
});module.exports = app;

server文件有routes, 来自routes文件夹。

Express app 被输出:module.exports

被发射伴随listen(),在bin/www文件内。

下面看一下app.js内的代码:

Routes in Express.js

可以在express-styl/app.js内看到自动生成的2个routes:

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');

//...

app.use('/', indexRouter);
app.use('/users', usersRouter);

第一行app.use():处理所有到home page的请求。如:http://localhost:3000/

第二行app.use():处理到/users,如http://localhost:3000/users.

2个routes处理URLs是大小写字母敏感的。

默认, Express.js不允许开发者通过query string arguments 来导航routes

GET: www.webapplog.com/books/?id=10&ref=201

而是,使用middleware:

app.use((req, res, next) => {next()
})

// next是一个回调函数。

开发者也可以完成response, 通过使用send(), end(), render()或其他Express method,

或者传递一个❌对象给next()来回调!

app.use((req, res, next) => {if (!req.session.loggedIN) { return next(new Error('Not enough permissions'))}if (req.session.credits === 0) {return res.render('not-enough-credits.pug')}next()
})

下面是另一个例子:

用条件逻辑来处理一个查询string, 使用req.query对象:

app.use((req, res, next) => {if (req.query.id) {//处理id,然后当完成后,调用next()} else if (req.query.author) {//和id相同的方式approach} else if (req.query.id && req.query.ref) {//当id and ref存在时,处理。} else {next()}
})app.get('/about', (req, res, next) => {//这里的代码,在query string middleware之后执行。
})

一个重要的特点:

只要request一样,每个req或者res对象在随后的中间件函数或者request handler functions内,req或res对象还是这个req or res对象。

req对象->中间件1函数->中间件2函数->请求处理函数->...->req对象(内部的key/value发生了变化)

这个特点,让开发者可以decorate a reference or a value。例如:

让第一个中间件的req对象得到数据库传入的数据,随后的第2个中间件中的req对象,就是第一个中间件执行完代码后的req对象, 这个req对象包含数据库数据。

(我的个人理解:类似Promise.then()链条传递的promise对象.)

app.use((req, res, next) => {req.db = const db = mongoskin.db('mongodb://@localhost:27017/test')
})
//在上一个中间件执行后,req对象新增了db属性。这个req对象被传入下一个中间件
app.use((req, res, next) => {req.articles =  req.db.collection('articles')
})
//上个中间件执行完成后,req对象又新增了articles属性。这个req对象被传入下一个中间件:
app.post('/users', (req, res, next) => { // use req.db or req.articlesreq.db.collection('users').insert({}, {}, (error, results)=>{req.articles.insert({}, {}, (error, results)=>{res.send()})})
})

回到app.js 文件。对root请求处理, 是"/",相当于routes/index.js。

来自HTTP request 的Everything 都在req对象内,并且把结果写入res对象。

在express-styl/routes文件夹,分别存在index.js和users.js,这2个文件导出后,会被app.js引入并使用。

var express = require('express')
var router = express.Router()// 得到home , res对象使用render()方法。
router.get('/', function(req,res, next) {res.render('index', {title: 'Express'})
})
module.exports = router

//users.js
var express = require('express');
var router = express.Router();/* GET users listing. */
router.get('/', function(req, res, next) {res.send('respond with a resource');
});module.exports = router;

Middleware as the Backbone

中间件是Express.js框架的支柱,脊梁骨。

在express-styl/app.js,每行/每个声明在routes上面,都是中间件。

这个中间件包括pass-through functions。当请求在中间件内旅行时,中间件会对请求request做有用或有帮助的事情。

const express = require('express');
const path = require('path');
const favicon = require('serve-favicon');
const logger = require('morgan');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const stylus = require('stylus');
//...
app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

例如:

bodyParser(), cookieParser() add HTTP request payload (req.body) 并 parsed cookie data(req.cookie)

app.use(logger('dev')),在terminal上打印每一个请求。

在Express v3, 这些中间件是内建的module。

在v4以后,Express Generator 声明和包含了app.js 和 package.json, 我们使用npm install来增加需要的modules。如:static-faviconmorgancookie-parser and body-parser.


Configuring an Express.js App

这是我们在一个典型的Express.js中的app.js内,定义配置声明。使用app.set()

第一个参数是名字,第二个参数是值。

app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');

在bin/www文件内:

 * Module dependencies.
var app = require('../app');
var debug = require('debug')('express-styl:server');
var http = require('http');

//Get port from environment and store in Express.
//定义port变量,并赋值。当server启动后,会被用到。
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);

创建http servervar server = http.createServer(app);

//监听提供的端口,并当error和listening事件,发生时执行onError, onListening回调函数。
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);

onError和onListening回调函数,定义在这个www文件内。


Pug Is Haml for Express.js/Node.js

Pug是一个模版引擎。类似Ruby on Rails的Haml。它使用whitespace和缩排列。

doctype html
htmlheadtitle= titlelink(rel='stylesheet', href='/stylesheets/style.css')bodyblock content

第4章会讲解它。(类似RoR的slim)可用可不用,每感觉效率提高多少,看开发团队是否用。


The Blog Project Overview

创建一个简单的blog页面,及相关功能。

  • home page, 一些文章
  • 独立的文章页面,全文显示一篇文章
  • 管理员页面,发布或移除。
  • 登陆页面,进入管理员页面。
  • post 页面,用于新增文章。

从一个开发者的视角,app有以下元素:

  • app.js主文件: Settings, routes, 其他重要的路径。 这个文件和node运行来开始server。
  • Routes: 所有的涉及页面的逻辑。如从数据库取数据,编译这些数据到HTML。
  • Node.js 文件package.json: 依赖和其他元数据。
  • 在mode_modules内的依赖: 第三方modules,(通过package.json安装的)
  • Database: 一个MongoDB实例,和一些seed data.
  • Templates: *.pug文件。
  • Static files: 如*.css,或者browser *.js
  • Configuration 文件config.json:安全设置,其他程序设置,如app的title.

这个程序包括所有的CRUD元素。另外使用两个方法发数据到server:

  1. 通过传统的form, 完全刷新页面。
  2. 通过REST API(AJAX HTTP request)

第一种是现代开发网页弃用的方式,速度太慢。

第2种是发送和接收数据,通过REST API/HTTP request和渲染客户端HTML。这些行为使用前端框架,例如React, Angular, Vue.js等等( many others (http://todomvc.com))。这些框架十分流行。

在hood罩子下面,事实上所有前端都使用jQuery's ajax()方法。

为了演示,本例子使用REST API通过$.ajax()。

同时,这个例子不使用CLI手脚架。逐步演示代码。如果创建一个Express.js。让你理解在这个框架下代码是如何组织在一起工作的。

开始把,创建我们的程序文件夹。

Express.js Hello World Example

一个例子,不使用generators, 额外的modules和middleware。包括以下部分:

  • 建立folders
  • npm init and package.json
  • Dependecy declaration
  • app.js 文件
  • Meet Pug
  • Running the app

第一步Setting Up Folders

Express.js是高度配置的,所有文件夹都可以重命名。不过,默认的文件夹不要改名:

  • node_modules:第三方 modules的代码放在这里。包括Express.js和Connect libraries。
  • views: 模版引擎文件Pug或其他。

这就够了。如果想要为之后的章节的其他案例创建新的文件夹,可创建:

  • routes: Node.js modules包括请求处理
  • db: 发送数据和scripts ,使用MongoDB
  • public: 所有静态的文件。包括HTML,CSS,JavaScript(browser), Stylus(或者其他的CSS语言框架文件)

创建文件夹hello-world

mkdir hello-world
cd hello-world
mkdir {public,public/css,public/img,public/js,db,views,views/includes,routes}

第二步npm init and package.json

上一步,没有使用Express.js Generator。

npm不仅是一个注册器,也是一个依赖管理工具。它永久建立程序文件package.json。

npm init   //创建package.json

$ npm install express //安装最新的稳定版本。

⚠️推荐使用明确的指定版本,使用@符号。

npm install express@4.15.4 --save

再安装

  • Pug: 2.0.0-rc.4
  • Stylus: 0.54.5

第三步Dependency Declaration: npm install

另一个创建package.json文件的方法是拷贝粘贴代码到package.json, 然后运行npm install

对脚本进行修改:如⬇️所见:

{{"name": "hello-advanced","version": "0.0.1","private": true,"scripts": {"start": "node app.js"},"dependencies": {"express": "4.15.4","pug": "2.0.0-rc.4"}
}

main entry point,即设定一个主文件main file:

一般使用app.js或者index.js, 执行这个脚本文件使用以下随意的一个:

$ node app.js
$ node app
$ npm start   

//因为在package.json内设定了"scripts": { "start": "node app.js"}

下一步,让我们创建app.js

第四步The App.js File

主文件的结构基本内容包括:

  1. Require dependencies
  2. Configure settings
  3. Connect to database(可选)
  4. Define middleware
  5. Define routes
  6. Start the server on a particular port
  7. Start workers with clusters to scale (a term spawn workers is also used for this) (optional)

1到7的顺序很重要,因为请求从上到下的经过中间件的链条。


打开app.js,然后:

//引入模块。
// path module 用于处理文件和目录的路径。
const express = require('express')
const http = require('http')
const path = require('path')
// Express使用一个函数模式,执行函数,得到一个实例。
let app = express();

// 使用express实例方法set('name', 'value')来进行配置
app.set('appName', 'hello-advanced')

还需要定义一些配置在app.js:

  • port: 端口,是一个number, server会监听请求。
  • views:template文件的绝对路径。
  • view engine:  模版文件的扩展(html, pug)

如果想要使用环境变量提供的port number,使用模块process的方法:

process.env.PORT

代码如下:

app.set('port', process.env.PORT || 3000)
app.set('views', path.join(_dirname, 'views'))
app.set('view engine', 'html')

__dirname

is an absolute path to the folder with the source code script (a file in which the global variable is called). 得到程序代码所在的文件夹。

本application是"/Users/chen/node_practice/hello-world"

//如何查询
node inspect app.js
//然后在控制台输入__dirname,即可返回路径

path.join([...paths])是path模块的方法之一

// ..返回上一个文件夹
path.join('/foo', 'bar', 'baz/asdf', 'quux', '..');
// Returns: '/foo/bar/baz/asdf'

然后,进入中间件 部分。

中间件是Express.js框架的backbone。

它包括:

  • 在第三方模块内的定义。例如:app.use(bodyParser.join());  这是body-parser模块的方法。
  • 在app或它的模块内的定义。 例如:app.use(function(req, res, next) { ... })

Middleware用于组织和复用代码,本质就是带参数的函数。(第6章会做更多的讲解)

routes

下一个组件是routes。Routes处理requests。定义路径使用帮助方法app.VERB(url, fn1, fn2, ...)

fn:request handlers

url:是URL pattern in RegExp

VERB:是get , post, put, patch, del, all, 用于捕捉不同的请求。

Routes按它们被定义的顺序,被处理。一般routes被放在middleware后面,但是一些中间件放在routes后面。例如error handler。

下图展示一个请求的旅行:

在本app Hello World, 只使用一个route,来得到所有关于URLs的方法的请求(*通配符号wildcard百搭牌)

app.all('*', (req, res) => {res.render('index', {msg: 'Welcome to Practical Note.js!'})
})

在这个请求内,使用res.render()函数渲染视图模版。res.render()的第一个参数是名字'index', 第二个参数是数据对象data object。

res.render(viewName, data, callback(error, html))

express的方法。

  • viewName: 模版名字及扩展名(file extension)
  • data: 一个可选的对象被传入,(从数据库取出的数据)
  • callback: 一个可选的函数被调用,用于处理an error and HTML当compilation is complete。

render()方法调用后,调用core http组件的end()方法,用于完成response。

换言之,中间件的链条不会在res.render()后继续执行代码。

(第4章,详细分析)

最后但不是最少的是开启服务的说明。在之前的章节的Hello World app, 你看到app.listen(),

但是http.createServer(app).listen()也可以生效。这2个连接的方法都是核心模块http的方法。

server.listen()

监听连接。

http.createServer(app).listen(app.get('port'), () => {console.log(`Express server listening on port ${app.get('port')}`)
})

你也可以使用https.createServer(app).listen() for the HTTPS support, 当你准备好部署你的server到产品。

在运行server之前,我们需要创建views/index.html文件

创建index视图文件

Express默认使用jade模版,也可以自定义如Pug,

如果想使用原生html模版,需要安装ejs (点击查看原文解释)

npm install ejs//引入ejs
var ejs = require('ejs')//设置html engine
app.engine('html', ejs.__express)//设置视图引擎, 'view engine'表示没有指定文件模版格式时,默认使用的引擎插件。
app.set('view engine', 'html')

:在express搭建的服务器中,html引擎没有被配置,直接添加即可;视图引擎已配置,修改配置即可。

index.html内的代码:

<h1>hello</h1>
<p>You are welcome</p>// 插入传入模版的数据。
<p><%= msg %></p>

app.engine(ext, callback)

http://expressjs.com/en/4x/api.html#app.engine

Registers the given template engine callback as ext.

默认,Express将require()这个基于文件扩展的engine。

app.engine('pug', require('pug').__express);
app.engine('html', require('ejs').renderFile); //也可以用__express方法

Running the Hello World App

$ node app 

打开http://localhost:3000.

总结:

第2章,学习使用Express.js, 知道它是如何工作的。了解使用手脚架来生成apps。

通过Blog app案例,了解了创建这个程序的过程。

最后,我们接触了一些主题:settings, request process, routes, Ajax server side, ejs模块产生模版。

下一章,谈谈驱动测试开发。另外会增加一个数据库到Blog routes。展示如何把数据转入到HTML pages!

转载于:https://www.cnblogs.com/chentianwei/p/10247959.html

Practical Node.js摘录(2018版)第1,2章。相关推荐

  1. Node.js v7 Beta版引入citgm

    Node.js基金会发布了Node.js v7 Beta版.该版本的发布恰逢v6成为该基金会的第二个LTS版本.在2019年4月份之前,v6版本将可以一直得到积极的技术支持和维护. \\ Node.j ...

  2. 华为 Mate 40 系列搭载麒麟 9000 芯片;短视频平台 Quibi 宣布关闭;Node.js 15 正式版发布|极客头条

    整理 | 郑丽媛 头图 | CSDN 下载自东方 IC 「极客头条」-- 技术人员的新闻圈! CSDN 的读者朋友们早上好哇,「极客头条」来啦,快来看今天都有哪些值得我们技术人关注的重要新闻吧. 国内 ...

  3. node.js在2018年能继续火起来吗?我们来看看node.js的待遇情况

    你知道node.js是怎么火起来的吗?你知道node.js现在的平均工资是多少吗?你知道node.js在2018年还能继续火吗?都不知道?那就来看文章吧,多学点node.js,说不定以后的你工资就会高 ...

  4. [Node.js月刊]2018年第1期

    为精华而生.Mybridge AI筛选10篇好文 本期关键字:微服务.人脸识别.全文本检索.性能基准.无服务Rest API.twitter机器人.NestJS.Buffer 2018年微服务疯狂之死 ...

  5. Node.js 15 正式版发布

    前两天,Node.js官方发布了Node.js 15的正式版本,Node.js 15 将替代 Node.js 14 成为当前的的稳定发行版,后者将在本月晚些时候升级为 LTS(长期支持)版本.如果大家 ...

  6. Node.js 15正式版发布

    英文 | https ://medium.com/@nodejs/node-js-v15-0-0-is-here-deb00750f278 前两天,Node.js官方发布了Node.js 15的正式版 ...

  7. java和node.js 2018_node.js在2018年能继续火起来吗?我们来看看node.js的待遇情况

    你知道node.js是怎么火起来的吗?你知道node.js现在的平均工资是多少吗?你知道node.js在2018年还能继续火吗?都不知道?那就来看文章吧,多学点node.js,说不定以后的你工资就会高 ...

  8. node.js基于JavaScript网上商城毕业设计源码261620

    Node.js网上商城的开发 摘  要 随着Internet的使用越来越广泛,在传统的商业模式中,对于日常各类商品,人们习惯于到各种商家店铺购买.然而在快节奏的新时代中,人们不一定能为购买各类商品腾出 ...

  9. (附源码)node.js华联招聘网站011229

    华联招聘网站 摘 要 随着科学技术的飞速发展,社会的方方面面.各行各业都在努力与现代的先进技术接轨,通过科技手段来提高自身的优势,招聘网站当然也不能排除在外.招聘网站是以实际运用为开发背景,运用软件工 ...

  10. (附源码)node.js华联招聘网站 毕业设计 011229

    华联招聘网站 摘 要 随着科学技术的飞速发展,社会的方方面面.各行各业都在努力与现代的先进技术接轨,通过科技手段来提高自身的优势,招聘网站当然也不能排除在外.招聘网站是以实际运用为开发背景,运用软件工 ...

最新文章

  1. R语言中使用pkgbuild::find_rtools查看是否有Rtools、使用Sys.which函数查看make是否存在、如果没有则安装、使用writeLines函数绑定R和Rtools
  2. 微型计算机中PRON是,英语词性英语中的pron指的是什么词性?? – 手机爱问
  3. a href=#与 a href=javascript:void(0) 的差别
  4. mysql中find_in_set_mysql中find_in_set()函数的使用详解
  5. Android char数据类型乱码��解决方法
  6. 参与势力战是不可多得的zhajinhua2012
  7. PHP文字转语音合成网源码 百度API开发
  8. Express-static
  9. httpd的三种模式比较
  10. install intel c/c++ compiler
  11. 设置时间同步(ntp)详细步骤
  12. 素数筛(快速筛)-爱拉托斯特尼筛法+欧拉筛
  13. 小升初数学计算机考试题,重点中学小升初数学分班考试模拟试卷试题及解析总结计划-20210513100212.docx-原创力文档...
  14. 多多农场游戏源码果园种植+养殖游戏 对接广告联盟APP+小程序
  15. 网络编程资源大集合(包含前端、java、linux、安卓、github开源项目、开发工具等)
  16. 校园宽带破解---解救断网之际
  17. Kindle下载字典
  18. trajan割点模板
  19. 沃尔玛经典营销案例:啤酒与尿布
  20. python中私有属性无法访问的原理_python私有属性访问不到吗?

热门文章

  1. 年轻人,在公司混日子,伤害的是自己!
  2. 滴滴出行高并发高性能的分布式架构设计之道
  3. 最全 MySQL 优化方法,从此优化不再难
  4. 微型计算机的软件系统分为哪几类,系统软件分为哪几类?各有什么特点?
  5. 大数据数学基础 python描述下载_正版 大数据数学基础(Python语言描述)Python 大数据 数学 高职-计算机-大数据技术...
  6. shell应用之简单计算器
  7. (转载)用C#实现MySQL建库及建表
  8. bzoj1612 奶牛的比赛
  9. 【自动化__持续集成】___java___代码非空指针
  10. 教学思路SQL之入门习题《学员成绩》 二、基础单表查询