自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

復(fù)盤Node項(xiàng)目中遇到的13+常見問題和解決方案

系統(tǒng)
筆者之前陸陸續(xù)續(xù)接手過幾個(gè)nodejs項(xiàng)目, 也參與過幾個(gè)有點(diǎn)意思的nodejs開源項(xiàng)目, 最近把其中遇到的一些問題和解決方案做一個(gè)梳理, 避免大家繼續(xù)踩坑. 話不多說(shuō)我們開始吧~

筆者之前陸陸續(xù)續(xù)接手過幾個(gè)nodejs項(xiàng)目, 也參與過幾個(gè)有點(diǎn)意思的nodejs開源項(xiàng)目, 最近把其中遇到的一些問題和解決方案做一個(gè)梳理, 避免大家繼續(xù)踩坑. 話不多說(shuō)我們開始吧~

1. window和mac下設(shè)置NODE_ENV變量的問題

我們都知道在前端項(xiàng)目中會(huì)根據(jù)不同的環(huán)境變量來(lái)處理不同的邏輯, 在nodejs中也一樣, 我們需要設(shè)置本地開發(fā)環(huán)境, 測(cè)試環(huán)境, 線上環(huán)境等, 此時(shí)有一直設(shè)置環(huán)境變量的方案是在package.json中的script屬性中設(shè)置, 如下:

  1. "scripts": { 
  2.    "start""export NODE_ENV=development && nodemon -w src --exec \"babel-node src\""
  3.    "build""babel src --out-dir dist"
  4.    "run-build""node dist"
  5.    "test""echo \"Error: no test specified\" && exit 1" 
  6.  } 

從start指令中我們可以發(fā)現(xiàn)我們用export NODE_ENV=development來(lái)定義開發(fā)環(huán)境的環(huán)境變量,由于筆者采用的是mac電腦,所以可以用export來(lái)定義一個(gè)node環(huán)境變量. 但是在和朋友合作開發(fā)項(xiàng)目時(shí)發(fā)現(xiàn)執(zhí)行yarn start后會(huì)報(bào)錯(cuò), 后面看錯(cuò)誤信息才發(fā)現(xiàn)window下不識(shí)別export, 后面筆者發(fā)現(xiàn)window定義環(huán)境變量可以用set, 所以對(duì)于window用戶, 如果你使用了以上方法設(shè)置NODE_ENV, 可以采用如下方式:

  1. "scripts": { 
  2.    "start""set NODE_ENV=development && nodemon -w src --exec \"babel-node src\"" 
  3.  } 

2. 執(zhí)行npm install發(fā)生node-gyp報(bào)錯(cuò)的問題

在項(xiàng)目開發(fā)過程中有時(shí)候拉取新的node項(xiàng)目代碼后執(zhí)行npm install, 會(huì)報(bào)如下錯(cuò)誤:


node-gyp就是在node環(huán)境中使用的生成不同平臺(tái)不同編譯器的項(xiàng)目文件, 如果你遇到了相同的問題, 我們可以采用如下方案:

  1. npm install -g node-gyp 

或者直接刪除package-lock.json或者yarn.lock, 然后重新yarn install或者npm install即可, 筆者親測(cè)有效.

3. node + koa2項(xiàng)目中刪除已設(shè)置的cookie的解決辦法

  • 由于HTTP是無(wú)狀態(tài)協(xié)議,所以需要cookie來(lái)區(qū)分用戶之間的身份。我們可以把cookie作為是一個(gè)由瀏覽器和服務(wù)器共同協(xié)作實(shí)現(xiàn)的規(guī)范。

cookie的處理分為以下3步(基礎(chǔ)且重要的知識(shí)):

  1. 服務(wù)器向客戶端發(fā)送cookie
  2. 瀏覽器將cookie保存(可以在后端設(shè)置expires或者maxAge,以session形式存在)
  3. 每次瀏覽器都會(huì)將之前設(shè)置好的cookie發(fā)向服務(wù)器

在開發(fā)node后臺(tái)項(xiàng)目時(shí)我們經(jīng)常涉及用戶管理模塊, 這意味我們需要對(duì)用戶進(jìn)行登錄態(tài)管理, 在用戶退出時(shí)能及時(shí)刪除用戶的cookie, 好在koa2自帶了處理cookie的方法, 我們可以通過如下的方式設(shè)置cookie:

  1. router.post(api.validVip, 
  2.     async ctx => { 
  3.       ctx.cookies.set('vid''xuxiaoxi', { maxAge: 24 * 3600 * 1000 }); 
  4.     } 
  5. ); 

以上我們隨便設(shè)置了一個(gè)有效期為1天的cookie, 那如果業(yè)務(wù)有變動(dòng), 需要在有效期內(nèi)清空此cookie, 我們?cè)撊绾翁幚砟? 解析來(lái)給出一個(gè)相對(duì)可用的解決方案:

  1. ctx.cookies.set('vid''', { maxAge: 0 }); 

此時(shí)客戶端的cookie將在下次請(qǐng)求時(shí)自動(dòng)失效.

4. socket.io如何與koa/egg配合使用

我們都知道完整的socket.io通信由兩部分組成:

  1. 與NodeJS HTTP 服務(wù)器集成(或安裝在其上)的socket.io
  2. 在瀏覽器端加載的客戶端庫(kù)socket.io-client

如果我們直接使用koa或者egg, 我們需要將它們內(nèi)部集成的http和socket.io做兼容, 此時(shí)我們可以這樣處理:

  1. import koa from 'koa'
  2. import http from 'http'
  3.  
  4. const app = new koa(); 
  5. const server = http.createServer(app.callback()); 
  6. const io = require('socket.io')(server); 
  7. //  正常的業(yè)務(wù)處理 
  8. // io 
  9. io.on('connection', (socket) => { 
  10.     console.log('a user connected'); 
  11.     socket.on('doc load', (msg) => { 
  12.       console.log('doc load', msg) 
  13.       io.emit('getData', users) 
  14.     }) 
  15.   }); 
  16.  
  17. server.listen(3000, () => { 
  18.     // ... 
  19. }); 

通過以上的方式就可以正常的將koa和socket.io 做兼容. 后面我們就可以正常的開發(fā)IM應(yīng)用啦~

5. 由于nodejs第三方模塊依賴特定node版本導(dǎo)致的報(bào)錯(cuò)解決方案

這個(gè)情況筆者之前也遇到過, 主要原因是第三方?jīng)]有和node版本做到很好的向后兼容, 此時(shí)解決方案就是更新此第三方包到最新版本(如果還在維護(hù)的情況), 或者使用node包管理工具(n)切換到適配的node版本, 如下:

  1. // 更新最新的包 
  2. npm i xxx@latest 
  3.  
  4. // 使用包管理工具n 
  5. npm i -g n 

使用n可以很方便的管理node版本, 感興趣可以嘗試一下.

6. nodejs如何創(chuàng)建定時(shí)任務(wù)

定時(shí)任務(wù)在后端開發(fā)中是很常見的功能之一, 其本質(zhì)是根據(jù)時(shí)間規(guī)則,系統(tǒng)在后臺(tái)自動(dòng)執(zhí)行相應(yīng)的任務(wù). 在java, PHP 等后臺(tái)語(yǔ)言中有很豐富的定時(shí)任務(wù)的支持, 對(duì)于nodejs 這個(gè)興起之秀來(lái)說(shuō), 雖然沒有那么成熟的生態(tài), 但是仍然有定時(shí)任務(wù)的模塊, 比如node-schedule.

  • Node Schedule 是用于Node.js的靈活的 cron 類和非 cron 類作業(yè)調(diào)度程序。它允許我們使用可選的重復(fù)規(guī)則來(lái)安排作業(yè)(任意函數(shù))在特定日期執(zhí)行。它在任何給定時(shí)間僅使用一個(gè)計(jì)時(shí)器(而不是每秒鐘/分鐘重新評(píng)估即將到來(lái)的作業(yè))。

一個(gè)很實(shí)用的場(chǎng)景是我們想在每年的雙十一或者雙十二讓node程序自動(dòng)抓取某電商的“商品羊毛”, 并推送到自己的郵箱, 此時(shí)我們就可以用Node Schedule來(lái)開啟一個(gè)定時(shí)任務(wù)來(lái)執(zhí)行我們的業(yè)務(wù)操作, 筆者的很多node應(yīng)用都采用了類似的模式.感興趣可以互相交流一下.

那什么是cron風(fēng)格的Scheduling呢? 其github上給出了一個(gè)簡(jiǎn)單的介紹:


所以我們可以像如下方式這樣來(lái)寫一個(gè)定時(shí)任務(wù):

  1. let schedule = require('node-schedule'); 
  2.  
  3. let testJob = schedule.scheduleJob('42 * * * *'function(){ 
  4.   console.log('將在未來(lái)的每個(gè)時(shí)刻的42分時(shí)執(zhí)行此代碼, 比如22:42, 23:42'); 
  5. }); 

7. 在nodejs項(xiàng)目中使用import, export和修飾器@decorator語(yǔ)法

我們都知道現(xiàn)在nodejs版本已經(jīng)到14.0+版本了, 對(duì)最新的es語(yǔ)法支持的也足夠好, 但是目前仍然有一些語(yǔ)法不支持, 比如es的模塊導(dǎo)入導(dǎo)出(import, export), 裝飾器(@decorator)等, 此時(shí)我們要在node項(xiàng)目中使用這些新特性, 我們就不得不借助工具, 這里筆者采用babel7來(lái)解決上述問題, 如下:

  1. # .babelrc 
  2.   "presets": [ 
  3.     [ 
  4.       "@babel/preset-env"
  5.       { 
  6.         "targets": { 
  7.           "node""current" 
  8.         } 
  9.       } 
  10.     ] 
  11.   ], 
  12.   "plugins": [ 
  13.     ["@babel/plugin-proposal-decorators", { "legacy"true }], 
  14.     ["@babel/plugin-proposal-class-properties", { "loose" : true }] 
  15.   ] 

我們只需要在項(xiàng)目根目錄里新建并寫入如上文件, 并安裝babel對(duì)應(yīng)的模塊即可, 如下:

  1. yarn add  
  2. @babel/cli  
  3. @babel/core  
  4. @babel/node  
  5. @babel/plugin-proposal-class-properties  
  6. @babel/plugin-proposal-decorators  
  7. @babel/preset-env 

此時(shí)就可以想寫前端項(xiàng)目一樣使用這些新語(yǔ)法特性啦~

8. nodejs中優(yōu)雅的處理json文件以及提高json讀寫性能

對(duì)于nodejs優(yōu)化方面其實(shí)有很多要聊的, 這里主要來(lái)說(shuō)說(shuō)json相關(guān)的優(yōu)化方案. 我們需要從2個(gè)方面來(lái)優(yōu)化, 一個(gè)就是json文件的讀寫性能, 此時(shí)我們可以采用fast-json-stringify 來(lái)大大提高json的讀寫速度, 其本質(zhì)是提供了一套json-schema約束, 讓json結(jié)構(gòu)更加有序, 從而提高json的讀取查詢速度. 如下使用方式:

  1. const fastJson = require('fast-json-stringify'
  2. const stringify = fastJson({ 
  3.   title: 'H5 Dooring Schema'
  4.   type: 'object'
  5.   properties: { 
  6.     firstName: { 
  7.       type: 'string' 
  8.     }, 
  9.     lastName: { 
  10.       type: 'string' 
  11.     }, 
  12.     age: { 
  13.       description: 'Age in years'
  14.       type: 'integer' 
  15.     }, 
  16.     reg: { 
  17.       type: 'string' 
  18.     } 
  19.   } 
  20. }) 

比如說(shuō)在H5-Dooring的后臺(tái)中, 有很多需要頻繁讀寫json數(shù)據(jù)的接口, 此時(shí)使用fast-json-stringify對(duì)讀寫性能會(huì)有很大的提升.

另一方面, 我們?cè)趎ode 端操作json, 如果用原生的寫法會(huì)非常麻煩, 此時(shí)我們最好自己對(duì)json讀取進(jìn)行封裝來(lái)提高代碼的簡(jiǎn)約性, 或者我們直接使用第三方庫(kù)jsonfile 來(lái)輕松讀寫json文件, 如下使用案例:

  1. const json = require('jsonfile'
  2. const fileName = 'h5-dooring.json' 
  3. const jsonData = jsonFile.readFileSync(fileName) 

9. nodejs讀取大文件報(bào)錯(cuò)解決方案

在nodejs中 我們可以使用兩種方式來(lái)讀寫文件, 如下:

  1. fs.readFile() 一次性將文件讀取進(jìn)內(nèi)存中, 如果文件過大會(huì)導(dǎo)致node內(nèi)存不夠而報(bào)錯(cuò)
  2. fs.createReadStream() 以文件流的方式讀取, 此時(shí)可以不用擔(dān)心文件的大小

由以上介紹可知如果我們要讀取的文件可能會(huì)很大(比如視頻等大文件), 我們一開始就要使用fs.createReadStream(), 其實(shí)如果我們需要對(duì)文件進(jìn)行解析, 比如要對(duì)簡(jiǎn)歷等文件進(jìn)行逐行解析提取關(guān)鍵語(yǔ)料, 我們可以使用node的readline模塊, 此時(shí)我們就可以對(duì)文件進(jìn)行逐行讀取并解析, 如下案例:

  1. const fs = require("fs"); 
  2. const path = require("path"); 
  3. const readline = require("readline"); 
  4.  
  5. const readlineTask = readline.createInterface({ 
  6.     input: fs.createReadStream(path.join(__dirname, './h5-dooring')), 
  7. }); 
  8.   
  9. readlineTask.on('line'function(chunk) { 
  10.   // 讀取每一行數(shù)據(jù) 
  11. }); 
  12.   
  13. readlineTask.on('close'function() { 
  14.   //文件讀取結(jié)束的邏輯 

10. nodejs如何開啟gzip優(yōu)化網(wǎng)站性能

對(duì)于nodejs開啟gzip 的操作也屬于node性能優(yōu)化的一部分, 經(jīng)過這樣的處理可以讓我們的網(wǎng)站加載更快, 我們可以使用koa的koa-compress中間件來(lái)實(shí)現(xiàn)gzip 功能. 具體實(shí)現(xiàn)如下:

  1. import koa from 'koa'
  2. import compress from 'koa-compress'
  3.  
  4. const app = new koa(); 
  5. // 開啟gzip 
  6. const options = { threshold: 2048 }; 
  7. app.use(compress(options)); 

當(dāng)然koa-compress還有很多自定義的配置項(xiàng), 大家可以感受一下.

11. 解決window和linux系統(tǒng)下路徑分隔符不一致的問題

這個(gè)問題也是系統(tǒng)之間的差異導(dǎo)致的, 也是需要考慮的問題, 我們都知道在linux系統(tǒng)下路徑的分隔符為/, 比如h5-dooring/src/pages, 但是在window下解析的可能就是h5-dooring\\src\\pages這樣的路徑, 此時(shí)我們需要做適配, 不然我們部署到不同系統(tǒng)上報(bào)錯(cuò)是必然的, 所以我們需要全局配置路徑通配符, 筆者的解決方案如下:

  1. import os from 'os' 
  2. const _$ = (os.platform().toLowerCase() === 'win32') ? '\\' : '/'; 

此時(shí)涉及到具體路徑的地方我們用_$ 代替即可, 以上代碼我們用到了node的os模塊, 感興趣的可以研究一下, 我們可以用os模塊處理很多有意思的因?yàn)橄到y(tǒng)差異導(dǎo)致的問題.

12. nodejs如何實(shí)現(xiàn)父子進(jìn)程通信

由于nodejs是單線程的, 但是有時(shí)候我們需要支持處理多個(gè)進(jìn)程的業(yè)務(wù), 目前nodejs可以通過哦父子進(jìn)程的模式來(lái)模擬多進(jìn)程, 我們可以用到child_process, 大致流程如下:


筆者之前分享的很多node實(shí)戰(zhàn)項(xiàng)目都采用了child_process, 大致實(shí)現(xiàn)過程如下:

  1. // child.js 
  2. function computedTotal(arr, cb) { 
  3.     // 耗時(shí)計(jì)算任務(wù) 
  4.  
  5. // 與主進(jìn)程通信 
  6. // 監(jiān)聽主進(jìn)程信號(hào) 
  7. process.on('message', (msg) => { 
  8.   computedTotal(bigDataArr, (flag) => { 
  9.     // 向主進(jìn)程發(fā)送完成信號(hào) 
  10.     process.send(flag); 
  11.   }) 
  12. }); 
  13.  
  14. // main.js 
  15. const { fork } = require('child_process'); 
  16.  
  17. app.use(async (ctx, next) => { 
  18.   if(ctx.url === '/fetch') { 
  19.     const data = ctx.request.body; 
  20.     // 通知子進(jìn)程開始執(zhí)行任務(wù),并傳入數(shù)據(jù) 
  21.     const res = await createPromisefork('./child.js', data) 
  22.   } 
  23.    
  24.   // 創(chuàng)建異步線程 
  25.   function createPromisefork(childUrl, data) { 
  26.     // 加載子進(jìn)程 
  27.     const res = fork(childUrl) 
  28.     // 通知子進(jìn)程開始work 
  29.     data && res.send(data) 
  30.     return new Promise(reslove => { 
  31.         res.on('message', f => { 
  32.             reslove(f) 
  33.         }) 
  34.     })   
  35.   } 
  36.    
  37.   await next() 
  38. }) 

13. node端實(shí)現(xiàn)圖片編輯/壓縮

圖片編輯壓縮在很多場(chǎng)景中用前端的技術(shù)實(shí)現(xiàn)比較常見, 其實(shí)在node端也有很多需要處理的圖片需要, 畢竟客戶端處理的質(zhì)量不好控制, 此時(shí)我們可以采用node-images, 他是一款node 端輕量級(jí)跨平臺(tái)圖像編解碼庫(kù), 其主要特性如下:

  • 輕量級(jí):無(wú)需安裝任何圖像處理庫(kù)。
  • 跨平臺(tái):Windows下發(fā)布了編譯好的.node文件,下載就能用。
  • 使用簡(jiǎn)單:jQuery風(fēng)格的API,簡(jiǎn)單可依賴

我們可以使用它來(lái)裁剪, 壓縮圖片, 基本使用如下:

  1. const images = require("images"); 
  2.  
  3. images("input.jpg")                     //加載圖像文件                             
  4.   .size(400)                          //等比縮放圖像到400像素寬 
  5.      .draw(images("logo.png"), 10, 10)   //在(10,10)處繪制Logo 
  6.        .save("output.jpg", {             //保存圖片到文件,圖片質(zhì)量為50 
  7.         quality : 50                     
  8.        }); 

H5-Dooring 編輯器中哦你也使用了它來(lái)做圖片處理和編輯, 大家也可以更根據(jù)實(shí)際業(yè)務(wù)來(lái)使用.

14. node端解析“命令行指令字符串”實(shí)現(xiàn)線上自動(dòng)打包部署項(xiàng)目

關(guān)于node解析cmd字符串并執(zhí)行命令行指令的方式筆者之前在寫自己實(shí)現(xiàn)一個(gè)自動(dòng)化工作流的文章中也介紹過, 使用了child_process模塊的exec, 具體實(shí)現(xiàn)可以參考文章:

基于NodeJS從零構(gòu)建線上自動(dòng)化打包工作流(H5-Dooring特別版)

這里寫一個(gè)簡(jiǎn)單的例子:

  1. const cmdStr = `cd ${outWorkDir} && yarn build ${fid}` 
  2. // 解析命令行指令, 實(shí)現(xiàn)線上自動(dòng)打包構(gòu)建項(xiàng)目 
  3. exec(cmdStr, function(err, stdout, stderr){ 
  4.   if(err) { 
  5.     console.log('api error:'+stderr); 
  6.     io.emit('htmlWorked', { result: 'error', message: stderr }) 
  7.   } else { 
  8.     // ... 
  9.   } 
  10. }) 

15. 如何解決node應(yīng)用崩潰, 負(fù)載均衡和進(jìn)程管理

解決此問題最好的方式就是采用pm2 或者forever, 其提供了強(qiáng)大的node進(jìn)程管理, 負(fù)載均衡的能力, 并提供了一定程度的應(yīng)用監(jiān)控, 建議在線上環(huán)境使用pm2 來(lái)管理我們的node應(yīng)用.

 

責(zé)任編輯:姜華 來(lái)源: 趣談前端
相關(guān)推薦

2022-03-26 13:31:18

項(xiàng)目node變量

2023-04-12 11:32:33

網(wǎng)絡(luò)

2019-10-08 16:05:19

Redis數(shù)據(jù)庫(kù)系統(tǒng)

2014-01-07 13:54:02

HadoopYARN

2024-07-08 08:45:41

2010-08-31 16:09:04

DIV+CSS

2016-09-27 21:14:53

JavaURL

2023-10-16 16:08:42

工業(yè) 4.0物聯(lián)網(wǎng)邊緣計(jì)算

2022-03-31 10:25:20

物聯(lián)網(wǎng)工業(yè) 4.0大數(shù)據(jù)分析

2010-08-26 12:59:29

marginCSS

2019-04-04 13:11:37

React內(nèi)存泄露memory leak

2010-08-04 10:20:30

Flex組件開發(fā)

2024-05-09 15:00:38

Python編碼開發(fā)

2025-02-19 08:00:00

移動(dòng)端移動(dòng)設(shè)備移動(dòng)開發(fā)

2011-07-26 16:05:19

Oracle數(shù)據(jù)庫(kù)服務(wù)器

2021-08-05 08:32:27

React開發(fā)項(xiàng)目

2024-05-24 10:56:24

PythonURL代碼

2024-10-30 11:00:00

Python列表索引

2010-12-27 11:00:53

Virtualbox

2010-09-01 14:51:12

CSSIEFirefox
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)