<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

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

          共 8259字,需瀏覽 17分鐘

           ·

          2020-12-22 21:10

          關(guān)注?程序員成長指北,回復(fù)“1

          加入我們一起學(xué)習(xí),天天進(jìn)步



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

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

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

          "scripts": {
          "start": "export NODE_ENV=development && nodemon -w src --exec \"babel-node src\"",
          "build": "babel src --out-dir dist",
          "run-build": "node dist",
          "test": "echo \"Error: no test specified\" && exit 1"
          }
          start指令中我們可以發(fā)現(xiàn)我們用export NODE_ENV=development來定義開發(fā)環(huán)境的環(huán)境變量,由于筆者采用的是mac電腦,所以可以用export來定義一個node環(huán)境變量. 但是在和朋友合作開發(fā)項目時發(fā)現(xiàn)執(zhí)行yarn start后會報錯, 后面看錯誤信息才發(fā)現(xiàn)window下不識別export, 后面筆者發(fā)現(xiàn)window定義環(huán)境變量可以用set, 所以對于window用戶, 如果你使用了以上方法設(shè)置NODE_ENV, 可以采用如下方式:
          "scripts": {
          "start": "set NODE_ENV=development && nodemon -w src --exec \"babel-node src\""
          }

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

          在項目開發(fā)過程中有時候拉取新的node項目代碼后執(zhí)行npm install, 會報如下錯誤:??node-gyp就是在node環(huán)境中使用的生成不同平臺不同編譯器的項目文件, 如果你遇到了相同的問題, 我們可以采用如下方案:

          npm install -g node-gyp

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

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

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

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

          1. 服務(wù)器向客戶端發(fā)送cookie
          2. 瀏覽器將cookie保存(可以在后端設(shè)置expires或者maxAge,以session形式存在)
          3. 每次瀏覽器都會將之前設(shè)置好的cookie發(fā)向服務(wù)器
          在開發(fā)node后臺項目時我們經(jīng)常涉及用戶管理模塊, 這意味我們需要對用戶進(jìn)行登錄態(tài)管理, 在用戶退出時能及時刪除用戶的cookie, 好在koa2自帶了處理cookie的方法, 我們可以通過如下的方式設(shè)置cookie:
          router.post(api.validVip,
          async ctx => {
          ctx.cookies.set('vid', 'xuxiaoxi', { maxAge: 24 * 3600 * 1000 });
          }
          );

          以上我們隨便設(shè)置了一個有效期為1天的cookie, 那如果業(yè)務(wù)有變動, 需要在有效期內(nèi)清空此cookie, 我們該如何處理呢? 解析來給出一個相對可用的解決方案:

          ctx.cookies.set('vid', '', { maxAge: 0 });
          此時客戶端的cookie將在下次請求時自動失效.

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

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

          1. NodeJS HTTP?服務(wù)器集成(或安裝在其上)的socket.io
          2. 在瀏覽器端加載的客戶端庫socket.io-client
          如果我們直接使用koa或者egg, 我們需要將它們內(nèi)部集成的httpsocket.io做兼容, 此時我們可以這樣處理:
          import koa from 'koa';
          import http from 'http';

          const app = new koa();
          const server = http.createServer(app.callback());
          const io = require('socket.io')(server);
          // 正常的業(yè)務(wù)處理
          // io
          io.on('connection', (socket) => {
          console.log('a user connected');
          socket.on('doc load', (msg) => {
          console.log('doc load', msg)
          io.emit('getData', users)
          })
          });

          server.listen(3000, () => {
          // ...
          });

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

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

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

          // 更新最新的包
          npm i xxx@latest

          // 使用包管理工具n
          npm i -g n

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

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

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

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

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

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

          所以我們可以像如下方式這樣來寫一個定時任務(wù):

          let schedule = require('node-schedule');

          let testJob = schedule.scheduleJob('42 * * * *', function(){
          console.log('將在未來的每個時刻的42分時執(zhí)行此代碼, 比如22:42, 23:42');
          });

          7. 在nodejs項目中使用import, export和修飾器@decorator語法

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

          # .babelrc
          {
          "presets": [
          [
          "@babel/preset-env",
          {
          "targets": {
          "node": "current"
          }
          }
          ]
          ],
          "plugins": [
          ["@babel/plugin-proposal-decorators", { "legacy": true }],
          ["@babel/plugin-proposal-class-properties", { "loose" : true }]
          ]
          }

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

          yarn add
          @babel/cli
          @babel/core
          @babel/node
          @babel/plugin-proposal-class-properties
          @babel/plugin-proposal-decorators
          @babel/preset-env
          此時就可以想寫前端項目一樣使用這些新語法特性啦~

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

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

          const fastJson = require('fast-json-stringify')
          const stringify = fastJson({
          title: 'H5 Dooring Schema',
          type: 'object',
          properties: {
          firstName: {
          type: 'string'
          },
          lastName: {
          type: 'string'
          },
          age: {
          description: 'Age in years',
          type: 'integer'
          },
          reg: {
          type: 'string'
          }
          }
          })

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

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

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

          9. nodejs讀取大文件報錯解決方案

          nodejs中 我們可以使用兩種方式來讀寫文件, 如下:

          1. fs.readFile()?一次性將文件讀取進(jìn)內(nèi)存中, 如果文件過大會導(dǎo)致node內(nèi)存不夠而報錯
          2. fs.createReadStream()?以文件流的方式讀取, 此時可以不用擔(dān)心文件的大小
          由以上介紹可知如果我們要讀取的文件可能會很大(比如視頻等大文件), 我們一開始就要使用fs.createReadStream(), 其實如果我們需要對文件進(jìn)行解析, 比如要對簡歷等文件進(jìn)行逐行解析提取關(guān)鍵語料, 我們可以使用nodereadline模塊, 此時我們就可以對文件進(jìn)行逐行讀取并解析, 如下案例:
          const fs = require("fs");
          const path = require("path");
          const readline = require("readline");

          const readlineTask = readline.createInterface({
          input: fs.createReadStream(path.join(__dirname, './h5-dooring')),
          });

          readlineTask.on('line', function(chunk) {
          // 讀取每一行數(shù)據(jù)
          });

          readlineTask.on('close', function() {
          //文件讀取結(jié)束的邏輯
          }

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

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

          import koa from 'koa';
          import compress from 'koa-compress';

          const app = new koa();
          // 開啟gzip
          const options = { threshold: 2048 };
          app.use(compress(options));
          當(dāng)然koa-compress還有很多自定義的配置項, 大家可以感受一下.

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

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

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

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

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

          由于nodejs是單線程的, 但是有時候我們需要支持處理多個進(jìn)程的業(yè)務(wù), 目前nodejs可以通過哦父子進(jìn)程的模式來模擬多進(jìn)程, 我們可以用到child_process, 大致流程如下:??筆者之前分享的很多node實戰(zhàn)項目都采用了child_process, 大致實現(xiàn)過程如下:

          // child.js
          function computedTotal(arr, cb) {
          // 耗時計算任務(wù)
          }

          // 與主進(jìn)程通信
          // 監(jiān)聽主進(jìn)程信號
          process.on('message', (msg) => {
          computedTotal(bigDataArr, (flag) => {
          // 向主進(jìn)程發(fā)送完成信號
          process.send(flag);
          })
          });

          // main.js
          const { fork } = require('child_process');

          app.use(async (ctx, next) => {
          if(ctx.url === '/fetch') {
          const data = ctx.request.body;
          // 通知子進(jìn)程開始執(zhí)行任務(wù),并傳入數(shù)據(jù)
          const res = await createPromisefork('./child.js', data)
          }

          // 創(chuàng)建異步線程
          function createPromisefork(childUrl, data) {
          // 加載子進(jìn)程
          const res = fork(childUrl)
          // 通知子進(jìn)程開始work
          data && res.send(data)
          return new Promise(reslove => {
          res.on('message', f => {
          reslove(f)
          })
          })
          }

          await next()
          })

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

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

          • 輕量級:無需安裝任何圖像處理庫。
          • 跨平臺:Windows下發(fā)布了編譯好的.node文件,下載就能用。
          • 使用簡單:jQuery風(fēng)格的API,簡單可依賴
          我們可以使用它來裁剪, 壓縮圖片, 基本使用如下:
          const images = require("images");

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

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

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

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

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

          這里寫一個簡單的例子:

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

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

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

          ??愛心三連擊

          1.看到這里了就點個在看支持下吧,你的點贊在看是我創(chuàng)作的動力。

          2.關(guān)注公眾號程序員成長指北,回復(fù)「1」加入高級前端交流群!「在這里有好多 前端?開發(fā)者,會討論?前端 Node 知識,互相學(xué)習(xí)」!

          3.也可添加微信【ikoala520】,一起成長。

          “在看轉(zhuǎn)發(fā)”是最大的支持

          瀏覽 46
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  操逼的三级片的视频 | 国产传媒天美果冻精品亚洲一区二区三区直播 | 欧美性爱手机在线免费观看 | 操逼图网址 | 影音先锋色色影院 |