Node學習筆記

前情提要

  • 本篇博客整理內容都是本人在學習node過程中所遇到重要知識點,作用如下:
    • 爲初學者整理出學習node過程中會遇到的知識點,有針對性的快速定位知識點
    • 方便有基礎者快速查找重點知識,回憶不清晰的知識點

開發環境

Node 6.9.1
Express 4.15.3
Mongoose 4.10.5
Window 10
ubuntu 16.04(服務器環境)

要點整理

全局安裝npm包目錄(如:cnpm install xxx -g)

  • C:\Users\Think\AppData\Roaming\npm\node_modules(本人電腦)

Node 版本切換

  • 安裝過n和nvmw,出現過各種各樣的問題,都沒有實現正常切換node版本的目的
  • 最後在淘寶鏡像下載多個node版本(下載壓縮包,這樣可以共存多個版本),手動的改變環境變量,來達到切換node版本的目的
  • 阿里雲購買的服務器(linux版本:ubuntu 16.04)上安裝nvm成功

Windows下通過nvmw安裝NodeJS v4.4.0的問題及解決辦法

telnet 命令必須在cmd中才能生效

Win10正式版telnet不是內部或外部命令怎麼辦 [1]

Content-Length 設置

  • var http = require('http');
    
    var server = http.createServer(function(req, res) {
        var body = '你好';
        res.writeHead(200, {
            'Content-Type': 'text/plain;charset=utf8',
            'Content-Length': Buffer.byteLength(body),// 這個值可以<=Buffer.byteLength(body)
        })
        res.end(body);
    })
    
    server.listen(3000, function() {
        console.log('server...')
    })

curl 命令

  • 使用 git bash 可以直接運行 curl 命令
  • curl -X DELETE 127.0.0.1:3000 表示發送一個刪除請求

curl命令詳解

表單提交模擬 REST 架構

> [REST架構中的PUT、DELETE請求如何實現?](https://segmentfault.com/q/1010000000123615)
> [AJAX如何實現PUT和DELETE方法](https://segmentfault.com/q/1010000002581227)
> [method-override(改寫前端form表單的請求)](https://github.com/expressjs/method-override)

Buffer.from() 在 node6.x 中才能使用

Getting TypeError: this is not a typed array using Buffer.from in mocha

參數解析

  • req.body

    • 表單提交的數據
    • 服務端

      ...
      var bodyParser = require('body-parser')
      app.use(bodyParser.json())
      ...
      
      app.all('/list', function(req, res, next) {
          console.log(req.body)
      })
    • 客戶端(下例使用FormData提交數據,或者你可以使用原生表單submit提交,不推薦)

      var formData = new FormData();
      formData.append('id', 1);
      
      $.ajax({
          type: 'post',
          url: '/list',
          data: formData,
          contentType: false,
          processData: false,
      })
  • req.query

    • url中?後面帶的參數
    • 服務端

      app.all('/list', function(req, res, next) {
          console.log(req.query)
      })
    • 客戶端

      $.ajax({
          url: '/list?id=1',
      })
  • req.params

    • rest風格時,url中路徑參數
    • 服務端

      app.get('/list/:id', function(req, res, next) {
          console.log(req.params)
      })
    • 客戶端

      $.ajax({
          url: '/list/1',
      })
  • req.files

    • 表單提交的數據()
    • 服務端

      ...
      var multer = require('multer')
      var upload = multer({dest: './uploads'})
      ...
      
      app.all('/add', upload.fields([
              {name: 'file'},
          ]), function(req, res, next) {
          console.log(req.files)
      })
    • 客戶端(下例使用FormData提交數據,或者你可以使用原生表單submit提交,不推薦)

      var formData = new FormData();
      formData.append('file', document.querySelector('[type=file]').files[0]);
      
      $.ajax({
          type: 'post',
          url: '/add',
          data: formData,
          contentType: false,
          processData: false,
      })

解析url參數 querystring.parse(url.parse(req.url).query)

process.env.NODE_ENV

  • cmd 中 SET NODE_ENV=prod
  • git bash 中
    • 直接運行NODE_ENV=prod node app
    • 或者先運行export NODE_ENV=prod,再運行node app

process.env.NODE_ENV is undefined

connect 中間件

  • 常規處理中間件函數有3個參數:req、res、next,錯誤處理中間件函數必須接收4個參數:err、req、res、next
  • 調用next()的時候,如果向裏面傳遞參數,如:next(new Error('not found')),那麼它接下來會自動尋找錯誤處理中間件
  • 以下中間件都獨立於connect本身
    • cnpm install cookie-parser –save
    • cnpm install body-parser –save
  • connect.limit中間件已經整合到body-parser中
var express = require('express')
var cookieParser = require('cookie-parser')
var moment = require('moment')

var app = express()

app.use(cookieParser('sign'))// 設置簽名標記

app.all('/', function(req, res) {
    res.cookie('name', 'hvb', {
        expires: new Date(moment().add(30, 's')),
        httpOnly: true,// 僅服務端可訪問
    })
    res.cookie('sex', 'male', {signed: true})// 設置簽名的cookie(簽名≠加密,爲了檢驗客戶端cookie是否僞造,以上不設置簽名標記,這裏就會報錯)
    res.cookie('obj', {a: 1, b: 2})// cookie內容爲對象
    res.send({message: '/'})
})

app.all('/get', function(req, res) {
    console.log(req.cookies)// 獲取所有普通cookie
    console.log(req.signedCookies)// 獲取所有簽名cookie
    res.send({message: '/get'})
})

app.all('/del', function(req, res) {
    res.clearCookie('name')// 刪除cookie,對httpOnly爲true的cookie也會生效
    res.send({message: '/get'})
})
...

加密、摘要和簽名的區別
express中cookie的使用和cookie-parser的解讀
cookie 和 session

npm模塊-bcryptjs(密碼加密)

  • 建議安裝密碼加密模塊時,不要選用bcrypt模塊(安裝依賴問題比較多),使用bcryptjs模塊即可(API跟bcrypt是一樣的,而且不會出現問題)

nodejs中常用加密算法
用戶密碼以BCrypt加密的方式來防範被破解
密碼破解
md5密碼加鹽
bcryptjs

使用connect-mongo將session存儲到數據庫

  • 一定要注意如果有2個接口都需要寫入session到數據庫,那麼這2個接口在前端千萬不能同時請求,否則,後面的會完全覆蓋前面的session,如下圖:
    • app.js
      這裏寫圖片描述
    • 數據庫數據:
      這裏寫圖片描述
var express = require('express')
var mongoose = require('mongoose')
var session = require('express-session')
var MongoStore = require('connect-mongo')(session)

mongoose.connect('127.0.0.1:27017/foobar')

var app = express()

app.use(session({
    secret: 'sessiontest',
    resave: true,
    saveUninitialized:true,
    store: new MongoStore({
        mongooseConnection: mongoose.connection,
        ttl: 10,// 表示10秒鐘後該session過期,如果不設置session過期時間默認爲2周(如果關閉了瀏覽器,那麼該session會立即失效,也就說打開瀏覽器還需要再次登錄,但是數據庫的相應字段不會被立即刪除,如果想實現自動登錄,那麼需要藉助cookie來實現)
    })
}))

// 存儲session
app.get('/', function(req, res) {
    // 這裏存儲session(具體值)到數據庫,可以打開數據庫查看(客戶端是以cookie的方式來存儲session(唯一id),字段爲connect.sid)
    req.session.user = {
        a: 1,
        b: 2,
    }
    res.send({message: '/'})
})

// 查看session
app.get('/a', function(req, res) {
    console.log(req.session)// 將在這裏輸出之前存儲的session,或者可以打開數據庫查看
    res.send({message: '/a'})
})
...

Session會在瀏覽器關閉後消失嗎?
nodesj中 中間件express-session的理解
connect-mongo和mongoose的區別聯繫
connect-mongo

自動登錄

網站的下次自動登錄功能的實現方法

npm模塊-serve-favicon(設置網站圖標)

var express = require('express')
var favicon = require('serve-favicon')
var path = require('path')

var app = express()

app.use(favicon(path.join(__dirname, 'public', 'dog.png')))// 後綴名可以不是ico且設置之後要重啓瀏覽器才能生效
...

npm模塊-morgan(請求日誌)

var express = require('express')
var moment = require('moment')
var morgan = require('morgan')
var uuid = require('uuid')// node-uuid已合併爲uuid
var path = require('path')
var fs = require('fs')

var app = express()

// 添加唯一標識
morgan.token('id', function(req) {
    return req.id
})
function assignId (req, res, next) {
    req.id = uuid.v4()
    next()
}

// 自定義時間格式
morgan.token('date', function(req) {
    return req.date
})
function assignDate (req, res, next) {
    req.date = moment().format('YYYY-MM-DD HH:mm:ss')// 2017-06-16 17:43:24 
    next()
}

// 創建可寫流
var testLogStream = fs.createWriteStream(path.join(__dirname, 'test.log'))

app.use(assignId)
app.use(assignDate)
app.use(morgan(':id :method :url :response-time ms :date\\r', {stream: testLogStream}))// 以自定義的格式寫入到test.log,結尾換行
...

Express的日誌模塊morgan
Java寫到.txt文件,如何實現換行
生成唯一標識 uuid

npm模塊-compression(gzip)

  • 圖片使用gzip後體積反而會變大,所以compression沒有對圖片進行壓縮

npm模塊-csurf(防止csrf攻擊)

  • server.js

    var express = require('express')
    var cookieParser = require('cookie-parser')
    var bodyParser = require('body-parser')
    var csrf = require('csurf')
    
    var app = express()
    
    app.set('views', './views')
    app.set('view engine', 'ejs')
    
    app.use(express.static('./public'))
    app.use(bodyParser.urlencoded({ extended: false }))
    app.use(cookieParser())
    app.use(csrf({
        cookie: true,
        //ignoreMethods: ['GET', 'HEAD', 'OPTIONS'],// 以上3種方法默認不會進行安全驗證,所以注意不要把更新、刪除操作使用get請求接收
    }))
    // 自定義錯誤信息
    app.use(function (err, req, res, next) {
      if (err.code !== 'EBADCSRFTOKEN') return next(err)
    
      res.status(403)
      res.send({message: '非法請求'})
    })
    
    // 渲染模板
    app.all('/', function (req, res) {
      res.render('nav', {csrfToken: req.csrfToken()})
    })
    // 默認不對get請求進行驗證,所以即使客戶端傳來錯誤的_csrf,也會成功返回
    app.get('/a', function (req, res) {
        res.send({message: '/a'})
    })
    // 會進行驗證
    app.post('/b', function (req, res) {
        res.send({message: '/b'})
    })
    ...
  • test.ejs

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>test</title>
        <script src="js/jquery-1.11.3.min.js"></script>
    </head>
    <body>
        <form>
            <input type="hidden" name="_csrf" value="<%= csrfToken %>2321312312">
            <input type="text" name="username">
        </form>
        <button class="get">get請求</button>
        <button class="post">post請求</button>
    </body>
    <script>
    $(function() {
        // 發送get請求
        $('.get').on('click', function() {
            $.ajax({
                url: '/a',
                data: $("form").serialize(),
            })
        })
        // 發送post請求
        $('.post').on('click', function() {
            $.ajax({
                url: '/b',
                data: $("form").serialize(),
                type: 'post',
            })
        })
    })
    </script>
    </html>
    

淺談CSRF攻擊方式
npm模塊csurf(防止csrf攻擊)
爲什麼http用的時候不能用POST方式替代全部的GET方式?

npm模塊-serve-index(生成靜態資源目錄)

var express = require('express')
var serveIndex = require('serve-index')

var app = express()

app.use('/dir', express.static('./public'))// 託管靜態資源
app.use('/dir', serveIndex('./public', {'icons': true}))// 生成靜態資源目錄

app.all('/', function (req, res) {
  res.send({message: '/'})
})

app.listen(3000, function() {
    console.log('server...')
})

客戶端訪問http://127.0.0.1:3000/dir即可看到效果

npm模塊-connect-flash(攜帶一些信息給重定向後的頁面)

var express = require('express')
var flash = require('connect-flash')

var app = express()

app.use(flash())

app.get('/', function(req, res) {
    res.send({message: req.flash()})// 訪問'/a'時會重定向到'/',且頁面顯示出從'/a'帶來的信息,該信息只顯示一次,再次刷新'/'頁面,就不會有了
})

app.get('/a', function(req, res) {
    req.flash('name', 'hvb')// 攜帶信息name
    req.flash('age', 1, 2, 3)// 攜帶信息age
    res.redirect('/')// 重定向到'/'
})
...

客戶端訪問http://127.0.0.1:3000/a即可看到效果

npm模塊-fs-extra(對fs模塊的擴展)

  • 可以實現遞歸刪除文件夾、遞歸創建文件夾
  • 還支持promise方式調用
  • 示例

    var fs = require('fs-extra')
    
    fs.ensureDir('./a/b/c')
    .then(function() {
        console.log('done')
    })
    .catch(function(e) {
        console.log(e.message)
    })

node 模塊 fs-extra

npm模塊-validator(各種驗證)

var validator = require('validator')

console.log(validator.equals('vcxiaohan', 'vcxiaohan'))// 驗證2個字符串是否相等(如果都傳空,也返回true)
console.log(validator.isAlphanumeric('vcxiaohan'))// 驗證是否只包含字母和數字
console.log(validator.isByteLength('vcxiaohan', {min: 4, max: 12}))// 驗證字符串的長度是否在4-12之間
console.log(validator.isURL('http://v35new.faqrobot.org/web/common/index.html#material/menuList'))// 驗證網址
console.log(validator.isMobilePhone('+8618752011111', 'zh-CN'))// 驗證電話(不能驗證固定電話)
console.log(validator.isEmail('[email protected]'))// 驗證郵箱

nodejs的後端字符串驗證器-validator
手機號碼前 +86和86的區別
最強正則表達式

npm模塊-@fnando/password_strength(驗證密碼強度)

var PasswordStrength = require('@fnando/password_strength')

var strength = PasswordStrength.test('vcxiaohan', '10hvb29@')// 分別傳入用戶名和密碼,會檢測用戶名和密碼是否相同,若相同,那麼強度很低
console.log(strength.isWeak())// false
console.log(strength.isGood())// false
console.log(strength.isStrong())// true
console.log(strength.isValid('good'))// true(我們使用這個方法就可以驗證密碼強度是否滿足需要了)
console.log(strength.isGood() == strength.isValid('good'))// false(注意區別)

@fnando/password_strength

驗證重複用戶名

  • 如果要改變索引,最好刪除數據庫且重啓服務(因爲索引已經建立好了),否則有可能出現改變索引不生效的情況
...
// 定義 Schema
var userSchema = new Schema({
    name: {
        type: String,
        unique: true,// 建立唯一索引
        sparse: true,// 建立稀疏索引(允許值爲null的字段同時存在)
    },
})

var User = mongoose.model('User', userSchema)

var app = express()

app.get('/addUser', function(req, res) {
    Blog.create({name: '1234'}).then(function(data) {
        res.send({message: '創建用戶成功'})
    }).catch(function(e) {
        console.log(e.message)
        if(e.message.indexOf('E11000 duplicate key')+1) {// 當設爲唯一索引的字段有重複時,會報出此錯誤
            res.send({message: '用戶名重複'})
        }else {
            res.send({message: '其他錯誤'})
        }
    })
})
...

解決MongoDB唯一索引的空值問題

打印對象到控制檯

var foo = function() {
    console.log(1)
}
console.log(foo)// 打印出[Function],很不明顯
console.log(foo.toString())// 詳細的打印出函數內容

Express 4.x

Express 4.x API 英文手冊
Express 4.x API 中文手冊
Express4.X中的bin/www是作什麼用的?爲什麼沒有後綴?
Express Migrating from 3.x to 4.x
nodejs取參四種方法req.body,req.params,req.param,req.body
What is the difference between res.end() and res.send()?
前端ajax,後端res.redirect重定向

body-parser(請求參數解析)

bodyParser中間件的研究
問一個bodyParser獲取不到對象參數的問題
bodyParser.urlencoded({extended: true})

模板引擎

EJS 模板快速入門

文件上傳 [#f]

multer 中文文檔

文件下載

  • 前端千萬不要使用ajax請求,否則不會激活下載功能
  • 前端調用下載接口
    • <img src="/download/img">這樣服務端返回的圖片可以直接顯示在頁面中
    • <a href="/download/file" target="_blank">點擊下載</a>這樣用戶點擊鏈接後,會直接下載此文件

Content-disposition中Attachment和inline的區別
File not downloading express.js res.download
nodejs+express4.X的文件下載
res.download() not working in my case

格式化時間

  • moment().add()(當前時間向後推遲,可用來設置cookie過期時間)
    這裏寫圖片描述
    Moment.js

https

“HTTPS”安全在哪裏?
HTTPS是如何保證連接安全:每位Web開發者都應知道的

Promise

大白話講解Promise(一)
BlueBird VS ES6 promises
BlueBird 官方文檔

supervisor(保存文件後自動重啓服務)

  • 該模塊主要用在開發環境中,只要你對項目進行更改,再保存後,該模塊就會自動重啓你的項目,省去了手動重啓服務的麻煩
  • cnpm -g install supervisor安裝supervisor到全局
  • supervisor app啓動app.js
  • supervisor -i public app啓動app.js,且忽略public文件夾的監視

使用supervisor提高nodejs調試效率

運維與部署

  • mongod操作

    • 本人自定義的一種結構(僅供參考)
      這裏寫圖片描述
    • 配置文件(適用於linux,根據你的需要配置數據庫路徑、錯誤日誌路徑、開啓的端口號)

      
      # mongod.conf
      
      
      
      # for documentation of all options, see:
      
      
      #   http://docs.mongodb.org/manual/reference/configuration-options/
      
      
      
      # Where and how to store data.
      
      storage:
        dbPath: /home/vc/data/blog/lib
        journal:
          enabled: true
      
      
      # where to write logging data.
      
      systemLog:
        destination: file
        logAppend: true
        path: /home/vc/data/blog/log/mongod.log
      
      
      # network interfaces
      
      net:
        port: 30001
        bindIp: 127.0.0.1
      
    • 配置文件(適用於window,根據你的需要配置數據庫路徑、錯誤日誌路徑、開啓的端口號)

      
      # mongod.conf
      
      
      
      #數據庫路徑
      
      dbpath=E:\data\blog\lib
      
      
      #日誌輸出文件路徑
      
      logpath=E:\data\blog\log\mongod.log
      
      
      #錯誤日誌採用追加模式
      
      logappend=true
      
      
      #啓用日誌文件,默認啓用
      
      journal=true
      
      
      #這個選項可以過濾掉一些無用的日誌信息,若需要調試使用請設置爲false
      
      quiet=true
      
      
      #端口號 默認爲27017
      
      port=30002
    • sudo mongod -f /home/vc/data/blog/mongod.conf &
      根據配置文件啓動(結尾加的&表示在後臺運行此服務,這樣關閉窗口,服務依然運行)
    • sudo netstat -lanp | grep 30001查看mongod在linux上的30001端口是否啓動成功,如下表示已經啓動成功
      這裏寫圖片描述
    • sudo kill 15192殺死mongod進程(以便於我們重新啓動)
    • 如果啓動了多個mongod服務,而我們只需要殺死其中一個,爲了防止殺錯進程,我們可以去相應的mongod.log裏面查看當前的服務對應的pid,再確定是否是需要殺死的進程
      這裏寫圖片描述
  • pm2操作
    • pm2 start app.js千萬不能簡寫成pm2 start app,2個是不一樣的
    • pm2 deploy ecosystem.json production setup初始化項目,如果不setup,下一步會報錯
    • pm2 deploy ecosystem.json production啓動遇到錯誤:bash: pm2: command not found,則需要使用cnpm install -g pm2命令在git服務器上安裝pm2
  • nginx操作
    • 把下載的nginx傳到服務器,進入到configure所在目錄,執行./configure --prefix=/home/vc/nginx --with-http_ssl_module
      • –prefix=/home/vc/nginx爲指定編譯的目錄爲/home/vc/nginx
      • –with-http_ssl_module爲使用ssl模塊,用來提供https服務
    • /home/vc/nginx/conf/nginx.confnginx配置文件位置
    • make && make install安裝nginx
    • sudo /home/vc/nginx/sbin/nginx -t檢測配置文件是否正確
    • sudo /home/vc/nginx/sbin/nginx啓動
    • sudo /home/vc/nginx/sbin/nginx -s stop停止
    • sudo /home/vc/nginx/sbin/nginx -s reload重啓
    • 如遇到nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)nginx: [error] open() "/home/vc/nginx/logs/nginx.pid" failed (2: No such file or directory)
      錯誤,說明你之前安裝的nginx,在沒有正常停止nginx服務的情況下,又重新安裝了一次
      • sudo fuser -n tcp 80查看nginx所佔用的進程,比如:80/tcp: 7811 7812
      • 則使用sudo kill 7811 7812殺死這2個進程,重新啓動nginx即可解決以上問題

How can I make nginx support @font-face formats and allow access-control-allow-origin?
nginx 出現413 Request Entity Too Large問題的解決方法
PM2 介紹
Win10怎麼修改hosts文件 Win10系統hosts修改不了
NodeJS on Nginx: 使用nginx反向代理處理靜態頁面
windows下nginx安裝、配置與使用
ubuntu16.04 nginx安裝
Ubuntu16.04安裝mongodb

ssh免密碼登錄

  • 要特別注意.ssh父目錄的權限問題,如:/home/vc/.ssh,則vc文件夾權限應該是755

解決linux中ssh登錄Warning:Permanently added (RSA) to the list of known hosts
SSH localhost免密碼後依然需要輸入密碼問題的解決
在oschina上添加SSH公鑰

git管理

  • git init --bare sample.gitgit創建一個裸倉庫,裸倉庫沒有工作區
  • 請一定注意新建的倉庫的權限以及所屬者,防止本地提交時報錯,還不知道是權限不足造成的
  • 先要 獲取 git倉庫所有分支,才能繼續其他操作,否則會報錯
  • 有時間我會寫一篇搭建git服務及遠程連接git服務的文章
  • 使用putty連接git服務
  • 使用sourcetree連接git服務(推薦,可視化界面)
    • 需要注意選用OpenSSH,可以使用任何一對公、私鑰進行驗證(本地電腦的或者任何一個服務器用戶的)
    • 將公鑰傳到git服務器的/home/git/.ssh/authorized_keys
    • 在sourcetree上選擇相對應的私鑰
    • 遠程地址爲[email protected]:/home/git/project/sample.git

Git遠程操作詳解
搭建Git服務器

爬蟲

SuperAgent中文使用文檔
用node爬數據遇到的charset編碼轉換問題的解決方案
ajax返回數據成功 卻進入error方法
常見的反爬蟲和應對方法

發送郵件驗證

  • 請注意一定要在本地或服務器上使用Node.js v6+,之前我用pm2在服務器部署nodemailer項目不成功,就是node版本太低了

node.js使用nodemailer發送郵件實例

圖片處理(圖片水印、圖片驗證碼、頭像裁剪)

node圖片處理工具gm的使用:圖片水印、圖片驗證碼、圖片裁剪示例

視頻處理

  • 轉換視頻格式
  • 製作視頻縮略圖
  • 多視頻合成一個
  • 監聽任務進度

    var ffmpeg = require('fluent-ffmpeg')
    
    ffmpeg(...)
    .on('progress', function(progress) {
        console.log(progress.percent)
    })

fluent-ffmpeg/node-fluent-ffmpeg
FFmpeg安裝(windows環境)
Merge Multiple Videos using node fluent ffmpeg

定時任務


  • '* * * * * *'每秒鐘執行一次
  • '*/30 * * * * *'每隔30秒執行一次
  • '0 */5 * * * *''*/5 * * * *'秒數可以省略,所以以上都是每隔5分鐘執行一次
  • '30 */5 * * * *'每隔5分鐘30秒執行一次
  • '0 */5 * * *'每隔5小時執行一次
  • '* 14 * * *'每天的14點開始,每隔1分鐘執行一次,直到15點爲止
  • 以此類推…

Nodejs學習筆記(十二)— 定時任務(node-schedule)

權限控制

node權限控制模塊node_acl的應用

全文檢索

node全文檢索研究

jsonp(解決跨域問題)

  • 跨域環境:本地協議打開html文件,則會使用file://調用http://127.0.0.1:3002的接口,可構成跨域調用
  • index.html(在本地打開)

    ...
    <script>
        $(function() {
            $.ajax({
                url: 'http://127.0.0.1:3002/jsonp',
                dataType: 'jsonp',// 這句不寫的時候,相當於同域名發送xhr,寫的時候,相當於不同域名發送jsonp
            })
            .then(function(data) {
                console.log(data)
            })
        })
    </script>
    ...
  • app.js

    app.all('/jsonp', (req, res, next) => {
        res.jsonp({message: 'jsonp...'})// 既可以響應xhr請求,又可以響應jsonp請求
    })

直播

  • 選用七牛直播雲服務,按照控制檯快速入門配置好直播服務,獲取推流地址和播放地址
  • 使用OBS Studio配置好推流地址,進行推流
  • 使用Video.js配置好播放地址,進行播放

PC端播放rtmp和hls視頻流
videojs播放不了提示 (CODE:4 MEDIA_ERR_SRC_NOT_SUPPORTED) No compatible source was found for this video.

日誌記錄+配置環境

  • (new Image()).src = 'http://xxx/xxx'通過這種方式可以很方便的調用一個接口來實現錯誤日誌的記錄
  • pm2自帶錯誤日誌,運行pm2 logs blog可以展示blog項目的錯誤日誌,該日誌包括編寫錯誤bug等,很方便的可以快速定位到項目運行失敗的問題
  • 開發階段:node app直接運行app.js,運行後因爲沒有配置環境,所以默認是development
  • 生產階段:pm2 deploy ecosystem.json production使用pm2部署服務,部署成功後,環境是production
  • 在不同的環境下加載不同的日誌配置
  • 配置文件目錄
    這裏寫圖片描述
  • default.js

    module.exports = {
        logger: require('tracer').colorConsole(),// 日誌記錄
    }
  • production.js

    module.exports = {
        logger: require('tracer').dailyfile({root:'./logs', allLogsFileName: 'all'}),// 日誌記錄
    }
  • 效果:開發環境日誌會打印到命令面板上,生產環境日誌會寫入文件中
  • 進階:可以添加一個日誌中間件,這樣每次請求信息都可以被記錄下來

baryon/tracer
lorenwest/node-config

單元測試


  • 疑問:爲什麼需要單元測試?平時寫項目,開發環境跑起來,各種流程走一遍,保證不出bug不就行了嗎?
  • 寫成測試用例可以很方便的每次運行,否則比較麻煩

Node.js 單元測試:我要寫測試
測試框架 Mocha 實例教程
代碼覆蓋率工具 Istanbul 入門教程

多線程(child_process/cluster模塊)

發佈了221 篇原創文章 · 獲贊 155 · 訪問量 71萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章