express.js的

  • Node.js 《Node.js 官網(中文)》
  • Node.js 《Node.js 官網(英文)》

<br/><br/>

Node.js 是什麼

Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient. Node.js' package ecosystem, npm, is the largest ecosystem of open source libraries in the world.
1. JavaScript 運行時
2. 既不是語言,也不是框架,它是一個平臺

Node.js 中的 JavaScript

1. 沒有 BOM、DOM
2. 在 Node 中爲 JavaScript 提供了一些服務器級別的 API
    2.1 fs 文件操作模塊
    2.2 http 網絡服務構建模塊
    2.3 os 操作系統信息模塊
    2.4 path 路徑處理模塊
    2.5 .....

<!-- markdown-to-slides share1.md -o index.html -s slide.css -->

I. express簡介

基於 Node.js 平臺,快速、開放、極簡的 Web 開發框架

簡單來說,封裝了node中http核心模塊,專注於業務邏輯的開發。

安裝方法


npm install express --save

koa

Koa - next generation web framework for node.js

Koa 是一個新的 web 框架,由 Express 幕後的原班人馬打造, 致力於成爲 web 應用和 API 開發領域中的一個更小、更富有表現力、更健壯的基石。 通過利用 async 函數,Koa 幫你丟棄回調函數,並有力地增強錯誤處理。 Koa 並沒有捆綁任何中間件, 而是提供了一套優雅的方法,幫助您快速而愉快地編寫服務端應用程序。(project:koa-1.js)

const Koa = require('koa');
const app = new Koa();

app.use(async ctx => {
  ctx.body = 'Hello World';
});

app.listen(3000);

<img src="http://img0.ph.126.net/77JLQd...; />


Hello XXX (node)


var http = require('http')

http.createServer(function (req, res) {
  // 主頁
  if (req.url == "/") {
    res.end("Holle hemo!");
  }

  // About頁
  else if (req.url == "/about") {
    res.end("Hello about!");
  }

}).listen('3009', 'localhost', function () {
  console.log('listen 3009 ....')
})

project:demo-1.js Hello XXX 測試結果:

<img src="http://img2.ph.126.net/oE0IH7...; height="200" width="600" />


Hello XXX (express)


var express = require('express')
var app = express()

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

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

app.listen(3000, function () {
  console.log('express app is runing .....')
})

project:demo-2.js Hello XXX 測試結果:

<img src="http://img1.ph.126.net/py2gHZ...; height="200" width="600" />


express 路由

Routing refers to how an application’s endpoints (URIs) respond to client requests.

-請求方法

-請求路徑

-請求處理函數

公開靜態資源


// 訪問路徑 http://127.0.0.1:3000/a.js
app.use(express.static('./public/'))

// 訪問路徑 http://127.0.0.1:3000/public/a.js
app.use('/public/',express.static('./public/'))

require 方法的加載規則

-深入淺出 node.js

node 中存在的模塊主要有:

  1. 核心模塊 path fs http ...
  2. 自己定義的模塊 (路徑形式的模塊)
  3. 第三方模塊 art-template express(使用npm安裝的模塊)

// 加載核心模塊
const path = require('path');

// 加載自定義模塊
const foo = require('./fooo.js')

// 加載第三方模塊 node_modules
const express = require('express')

node 中require加載規則:

  1. 優先緩存加載
  2. 判斷模塊標識

    2.1 是否是核心模塊 http 、fs 加載 緩存 export

    2.2 是否是文件模塊 ./foo.js 加載 緩存 export

    2.3 是否是第三方模塊 (第三方模塊需要 npm install 安裝)

    - node_modules/art-template/
    - node_modules/art-template/package.json
    - node_modules/art-template/package.json 中找main 作爲文件加載入口
    - index.js 備選項
    - 進入上一級目錄找 node_modules
    - 按照此規則依次向上查找,直到磁盤根目錄找不到 報錯 Can not find moudle XXX
    

node 中require加載規則:

<img src="http://img1.ph.126.net/rbUZEF...; height="540" width="300" />
<img src="http://img2.ph.126.net/h8Kc7e...; height="540" width="400" style="margin-left:60px"/>


nodemon

nodemon《nodemon使用方法》

nodemon reload, automatically

nodemon用來監視node.js應用程序中的任何更改並自動重啓服務,非常適合用在開發環境中


// 全局安裝nodemon
npm install -g nodemon

nodemon app.js

中間件 body-parser

express中沒有內置的獲取表單請求體的API,所以需要第三方包解析HTTP請求體

This module provides the following parsers:

  1. JSON body parser
  2. Raw body parser
  3. Text body parser
  4. URL-encoded form body parser

使用方法:


const bodyParser = require('body-parser');
const app = express();

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});

router.post('/students/new', function (req, res) {
  console.log(req.body)
  Student.save(req.body, function (err) {
    if (err) {
      return res.status(500).send('Server error.')
    }
    res.redirect('/students')
  })
})

post 提交方式測試:

<img src="http://img1.ph.126.net/82CmNm...; width="350" />
<img src="http://img1.ph.126.net/wSMCvy...; width="350" style="margin-left:40px"/>


package-lock.json

npm 5以前沒有 package-lock.json 文件

  1. 安裝包時不需要加 --save參數 會自動保存依賴信息
  2. 在安裝包時,會自動更新package-lock.json文件
  3. package-lock.json文件保存node_molules中所有包信息(記錄版本號和下載地址等信息)

path 路徑操作模塊


path.join(__dirname, '../node_modules')

path.basename(path[, ext])

<img src="http://img2.ph.126.net/MgfYCw...; />


node 中的其他成員

在每個模塊中,除了require、export 等模塊相關的API之外,還有兩個特殊的成員

  • __dirname 可以用來獲取當前文件模塊所屬目錄的絕對路徑 動態獲取
  • __filename 可以用來獲取當前文件的絕對路徑 動態獲取

1. 在文件操作路徑中,相對路徑設計的是相對於執行node命令所在路徑
2. 模塊中的路徑標識就是相對於當前文件模塊,不受執行node命令所處路徑影響

const fs = require('fs')
const path = require('path')

// 文件操作中的相對路徑
fs.readFile('c:/a/b/a.txt', 'utf-8', function (err, data) {
  if (err) throw err
  console.log(data)
})

// 文件操作中的相對路徑轉化爲動態獲取的絕對路徑
fs.readFile(path.join(__dirname,'./a.txt'), 'utf-8', function (err, data) {
})

// 模塊中的路徑標識
require('./b')

II. Express 中間件

中間件(middleware) 在 Node.js 中被廣泛使用,它泛指一種特定的設計模式、一系列的處理單元、過濾器和處理程序,以函數的形式存在,連接在一起,形成一個異步隊列,來完成對任何數據的預處理和後處理。

常規的中間件模式

<img src="https://upload-images.jianshu...; />


express 中間件

express 中間件

Middleware functions are functions that have access to the request object (req), the response object (res), and the next function in the application’s request-response cycle.

中間件的本質就是請求處理方法,把用戶從請求到響應的整個過程分發到多箇中間件中去處理,提高代碼靈活性,動態可擴展

<img src="https://timgsa.baidu.com/timg...;quality=80&size=b9999_10000&sec=1542863886302&di=8c2650a2389ce7e21e5afcf63739266a&imgtype=0&src=http%3A%2F%2Fresupload.xueda.com%2Fupload%2F55ee1c9f-971f-4e88-a708-666a1459c388%2FkX159dhLPTXl.gif" />


中間件的使用

var express = require('express')
var app = express()
var myLogger = function (req, res, next) {
  console.log('LOGGED')
  next()
  console.log('After LOGGED')
}
var myLogger2 = function (req, res, next) {
  console.log('LOGGED2')
  next();
  console.log('After LOGGED2')
}
app.use(myLogger)
app.use(myLogger2)
app.listen(3000, function () {
  console.log('express app is runing .....')
})

project:demo-3.js 運行結果如下:
<img src="http://img0.ph.126.net/RJXU-z...; />


實現中間件機制

function express() {

  var taskArrray = []
  var app = function (req, res) {

    var i = 0
    function next() {
      var task = taskArrray[i++]
      if (!task) {
        return;
      }
      task(req, res, next);
    }
    next();
  }
  // 將中間件存入數組中
  app.use = function (task) {
    taskArrray.push(task)
  }

  return app;
}

project:demo-4.js


實現中間件機制測試結果

var http = require('http')
var app = express();
http.createServer(app).listen('3000', function () {
    console.log('listening 3000....');
});
var myLogger = function (req, res, next) {
  console.log('LOGGED')
  next()
  console.log('After LOGGED')
}
var myLogger2 = function (req, res, next) {
  console.log('LOGGED2')
  next();
  console.log('After LOGGED2')
}
app.use(myLogger)
app.use(myLogger2)

<img src="http://img0.ph.126.net/RJXU-z...; />


express 中間件分類

應用層級別中間件

  • 不關心請求路徑和請求方法的中間件,任何請求都會執行
  • 關心請求路徑的中間件

路由級別中間件

  • 不關心請求路徑和請求方法的中間件,任何請求都會執行
  • 嚴格匹配請求方法和請求路徑的中間件

錯誤處理中間件

  • 404頁面 全局錯誤頁面

內置中間件

  • express.static

第三方中間件

  • body-parser
  • cookie-session

使用express 中間件

project:demo-5.js

// 不關心請求路徑和請求方法的中間件
app.use(function (req, res, next) {
  console.log('all request must execute!!')
  next()
})

app.use(function (req, res, next) {
  console.log('all request must execute 1 !!')
})

// 以/XXX 開頭的路徑的中間件
app.use('/user/:id', function (req, res, next) {
  console.log('Request URL:', req.originalUrl)
  next()
}, function (req, res, next) {
  console.log('Request Type:', req.method)
  next()
})

// 嚴格匹配請求方法和請求路徑的中間件
app.get('/aa/bb', function (req, res, next) {
  console.log('/aa/bb')
  next()
})

使用express 中間件

// 內置中間件
app.use('/public/', express.static('./public/'))

// 所有都匹配不到時 404 (放在最後)
app.use('/', router)
app.use(function (req, res, next) {
  res.send('This is 404 !!!!!')
})

// 配置全局錯誤統一處理中間件
app.get('/aa/bb', function (req, res, next) {
  fs.readFile('c:/a/b/index.js', 'utf-8', function (err) {
    if (err) return next(err)
  })
})

app.use(function (err, req, res, next) {
  res.status(500).json({
    err_code: 500,
    err_msg: err.message
  })
})

// 第三方級別中間件
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

III. Express Generator

通過應用生成器工具 express-generator 可以快速創建一個應用的骨架。

npm install express-generator -g
express myapp --view=pug
cd myapp
npm install
npm run start

project:myapp 訪問http://localhost:3000/

<img src="http://img2.ph.126.net/Hdg8CX...; />


目錄結構與代碼

1.查看myapp目錄結構

2.結合中間件分析代碼

project: myapp

<img src="http://img1.ph.126.net/KyJ0a3...; height="580px" style="margin-left:400px;margin-top:-160px"/>


相關中間件

morgan

HTTP request logger middleware for node.js

pug

Pug is a high performance template engine heavily influenced by Haml and implemented with JavaScript for Node.js and browsers. For bug reports, feature requests and questions, open an issue. For discussion join the chat room.
h1 Pug - node template engine
<h1>Pug - node template engine</h1>
// compile
var fn = pug.compile('string of pug', options);
var html = fn(locals);
 
// render
var html = pug.render('string of pug', merge(options, locals));

IV. express 在vue項目中模擬接口

結合ccs-operation-web中 模擬接口 ./api/server.js

<img src="http://img1.ph.126.net/WcCZiU...; />

project:app.js


<img src="http://img2.ph.126.net/ODW9rX...; />
<img src="http://img1.ph.126.net/BPnIoG...; />


運行express服務器

"scripts": {
    "server": "nodemon api/server.js",
    "dev": "webpack-dev-server --inline --progress --open --config build/webpack.dev.conf.js",
    // 影響ccs-operation-web/config/proxyConfig.js http://localhost:3002/api/listContracts?pin=X&all=X
    "devlocal": "shell-exec --colored-output \"npm run dev --local\" \"npm run server\"",
  }

shell-executor

A small nodejs module to execute shell commands in parallel
npm i -g shell-executor
// --colored-output  Use colored output in logs
shell-exec --colored-output 'npm run lint' 'npm run test' 'npm run watch'

ccs-operation-web ./api/server.js

const express = require('express');
const bodyParser = require('body-parser');
const request = require('request');
const path = require('path');
const walk = require('klaw-sync');

const {
    origin_proxy_url,
    local_proxy_port,
    local_proxy_url
} = require('../config/proxyConfig');

const app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});

let _existRoutes = [];


app.use( (req, res, next)=>{ 
    const {url, body, method} = req;
    if (!~_existRoutes.indexOf(req.path)) {    
        const rurl = origin_proxy_url.replace(/\/$/, '') + url;
        let r = method === 'POST'
            ? request.post({url: rurl, form: body}, (err, httpRes, reqBody)=>{
                console.log(err, reqBody, body)
            })
            : request(rurl);
        console.log(`本地未定義的請求,跳轉到 ${method} ${rurl}`);
        req.pipe(r).pipe(res);
        return;
    }
    next();
});

//遍歷本目錄下的 *.api.js
walk(path.resolve('./'))
    .filter(p=>/\.api\.js$/.test(p.path))
    .map(p=>p.path)
    .forEach(part=>require(part)(app));

//記錄註冊過的路由
_existRoutes = app._router.stack.filter(s=>s.route).map(s=>s.route.path);

app.listen(local_proxy_port, ()=>{
    console.log(`\n\n local server running at ${local_proxy_url} \n\n`);
});

klaw-sync

klaw-sync is a Node.js recursive and fast file system walker
// 用法
const klawSync = require('klaw-sync')
const paths = klawSync('/some/dir')
// paths = [{path: '/some/dir/dir1', stats: {}}, {path: '/some/dir/file1', stats: {}}]

<img src="http://img1.ph.126.net/O9u0y_...; />


request

Request - Simplified HTTP client
// 用法
npm install request

var request = require('request');
request('http://www.google.com', function (error, response, body) {
  console.log('error:', error); 
  console.log('statusCode:', response && response.statusCode);
  console.log('body:', body);
});

req.pipe(request('http://mysite.com/doodle.png')).pipe(resp)

<img src="http://img1.ph.126.net/B5PvG3...; />


VI. 總結

express 基於 Node.js 平臺,快速、開放、極簡的 Web 開發框架

簡單來說,封裝了node中http核心模塊,專注於業務邏輯的開發。

express 核心內容 : 理解、使用中間件

express 源碼學習 路由
express 中間件原理


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章